Sindbad~EG File Manager

Current Path : /var/www/html/taet.readinessglobal.com/wp-content/plugins/presto-player/inc/Models/
Upload File :
Current File : /var/www/html/taet.readinessglobal.com/wp-content/plugins/presto-player/inc/Models/Model.php

<?php

namespace PrestoPlayer\Models;

use PrestoPlayer\Support\Utility;
use PrestoPlayer\Support\HasOneRelationship;

/**
 * Model for interfacing with custom database tables
 */
abstract class Model implements ModelInterface
{
    /**
     * Needs a table name
     *
     * @var string
     */
    protected $table = '';

    /**
     * Store model attributes
     *
     * @var object
     */
    protected $attributes;

    /**
     * Model schema
     *
     * @return array
     */
    public function schema()
    {
        return [];
    }

    /**
     * Guarded variables
     *
     * @var array
     */
    protected $guarded = [];

    /**
     * Attributes we can query by
     *
     * @var array
     */
    protected $queryable = [];

    /**
     * Optionally get something from the db
     *
     * @param integer $id
     */
    public function __construct($id = 0)
    {
        $this->attributes = new \stdClass();
        if (!empty($id)) {
            return $this->set($this->get($id)->toObject());
            return $this;
        }
        return $this;
    }

    /**
     * Get attributes properties
     *
     * @param string $property
     * @return mixed
     */
    public function __get($property)
    {
        if (property_exists($this->attributes, $property)) {
            return $this->attributes->$property;
        }
    }

    /**
     * Get attributes properties
     *
     * @param string $property
     * @return mixed
     */
    public function __set($property, $value)
    {
        $this->attributes->$property = $value;
    }

    public function getTableName()
    {
        return $this->table;
    }

    /**
     * Convert to Object
     *
     * @return object
     */
    public function toObject()
    {
        $output = new \stdClass();
        foreach ($this->attributes as $key => $attribute) {
            if (is_a($attribute, Model::class)) {
                $output->$key = $attribute->toObject();
            } else {
                $output->$key = $attribute;
            }
        }
        return $output;
    }

    /**
     * Convert to array
     *
     * @return array
     */
    public function toArray()
    {
        return (array) $this->toObject();
    }

    /**
     * Formats row data based on schema
     *
     * @param object $columns
     * @return object
     */
    public function formatRow($columns)
    {
        $columns = (array) $columns;
        $schema = $this->schema();

        $columns = $this->maybeUnSerializeArgs($columns);

        foreach ($columns as $key => $column) {
            if (!empty($schema[$key]['type'])) {
                settype($columns[$key], $schema[$key]['type']);
            }
        }

        return (object) $columns;
    }

    /**
     * Fetch all models
     *
     * @return array Array of preset objects
     */
    public function all()
    {
        global $wpdb;

        // maybe get only published if we have soft deletes
        $where = !empty($this->schema()['deleted_at']) ? "WHERE (deleted_at IS NULL OR deleted_at = '0000-00-00 00:00:00') " : '';

        $results = $wpdb->get_results(
            "SELECT * FROM {$wpdb->prefix}{$this->table} $where"
        );

        return $this->parseResults($results);
    }

