<?php

namespace MatthiasWeb\RealMediaLibrary\folder;

use MatthiasWeb\RealMediaLibrary\api\IFolder;
use MatthiasWeb\RealMediaLibrary\attachment\Permissions;
use MatthiasWeb\RealMediaLibrary\base\UtilsProvider;
// @codeCoverageIgnoreStart
\defined('ABSPATH') or die('No script kiddies please!');
// Avoid direct file request
// @codeCoverageIgnoreEnd
/**
 * Abstract base class for folders. It handles the available fields and getters / setters.
 * The class is completely documented in the implemented interface.
 * @internal
 */
abstract class BaseFolder implements IFolder
{
    use UtilsProvider;
    protected $id;
    protected $parent;
    protected $name;
    protected $cnt;
    protected $order;
    protected $slug;
    protected $absolutePath;
    protected $row;
    protected $children;
    protected $visible = \true;
    protected $restrictions = [];
    protected $restrictionsCount = 0;
    protected $systemReservedFolders = ['/', '..', '.'];
    protected $contentCustomOrder;
    protected $owner;
    // Documented in IFolder
    public function anyParentHas($column, $value = null, $valueFormat = '%s', $includeSelf = \false, $until = null)
    {
        global $wpdb;
        // phpcs:disable WordPress.DB
        $sql = \wp_rml_create_all_parents_sql($this, $includeSelf, $until, ['fields' => "rmldata.id, rmldata.{$column}", 'afterWhere' => $wpdb->prepare("AND rmldata.{$column} = {$valueFormat}", $value)]);
        return $sql === \false ? [] : $wpdb->get_results($sql, ARRAY_A);
        // phpcs:enable WordPress.DB
    }
    // Documented in IFolder
    public function anyParentHasMetadata($meta_key, $meta_value = null, $valueFormat = '%s', $includeSelf = \false, $until = null)
    {
        global $wpdb;
        // phpcs:disable WordPress.DB
        $sql = \wp_rml_create_all_parents_sql($this, $includeSelf, $until, ['fields' => 'rmlmeta.meta_id AS id, rmlmeta.realmedialibrary_id AS folderId, rmlmeta.meta_value AS value', 'join' => $wpdb->prepare('JOIN ' . $this->getTableName('meta') . ' rmlmeta ON rmlmeta.realmedialibrary_id = rmldata.id AND rmlmeta.meta_key = %s', $meta_key), 'afterWhere' => $meta_value === null ? "AND TRIM(IFNULL(rmlmeta.meta_value,'')) <> ''" : $wpdb->prepare("AND rmlmeta.meta_value = {$valueFormat}", $meta_value)]);
        return $sql === \false ? [] : $wpdb->get_results($sql, ARRAY_A);
        // phpcs:enable WordPress.DB
    }
    // Documented in IFolder
    public function anyChildrenHas($column, $value = null, $valueFormat = '%s', $includeSelf = \false)
    {
        global $wpdb;
        // phpcs:disable WordPress.DB
        $sql = \wp_rml_create_all_children_sql($this, $includeSelf, ['fields' => "rmldata.id, rmldata.{$column}", 'afterWhere' => $wpdb->prepare("AND rmldata.{$column} = {$valueFormat}", $value)]);
        return $sql === \false ? [] : $wpdb->get_results($sql, ARRAY_A);
        // phpcs:enable WordPress.DB
    }
    // Documented in IFolder
    public function anyChildrenHasMetadata($meta_key, $meta_value = null, $valueFormat = '%s', $includeSelf = \false)
    {
        // phpcs:disable WordPress.DB
        global $wpdb;
        $sql = \wp_rml_create_all_children_sql($this, $includeSelf, ['fields' => 'rmlmeta.meta_id AS id, rmlmeta.realmedialibrary_id AS folderId, rmlmeta.meta_value AS value', 'join' => $wpdb->prepare('JOIN ' . $this->getTableName('meta') . ' rmlmeta ON rmlmeta.realmedialibrary_id = rmldata.id AND rmlmeta.meta_key = %s', $meta_key), 'afterWhere' => $meta_value === null ? "AND TRIM(IFNULL(rmlmeta.meta_value,'')) <> ''" : $wpdb->prepare("AND rmlmeta.meta_value = {$valueFormat}", $meta_value)]);
        return $sql === \false ? [] : $wpdb->get_results($sql, ARRAY_A);
        // phpcs:enable WordPress.DB
    }
    // Documented in IFolder
    public function hasChildren($name, $returnObject = \false)
    {
        foreach ($this->getChildren() as $value) {
            if ($value->getName() === $name) {
                return $returnObject === \true ? $value : \true;
            }
        }
        return \false;
    }
    // Documented in IFolder
    public function getId()
    {
        return $this->id;
    }
    // Documented in IFolder
    public function getParent()
    {
        return $this->parent;
    }
    // Documented in IFolder
    public function getAllParents($until = null, $colIdx = 0)
    {
        global $wpdb;
        $sql = \wp_rml_create_all_parents_sql($this, \false, $until);
        // phpcs:disable WordPress.DB.PreparedSQL
        return $sql === \false ? [] : $wpdb->get_col($sql, $colIdx);
        // phpcs:enable WordPress.DB.PreparedSQL
    }
    // Documented in IFolder
    public function getName($htmlentities = \false)
    {
        return $htmlentities ? \htmlentities($this->name) : $this->name;
    }
    // Documented in IFolder
    public function getSlug($force = \false, $fromSetName = \false)
    {
        if ($this->slug === '' || $force) {
            $slugBefore = $this->slug;
            $this->slug = \_wp_rml_sanitize($this->name, $this->id > -1, $this->id);
            // Update in database
            if ($this->id > -1) {
                if ($slugBefore !== $this->slug) {
                    global $wpdb;
                    $table_name = $this->getTableName();
                    // phpcs:disable WordPress.DB.PreparedSQL
                    $wpdb->query($wpdb->prepare("UPDATE {$table_name} SET slug=%s WHERE id = %d", $this->slug, $this->id));
                    // phpcs:enable WordPress.DB.PreparedSQL
                    $this->debug("Successfully changed slug '{$this->slug}' in database", __METHOD__);
                }
                if (!$fromSetName) {
                    $this->updateThisAndChildrensAbsolutePath();
                }
            }
        }
        return $this->slug;
    }
    // Documented in IFolder
    public function getPath($implode = '/', $map = 'htmlentities', $filter = null)
    {
        $return = [];
        // Add initial folder
        if (!isset($filter) || \call_user_func_array($filter, [$this])) {
            $initial = $this->name;
            // Allow custom map function
            if ($map !== null) {
                if ($map === 'htmlentities') {
                    $initial = \htmlentities($initial);
                } else {
                    $initial = \call_user_func_array($map, [$initial, $this]);
                }
            }
            $return[] = $initial;
        }
        $folder = $this;
        while (\true) {
            $f = \wp_rml_get_object_by_id($folder->parent);
            if ($f !== null && $f->getType() !== RML_TYPE_ROOT) {
                $folder = $f;
                if (isset($filter) && !\call_user_func_array($filter, [$folder])) {
                    continue;
                }
                $name = $folder->name;
                // Allow custom map function
                if ($map !== null) {
                    if ($map === 'htmlentities') {
                        $name = \htmlentities($name);
                    } else {
                        $name = \call_user_func_array($map, [$name, $f]);
                    }
                }
                $return[] = $name;
            } else {
                break;
            }
        }
        return \implode($implode, \array_reverse($return));
    }
    // Documented in IFolder
    public function getOwner()
    {
        return $this->owner;
    }
    // Documented in IFolder
    public function getAbsolutePath($force = \false, $fromSetName = \false)
    {
        if ($this->absolutePath === '' || $force) {
            $pathBefore = $this->absolutePath;
            $return = [$this->getSlug(\true, \true)];
            $folder = $this;
            while (\true) {
                $f = \wp_rml_get_object_by_id($folder->getParent());
                if (\is_rml_folder($f) && $f->getId() !== -1) {
                    $folder = $f;
                    $return[] = $folder->getSlug();
                } else {
                    break;
                }
            }
            $this->absolutePath = \implode('/', \array_reverse($return));
            // Update in database
            if ($this->id > -1) {
                if ($pathBefore !== $this->absolutePath) {
                    global $wpdb;
                    $table_name = $this->getTableName();
                    // phpcs:disable WordPress.DB.PreparedSQL
                    $wpdb->query($wpdb->prepare("UPDATE {$table_name} SET absolute=%s WHERE id = %d", $this->absolutePath, $this->id));
                    // phpcs:enable WordPress.DB.PreparedSQL
                    $this->debug("Successfully changed absolute path '{$this->absolutePath}' in database", __METHOD__);
                }
                if (!$fromSetName) {
                    $this->updateThisAndChildrensAbsolutePath();
                }
            }
        }
        return $this->absolutePath;
    }
    // Documented in IFolder
    public function getCnt($forceReload = \false)
    {
        if ($this->cnt === null || $forceReload) {
            $query = new \MatthiasWeb\RealMediaLibrary\folder\QueryCount(
                /**
                 * Modify the query arguments to count items within a folder.
                 *
                 * @param {array} $query The query with post_status, post_type and rml_folder
                 * @hook RML/Folder/QueryCountArgs
                 * @return {array} The query
                 */
                \apply_filters('RML/Folder/QueryCountArgs', ['post_status' => 'inherit', 'post_type' => 'attachment', 'rml_folder' => $this->id])
            );
            if (isset($query->posts[0])) {
                $this->cnt = $query->posts[0];
            } else {
                $this->cnt = 0;
            }
        }
        return $this->cnt;
    }
    // Documented in IFolder
    public function getChildren()
    {
        return $this->children;
    }
    // Documented in IFolder
    public function getOrder()
    {
        return $this->order;
    }
    // Documented in IFolder
    public function getRestrictions()
    {
        if (!$this->isVisible()) {
            return Permissions::RESTRICTION_ALL;
        }
        return $this->restrictions;
    }
    // Documented in IFolder
    public function getRestrictionsCount()
    {
        if (!$this->isVisible()) {
            return \count(Permissions::RESTRICTION_ALL);
        }
        return $this->restrictionsCount;
    }
    // Documented in IFolder
    public function getPlain($deep = \false)
    {
        if (!$this->isVisible()) {
            return null;
        }
        $result = ['id' => $this->getId(), 'type' => $this->getType(), 'parent' => $this->getParent(), 'name' => $this->getName(), 'order' => $this->getOrder(), 'restrictions' => $this->getRestrictions(), 'slug' => $this->getSlug(), 'absolutePath' => $this->getAbsolutePath(), 'cnt' => $this->getCnt(), 'contentCustomOrder' => (int) $this->getContentCustomOrder(), 'forceCustomOrder' => $this->forceContentCustomOrder(), 'lastOrderBy' => $this->getRowData('lastOrderBy'), 'orderAutomatically' => $this->getRowData('orderAutomatically'), 'lastSubOrderBy' => $this->getRowData('lastSubOrderBy'), 'subOrderAutomatically' => $this->getRowData('subOrderAutomatically')];
        // Add the children
        if ($deep) {
            $children = [];
            foreach ($this->getChildren() as $child) {
                $plain = $child->getPlain($deep);
                if ($plain !== null) {
                    $children[] = $plain;
                }
            }
            $result['children'] = $children;
        }
        return $result;
    }
    // Documented in IFolder
    public function setRestrictions($restrictions = [])
    {
        $this->debug($restrictions, __METHOD__);
        $this->restrictions = $restrictions;
        $this->restrictionsCount = \count($this->restrictions);
        // Save in Database
        if ($this->id > -1) {
            global $wpdb;
            $table_name = $this->getTableName();
            // phpcs:disable WordPress.DB.PreparedSQL
            $wpdb->query($wpdb->prepare("UPDATE {$table_name} SET restrictions=%s WHERE id = %d", \implode(',', $restrictions), $this->id));
            // phpcs:enable WordPress.DB.PreparedSQL
            $this->debug('Successfully saved restrictions in database', __METHOD__);
        }
    }
    // Documented in IFolder
    public function is($folder_type)
    {
        return $this->getType() === $folder_type;
    }
    // Documented in IFolder
    public function isVisible()
    {
        return $this->visible;
    }
    // Documented in IFolder
    public function isRestrictFor($restriction)
    {
        if (!$this->isVisible()) {
            // When it is not visible, restrict the complete access
            return \true;
        }
        return \in_array($restriction, $this->restrictions, \true) || \in_array($restriction . '>', $this->restrictions, \true);
    }
}
