<?php

if (!class_exists('pdoFetch')) {
    require_once MODX_CORE_PATH . 'components/pdotools/model/pdotools/pdofetch.class.php';
}

class PolylangFetch extends pdoFetch
{
    /** @var Polylang $polylang */
    public $polylang;
    /** @var PolylangTools $tools */
    public $tools;

    /**
     * @param modX $modx
     * @param array $config
     */
    public function __construct(modX &$modx, $config = array())
    {
        parent::__construct($modx, $config);
        $this->polylang = $this->modx->getService('polylang', 'Polylang');
        $this->tools = $this->polylang->getTools();
    }


    /**
     * @return array|bool|string
     */
    public function run()
    {
        $onlyWithLocalization = $this->modx->getOption('onlyWithLocalization', $this->config, false, true);
        $cultureKey = $this->modx->getOption('cultureKey');
        if (
            $onlyWithLocalization &&
            $cultureKey != $this->tools->getOriginalLanguageKey()
        ) {
            $class = $this->modx->getOption('class', $this->config, 'modResource', true);
            $this->setConfig(array_merge($this->config, array(
                'rightJoin' => array(
                    'PolylangContent' => array(
                        'class' => 'PolylangContent',
                        'on' => "`{$class}`.`id` = `PolylangContent`.`content_id` AND `PolylangContent`.`culture_key` = '{$cultureKey}'",
                    )
                ),
            )));
        }
        return parent::run();
    }

    /**
     * PDO replacement for modX::getObject()
     * Returns array instead of object
     *
     * @param $class
     * @param string $where
     * @param array $config
     *
     * @return array
     */
    public function getArray($class, $where = '', $config = array())
    {
        $config['limit'] = 1;
        $rows = $this->getCollection($class, $where, $config);
        $rows = $this->prepareResourceRows($rows, $config);
        return !empty($rows[0]) ? $rows[0] : array();
    }

    /**
     * Prepares fetched rows and process template variables
     *
     * @param array $rows
     *
     * @return array
     */
    public function prepareRows(array $rows = array())
    {
        $rows = parent::prepareRows($rows);
        return $this->prepareResourceRows($rows);
    }

    public function prepareResourceRows(array $rows = array(), $config = array())
    {
        $options = array(
            'class' => $this->config['class'],
            'cultureKey' => $this->modx->getOption('cultureKey'),
            'tvPrefix' => !empty($this->config['tvPrefix']) ? trim($this->config['tvPrefix']) : '',
            'includeTVs' => !empty($this->config['includeTVs']) ? $this->config['includeTVs'] : '',
            'processTVs' => !empty($this->config['processTVs']) ? $this->config['processTVs'] : '',
            'decodeJSON' => !empty($this->config['decodeJSON']) ? $this->config['decodeJSON'] : true,
        );
        foreach ($rows as & $row) {
            if (!isset($row['id']) && !isset($config['id'])) continue;
            $options['content_id'] = $row['id'] ? $row['id'] : $config['id'];
            $row['polylang_override'] = 1;

            $this->tools->prepareResourceData(function ($key, $value, $context) use (&$row) {
                $row['polylang_original_' . $key] = $row[$key];
                $row[$key] = $value;
            }, $options);

        }
        return $rows;
    }

    /**
     * Add selection of template variables to query
     */
    public function addTVs()
    {
        $cultureKey = $this->modx->getOption('cultureKey');
        if ($cultureKey == $this->tools->getOriginalLanguageKey()) {
            parent::addTVs();
        } else {
            $time = microtime(true);

            $includeTVs = $this->config['includeTVs'];
            $tvPrefix = !empty($this->config['tvPrefix']) ?
                trim($this->config['tvPrefix'])
                : '';

            if (!empty($this->config['includeTVList']) && (empty($includeTVs) || is_numeric($includeTVs))) {
                $this->config['includeTVs'] = $includeTVs = $this->config['includeTVList'];
            }
            if (!empty($this->config['sortbyTV'])) {
                $includeTVs .= empty($includeTVs)
                    ? $this->config['sortbyTV']
                    : ',' . $this->config['sortbyTV'];
            }

            if (!empty($includeTVs)) {
                $class = !empty($this->config['joinTVsTo'])
                    ? $this->config['joinTVsTo']
                    : $this->config['class'];
                $subclass = preg_grep('#^' . $class . '#i', $this->modx->classMap['modResource']);
                if (!preg_match('#^modResource$#i', $class) && !count($subclass)) {
                    $this->modx->log(modX::LOG_LEVEL_ERROR,
                        '[pdoTools] Could not join TVs to the class "' . $class . '" that is not a subclass of the "modResource". Try to specify correct class in the "joinTVsTo" parameter.');
                } else {
                    $tvs = array_map('trim', explode(',', $includeTVs));
                    $tvs = array_unique($tvs);
                    $pTvs = $this->tools->getNameTranslatableTVs($tvs);
                    $pDefaultTextTvs = $this->tools->getDefaultTextTvs($cultureKey, $pTvs);
                    //$oTvs = array_diff($tvs, $pTvs);
                    if (!empty($tvs)) {
                        $q = $this->modx->newQuery('modTemplateVar', array('name:IN' => $tvs));
                        $q->select('id,name,type,default_text');
                        $tstart = microtime(true);
                        if ($q->prepare() && $q->stmt->execute()) {
                            $this->modx->queryTime += microtime(true) - $tstart;
                            $this->modx->executedQueries++;
                            $tvs = array();
                            while ($tv = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
                                $name = strtolower($tv['name']);
                                $alias = 'TV' . $name;
                                $defaultText = $tv['default_text'];
                                if ($pTvs && in_array($tv['name'], $pTvs)) {
                                    if ($pDefaultTextTvs && isset($pDefaultTextTvs[$tv['id']])) {
                                        $defaultText = $pDefaultTextTvs[$tv['id']];
                                    }
                                    $this->config['tvsJoin'][$name] = array(
                                        'class' => 'PolylangTv',
                                        'alias' => $alias,
                                        'on' => '`TV' . $name . '`.`content_id` = `' . $class . '`.`id` AND `TV' . $name . '`.`tmplvarid` = ' . $tv['id'] . ' AND `TV' . $name . '`.`culture_key` = "' . $cultureKey . '"',
                                        'tv' => $tv,
                                    );
                                } else {
                                    $this->config['tvsJoin'][$name] = array(
                                        'class' => 'modTemplateVarResource',
                                        'alias' => $alias,
                                        'on' => '`TV' . $name . '`.`contentid` = `' . $class . '`.`id` AND `TV' . $name . '`.`tmplvarid` = ' . $tv['id'],
                                        'tv' => $tv,
                                    );
                                }
                                $this->config['tvsSelect'][$alias] = array('`' . $tvPrefix . $tv['name'] . '`' => 'IFNULL(`' . $alias . '`.`value`, ' . $this->modx->quote($defaultText) . ')');
                                $tvs[] = $tv['name'];
                            }
                            $this->addTime('Included list of tvs: <b>' . implode(', ', $tvs) . '</b>',
                                microtime(true) - $time);
                        }
                    }
                }
            }
        }
    }

}