    /**
     * Fetch models from db
     *
     * @param array $args
     * @return Object Array of models with pagination data
     */
    public function fetch($args = [])
    {
        global $wpdb;

        // remove empties for querying
        $args = array_filter(
            wp_parse_args(
                $args,
                [
                    'status' => 'published',
                    'per_page' => 10,
                    'order_by' => [],
                    'page' => 1
                ]
            )
        );

        // get query args
        $query = array_filter($args, function ($key) {
            return in_array($key, ['per_page', 'page', 'status', 'date_query', 'fields', 'order_by']);
        }, ARRAY_FILTER_USE_KEY);

        $where = "WHERE 1=1 ";
        $schema = $this->schema();

        foreach ($args as $attribute => $value) {
            // must be queryable and in schema
            if (!in_array($attribute, $this->queryable) || empty($schema[$attribute])) {
                unset($args[$attribute]);
                continue;
            }

            // attribute schema
            $attr_schema = $schema[$attribute];

            // force type
            settype($value, $attr_schema['type']);

            // sanitize input
            if (!empty($attr_schema['sanitize_callback'])) {
                $value = $attr_schema['sanitize_callback']($value);
            }

            // maybe add quotes
            if (in_array($attr_schema['type'], ['integer', 'number', 'boolean'])) {
                $where .= $wpdb->prepare("AND %1s=%2s ", $attribute, $value);
            } else {
                $where .= $wpdb->prepare("AND %1s='%2s' ", $attribute, $value);
            }
        }

        // soft deletes
        if (!empty($this->schema()['deleted_at'])) {
            $status = !empty($args['status']) ? $args['status'] : '';
            switch ($status) {
                case 'trashed':
                    $where .= "AND (deleted_at IS NOT NULL OR deleted_at != '0000-00-00 00:00:00') ";
                    break;
                default: // default to published
                    $where .= "AND (deleted_at IS NULL OR deleted_at = '0000-00-00 00:00:00') ";
                    break;
            }
        }

        // before and after
        if (!empty($query['date_query'])) {
            // use created at by default
            $query['date_query'] = wp_parse_args($query['date_query'], [
                'field' => 'created_at'
            ]);

            // check for field
            $field = !empty($this->schema()[$query['date_query']['field']]) ? sanitize_text_field($query['date_query']['field']) : null;
            if (!$field) {
                return new \WP_Error('invalid_field', 'Cannot do a date query by ' . sanitize_text_field($query['date_query']['field']));
            }

            // if after
            if (!empty($query['date_query']['after'])) {
                $where .= $wpdb->prepare(
                    "AND %1s >= '%2s' ",
                    sanitize_text_field($field), // i.e. created_at
                    date('Y-m-d H:i:s', strtotime($query['date_query']['after'])) // convert to date
                );
            }
            // before
            if (!empty($query['date_query']['before'])) {
                $where .= $wpdb->prepare(
                    "AND %1s <= '%2s' ",
                    sanitize_text_field($field), // i.e. created_at
                    date('Y-m-d H:i:s', strtotime($query['date_query']['before'])) // convert to date
                );
            }
        }

        $limit = (int) $query['per_page'];
        $offset = (int) ($query['per_page'] * ($query['page'] - 1));
        $pagination = $wpdb->prepare("LIMIT %1s OFFSET %2s ", $limit, $offset);

        $select = "*";
        if (!empty($query['fields']) && 'ids' === $query['fields']) {
            $select = 'id';
        }

        $order_by = '';
        if (!empty($query['order_by'])) {
            $order_by .= "ORDER BY";
            $number = count($query['order_by']);
            $i = 1;
            foreach ($query['order_by'] as $attribute => $direction) {
                $order_by .= $wpdb->prepare(" %1s %2s", $attribute, $direction);
                $order_by .= $i === $number ? '' : ',';
                $i++;
            }
            $order_by .= " ";
        }


        $total = $wpdb->get_var("SELECT count(id) as count FROM {$wpdb->prefix}{$this->table} $where$order_by");
        $results = $wpdb->get_results("SELECT $select FROM {$wpdb->prefix}{$this->table} $where$order_by$pagination");

        return (object)[
            'total' => (int) $total,
            'per_page' => (int) $query['per_page'],
            'page' => (int) $query['page'],
            'data' => 'id' === $select ? $this->parseIds($results) : $this->parseResults($results)
        ];
    }

    /**
     * Find a specific model based on query
     */
    public function findWhere($args = [])
    {
        $args = wp_parse_args($args, ['per_page' => 1]);
        $items = $this->fetch($args);
        return !empty($items->data[0]) ? $items->data[0] : false;
    }

    /**
     * Turns raw sql query results into models
     *
     * @param array $results
     * @return array Array of Models
     */
    protected function parseResults($results)
    {
        if (is_wp_error($results)) {
            return $results;
        }
        if (empty($results)) {
            return [];
        }

        $output = [];
        // return new models for each row
        foreach ($results as $result) {
            $class = get_class($this);
            $output[] = (new $class)->set($result);
        }

        return $output;
    }

    public function parseIds($results)
    {
        if (is_wp_error($results)) {
            return $results;
        }
        if (empty($results)) {
            return [];
        }

        $ids = [];
        foreach ($results as $result) {
            $ids[] = (int) $result->id;
        }
        return $ids;
    }

    /**
     * Gets fresh data from the db
     *
     * @return Model
     */
    public function fresh()
    {
        if ($this->id) {
            return $this->get($this->id);
        }
        return $this;
    }

    /**
     * Get default values set from scheam
     *
     * @return array
     */
    protected function getDefaults()
    {
        $schema = $this->schema();
        $defaults = [];
        foreach ($schema as $attribute => $scheme) {
            if (empty($scheme['default'])) {
                continue;
            }
            $defaults[$attribute] = $scheme['default'];
        }

        return $defaults;
    }

    /**
     * Unset guarded variables
     *
     * @param array $args
     * @return void
     */
    protected function unsetGuarded($args = [])
    {
        // unset guarded
        foreach ($this->guarded as $arg) {
            if ($args[$arg]) {
                unset($args[$arg]);
            }
        }

        // we should never set an ID
        unset($args['id']);

        return $args;
    }

    /**
     * Create a preset
     *
     * @param array $args
     * @return integer
     */
    public function create($args)
    {
        global $wpdb;

        // unset guarded args
        $args = $this->unsetGuarded($args);

        // parse args with default args
        $args = wp_parse_args($args, $this->getDefaults());

        // creation time
        if (!empty($this->schema()['created_at'])) {
            $args['created_at'] = !empty($args['created_at']) ?  $args['created_at'] : current_time('mysql');
        }

        // maybe serialize args
        $args = $this->maybeSerializeArgs($args);

        // insert
        $wpdb->insert($wpdb->prefix . $this->table, $args);

        // set ID in attributes
        $this->attributes->id = $wpdb->insert_id;

        // created action
        do_action("{$this->table}_created", $this);

        // return id
        return $this->attributes->id;
    }

    protected function maybeSerializeArgs($args)
    {
        foreach ($args as $key => $arg) {
            if (!empty($this->schema()[$key])) {
                if ('array' === $this->schema()[$key]['type']) {
                    $args[$key] = maybe_serialize($args[$key]);
                }
            }
        }
        return $args;
    }

    protected function maybeUnSerializeArgs($args)
    {
        foreach ($args as $key => $arg) {
            if (!empty($this->schema()[$key])) {
                if ('array' === $this->schema()[$key]['type']) {
                    $args[$key] = maybe_unserialize($args[$key]);
                }
            }
        }
        return $args;
    }

    /**
     * Attempt to locate a database record using the given
     * column / value pairs. If the model can NOT be found
     * in the database, a record will be inserted with
     * the attributes resulting from merging the first array
     * argument with the optional second array argument.
     *
     * @param array $search Model to search for
     * @param array $create Attributes to create
     * @return Model|\WP_Error
     */
    public function firstOrCreate($search, $create = [])
    {
        if ($this->id) {
            return new \WP_Error('already_created', 'This model has already been created.');
        }

        $models = $this->fetch($search);
        if (is_wp_error($models)) {
            return $models;
        }

        // already created
        if (!empty($models->data[0])) {
            $this->set($models->data[0]->toObject());
            return $this;
        }

        // merge and create
        $merged = array_merge($search, $create);
        $this->create($merged);

        // return fresh instance
        return $this->fresh();
    }

    /**
     * Create and get a model
     *
     * @param array $args
     * @return Model|\WP_Error
     */
    public function createAndGet($args)
    {
        $id = $this->create($args);
        if (is_wp_error($id) || !$id) {
            return $id;
        }
        return $this->fresh();
    }

    /**
     * Attempt to locate a database record using the given
     * column / value pairs and update. If the model can NOT be found
     * in the database, a record will be inserted with
     * the attributes resulting from merging the first array
     * argument with the optional second array argument.
     *
     * @param array $search Model to search for
     * @param array $create Attributes to create
     * @return Model|\WP_Error
     */
    public function getOrCreate($search, $update = [])
    {
        // look for model
        $models = $this->fetch($search);
        if (is_wp_error($models)) {
            return $models;
        }

        // already created, update it
        if (!empty($models->data[0]) && !empty($update)) {
            $this->set($models->data[0]->toObject());
            return $this;
        }

        // merge and create
        $merged = array_merge($search, $update);

        // unset query stuff
        if (!empty($merged['date_query'])) {
            unset($merged['date_query']);
        }

        $this->create($merged);

        // return fresh instance
        return $this->fresh();
    }

    /**
     * Attempt to locate a database record using the given 
     * column / value pairs and update. If the model can NOT be found 
     * in the database, a record will be inserted with 
     * the attributes resulting from merging the first array 
     * argument with the optional second array argument.
     *
     * @param array $search Model to search for
     * @param array $create Attributes to create
     * @return Model|\WP_Error
     */
    public function updateOrCreate($search, $update = [])
    {
        // look for model
        $models = $this->fetch($search);
        if (is_wp_error($models)) {
            return $models;
        }

        // already created, update it
        if (!empty($models->data[0]) && !empty($update)) {
            $this->set($models->data[0]->toObject());
            $this->update($update);
            return $this;
        }

        // merge and create
        $merged = array_merge($search, $update);

        // unset query stuff
        if (!empty($merged['date_query'])) {
            unset($merged['date_query']);
        }

        $this->create($merged);

        // return fresh instance
        return $this->fresh();
    }

    /**
     * Gets a single model
     *
     * @param int $id
     *
     * @return Model Model object
     */
    public function get($id)
    {
        global $wpdb;

        // maybe cache results
        $results = $wpdb->get_row(
            $wpdb->prepare("SELECT * FROM {$wpdb->prefix}{$this->table} WHERE id=%d", $id)
        );

        if (!empty($this->with)) {
            foreach ($this->with as $with) {
                $method_name = Utility::snakeToCamel($with);
                if (method_exists($this, $method_name)) {
                    $relationship_class = $this->$method_name()->getRelationshipClass();
                    $parent_field = $this->$method_name()->getParentField();
                    if ($results->$parent_field) {
                        $results->$parent_field = (new $relationship_class)->get($results->$parent_field);
                    }
                }
            }
        }

        return $this->set($results);
    }

    /**
     * Set attributes
     *
     * @param array $args
     * @return Model
     */
    public function set($args)
    {
        $this->attributes = apply_filters("presto_player/{$this->table}/data", $this->formatRow($args));
        return $this;
    }

    /**
     * Update a model
     *
     * @param array $args
     * @return Model
     */
    public function update($args = [])
    {
        global $wpdb;

        // id is required
        if (empty($this->attributes->id)) {
            return new \WP_Error('missing_parameter', __('You must first create or save this model to update it.', 'presto-player'));
        }

        // unset guarded args
        $args = $this->unsetGuarded($args);

        // parse args with default args
        $args = wp_parse_args($args, $this->getDefaults());

        // update time
        if (!empty($this->schema()['updated_at'])) {
            $args['updated_at'] = !empty($args['updated_at']) ?  $args['updated_at'] : current_time('mysql');
        }

        // maybe serialize
        $args = $this->maybeSerializeArgs($args);

        // make update
        $updated = $wpdb->update($wpdb->prefix . $this->table, $args, ['id' => (int) $this->id]);

        // check for failure
        if (false === $updated) {
            return new \WP_Error('update_failure', __('There was an issue updating the model.', 'presto-player'));
        }

        // set attributes in model
        $this->set($this->get($this->id)->toObject());

        // created action
        do_action("{$this->table}_updated", $this);

        return $this;
    }

    /**
     * Trash model
     *
     * @return Model
     */
    public function trash()
    {
        return $this->update(['deleted_at' => current_time('mysql')]);
    }

    /**
     * Untrash model
     *
     * @return Model
     */
    public function untrash()
    {
        return $this->update(['deleted_at' => null]);
    }

    /**
     * Permanently delete model
     *
     * @return boolean Whether the model was deleted
     */
    public function delete($where = [])
    {
        if (empty($where)) {
            $where = ['id' => (int) $this->id];
        }
        global $wpdb;
        return (bool) $wpdb->delete($wpdb->prefix . $this->table, $where);
    }

    /**
     * Bulk delete by a list of ids
     *
     * @param array $ids
     * @return void
     */
    public function bulkDelete($ids = [])
    {
        global $wpdb;

        // convert to comman separated
        $ids = implode(',', array_map('absint', $ids));

        // delete in bulk
        return (bool) $wpdb->query(
            $wpdb->prepare("DELETE FROM {$wpdb->prefix}{$this->table} WHERE id IN(%1s)", $ids)
        );
    }

    /**
     * Has One Relationship
     */
    public function hasOne($classname, $parent_field)
    {
        return new HasOneRelationship($classname, $this, $parent_field);
    }
}

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists