Вход Регистрация
Файл: library/XenForo/Model/AdminTemplate.php
Строк: 725
<?php

/**
 * Model for admin templates.
 *
 * @package XenForo_AdminTemplates
 */
class XenForo_Model_AdminTemplate extends XenForo_Model
{
    
/**
     * Returns all admin template basic info in alphabetical order
     *
     * @return array Format: [title] => basic info
     */
    
public function getAllAdminTemplateTitles()
    {
        return 
$this->getAdminTemplateTitles();
    }

    
/**
     * Returns all admin template basic info for templates that match the conditions and fetch options
     *
     * @param array $conditions
     * @param array $fetchOptions
     *
     * @return array Format: [title] => basic info
     */
    
public function getAdminTemplateTitles(array $conditions = array(), array $fetchOptions = array())
    {
        
$whereClause = $this->prepareTemplateConditions($conditions, $fetchOptions);
        
$limitOptions = $this->prepareLimitFetchOptions($fetchOptions);

        return 
$this->fetchAllKeyed($this->limitQueryResults('
            SELECT template.template_id, template.title,
                addon.addon_id, addon.title AS addonTitle
            FROM xf_admin_template AS template
                LEFT JOIN xf_addon AS addon ON (addon.addon_id = template.addon_id)
            WHERE ' 
. $whereClause . '
            ORDER BY CONVERT(template.title USING utf8)
        '
, $limitOptions['limit'], $limitOptions['offset']), 'title');
    }

    
/**
     * Prepares SQL WHERE conditions for a SELECT query
     *
     * @param array $conditions
     * @param array $fetchOptions
     *
     * @return string
     */
    
public function prepareTemplateConditions(array $conditions, array &$fetchOptions)
    {
        
$db = $this->_getDb();
        
$sqlConditions = array();

        if (!empty(
$conditions['title']))
        {
            if (
is_array($conditions['title']))
            {
                
$sqlConditions[] = 'CONVERT(template.title USING utf8) LIKE ' . XenForo_Db::quoteLike($conditions['title'][0], $conditions['title'][1], $db);
            }
            else
            {
                
$sqlConditions[] = 'CONVERT(template.title USING utf8) LIKE ' . XenForo_Db::quoteLike($conditions['title'], 'lr', $db);
            }
        }

        if (!empty(
$conditions['template']))
        {
            
$caseSensitive = (empty($conditions['template_case_sensitive']) ? '' : 'BINARY ');

            if (
is_array($conditions['template']))
            {
                
$sqlConditions[] = 'template.template LIKE ' . $caseSensitive . XenForo_Db::quoteLike($conditions['template'][0], $conditions['phrase_text'][1], $db);
            }
            else
            {
                
$sqlConditions[] = 'template.template LIKE ' . $caseSensitive . XenForo_Db::quoteLike($conditions['template'], 'lr', $db);
            }
        }

        return 
$this->getConditionsForClause($sqlConditions);
    }

    
/**
     * Returns all admin templates in alphabetical title order
     *
     * @return array Format: [title] => (array) template
     */
    
public function getAllAdminTemplates()
    {
        return 
$this->fetchAllKeyed('
            SELECT *
            FROM xf_admin_template
            ORDER BY CONVERT(title USING utf8)
        '
, 'title');
    }

    
/**
     * Returns all admin templates that include the specified admin template
     *
     * @param integer $templateId
     *
     * @return array Format: [] => (array) template
     */
    
public function getDependentAdminTemplates($templateId)
    {
        return 
$this->_getDb()->fetchAll('
            SELECT admin_template.*
            FROM xf_admin_template AS admin_template
            INNER JOIN xf_admin_template_include AS include ON
                (admin_template.template_id = include.source_id)
            WHERE include.target_id = ?
        '
, $templateId);
    }

    
/**
     * Gets the template IDs of any templates that include the source
     * IDs. For example, this would pass in the ID of header
     * and get the ID of the PAGE_CONTAINER.
     *
     * @param integer|array $templateIds One ID as a scalar or an array of many.
     *
     * @return array Array of IDs
     */
    
public function getIncludingTemplateIds($templateIds)
    {
        if (!
is_array($templateIds))
        {
            
$templateIds = array($templateIds);
        }

        if (!
$templateIds)
        {
            return array();
        }

        
$db = $this->_getDb();

        return 
$db->fetchCol('
            SELECT source_id
            FROM xf_admin_template_include
            WHERE target_id IN (' 
. $db->quote($templateIds) . ')
        '
);
    }

    
/**
     * Returns the admin template specified by template_id
     *
     * @param integer Template id
     * @return array Template
     */
    
public function getAdminTemplateById($template_id)
    {
        return 
$this->_getDb()->fetchRow('
            SELECT *
            FROM xf_admin_template
            WHERE template_id = ?
        '
, $template_id);
    }

    
/**
     * Returns the admin template specified by its title
     *
     * @param string Template title
     *
     * @return array Template
     */
    
public function getAdminTemplateByTitle($title)
    {
        return 
$this->_getDb()->fetchRow('
            SELECT *
            FROM xf_admin_template
            WHERE title = ?
        '
, $title);
    }

    public function 
getAdminTemplatesLikeTitle($title, $likeType = 'lr', $limit = 0)
    {
        return 
$this->fetchAllKeyed($this->limitQueryResults('
            SELECT *
            FROM xf_admin_template
            WHERE CONVERT(title USING utf8) LIKE ' 
. XenForo_Db::quoteLike($title, $likeType) . '
            ORDER BY CONVERT(title USING utf8)
        '
, $limit), 'title');
    }

    
/**
     * Returns all the admin templates specified by the array of titles provided
     *
     * @param array $titles
     *
     * @return array Templates
     */
    
public function getAdminTemplatesByTitles(array $titles)
    {
        if (empty(
$titles))
        {
            return array();
        }

        return 
$this->fetchAllKeyed('
            SELECT *
            FROM xf_admin_template
            WHERE title IN(' 
. $this->_getDb()->quote($titles) . ')
            ORDER BY CONVERT(title USING utf8)
        '
, 'title');
    }

    
/**
     * Returns all the admin templates specified by the array of IDs provided
     *
     * @param array $ids
     *
     * @return array Templates
     */
    
public function getAdminTemplatesByIds(array $ids)
    {
        if (empty(
$ids))
        {
            return array();
        }

        return 
$this->fetchAllKeyed('
            SELECT *
            FROM xf_admin_template
            WHERE template_id IN (' 
. $this->_getDb()->quote($ids) . ')
            ORDER BY CONVERT(title USING utf8)
        '
, 'template_id');
    }

    
/**
     * Returns all the admin templates that belong to the specified add-on
     *
     * @param string $addOnId
     *
     * @return array Format: [title] => info
     */
    
public function getAdminTemplatesByAddOn($addOnId)
    {
        return 
$this->fetchAllKeyed('
            SELECT *
            FROM xf_admin_template
            WHERE addon_id = ?
            ORDER BY CONVERT(title USING utf8)
        '
, 'title', $addOnId);
    }

    
/**
     * Gets information on all admin templates that include the named phrase.
     *
     * @param string $phraseTitle
     *
     * @return array Format: [template id] => admin template info
     */
    
public function getAdminTemplatesThatIncludePhrase($phraseTitle)
    {
        return 
$this->fetchAllKeyed('
            SELECT admin_template.*
            FROM xf_admin_template_phrase AS template_phrase
            INNER JOIN xf_admin_template AS admin_template ON
                (admin_template.template_id = template_phrase.template_id)
            WHERE template_phrase.phrase_title = ?
        '
, 'template_id', $phraseTitle);
    }

    
/**
     * Gets all template ID and title pairs that belong to the specified add-on.
     *
     * @param string $addOnId
     *
     * @return array Format: [template id] => title
     */
    
public function getAdminTemplateTitlesByAddOn($addOnId)
    {
        return 
$this->_getDb()->fetchPairs('
            SELECT template_id, title
            FROM xf_admin_template
            WHERE addon_id = ?
        '
, $addOnId);
    }

    
/**
     * Get admin templates whose names contain the search text
     *
     * @param string $searchText
     *
     * @return array
     */
    
public function getAdminTemplatesForAdminQuickSearch($searchText)
    {
        return 
$this->fetchAllKeyed('
            SELECT template_id, title, addon_id
            FROM xf_admin_template
            WHERE CONVERT(title USING utf8) LIKE ' 
. XenForo_Db::quoteLike($searchText, 'lr') . '
        '
, 'template_id');
    }

    
/**
     * Returns the path to the admin template development directory, if it has been configured and exists
     *
     * @return string Path to admin template directory
     */
    
public function getAdminTemplateDevelopmentDirectory()
    {
        
$config = XenForo_Application::get('config');
        if (!
$config->debug || !$config->development->directory)
        {
            return 
'';
        }

        return 
XenForo_Application::getInstance()->getRootDir()
            . 
'/' . $config->development->directory . '/file_output/admin_templates';
    }

    
/**
     * Checks that the admin templates directory has been configured and exists
     *
     * @return boolean
     */
    
public function canImportAdminTemplatesFromDevelopment()
    {
        
$dir = $this->getAdminTemplateDevelopmentDirectory();
        return (
$dir && is_dir($dir));
    }

    
/**
     * Deletes the admin templates that belong to the specified add-on.
     *
     * @param string $addOnId
     */
    
public function deleteAdminTemplatesForAddOn($addOnId)
    {
        
$templateTitles = $this->getAdminTemplateTitlesByAddOn($addOnId);
        
$templateIds = array_keys($templateTitles);

        if (
$templateTitles)
        {
            
$db = $this->_getDb();
            
$quotedIds = $db->quote($templateIds);

            
$db->delete('xf_admin_template', "template_id IN ($quotedIds)");
            
$db->delete('xf_admin_template_compiled', 'title IN (' . $db->quote($templateTitles) . ')');
            
$db->delete('xf_admin_template_include', "source_id IN ($quotedIds)");
            
$db->delete('xf_admin_template_phrase', "template_id IN ($quotedIds)");
            
$db->delete('xf_admin_template_modification_log', "template_id IN ($quotedIds)");
        }

        
XenForo_Template_Compiler_Admin::resetTemplateCache();
    }

    
/**
     * Imports all admin templates from the admin templates directory into the database
     */
    
public function importAdminTemplatesFromDevelopment()
    {
        
$db = $this->_getDb();

        
$templateDir = $this->getAdminTemplateDevelopmentDirectory();
        if (!
$templateDir && !is_dir($templateDir))
        {
            throw new 
XenForo_Exception("Admin template development directory not enabled or doesn't exist");
        }

        
$files = glob("$templateDir/*.html");
        if (!
$files)
        {
            throw new 
XenForo_Exception("Admin template development directory does not have any templates");
        }

        
XenForo_Db::beginTransaction($db);
        
$this->deleteAdminTemplatesForAddOn('XenForo');

        
$titles = array();
        foreach (
$files AS $templateFile)
        {
            
$filename = basename($templateFile);
            if (
preg_match('/^(.+).html$/', $filename, $match))
            {
                
$titles[] = $match[1];
            }
        }

        
$existingTemplates = $this->getAdminTemplatesByTitles($titles);

        foreach (
$files AS $templateFile)
        {
            if (!
is_readable($templateFile))
            {
                throw new 
XenForo_Exception("Template file '$templateFile' not readable");
            }

            
$filename = basename($templateFile);
            if (
preg_match('/^(.+).html$/', $filename, $match))
            {
                
$templateName = $match[1];
                
$data = file_get_contents($templateFile);

                
$dw = XenForo_DataWriter::create('XenForo_DataWriter_AdminTemplate');
                if (isset(
$existingTemplates[$templateName]))
                {
                    
$dw->setExistingData($existingTemplates[$templateName], true);
                }
                
$dw->setOption(XenForo_DataWriter_AdminTemplate::OPTION_DEV_OUTPUT_DIR, '');
                
$dw->setOption(XenForo_DataWriter_AdminTemplate::OPTION_FULL_COMPILE, false);
                
$dw->setOption(XenForo_DataWriter_AdminTemplate::OPTION_TEST_COMPILE, false);
                
$dw->set('title', $templateName);
                
$dw->set('template', $data);
                
$dw->set('addon_id', 'XenForo');

                try
                {
                    
$dw->save();
                }
                catch (
Exception $e)
                {
                    throw new 
XenForo_Exception("Template '$templateName' not imported." . "n" . $e->getMessage() . "n" . $e->getTraceAsString());
                }
            }
        }

        
$this->compileAllParsedAdminTemplates();

        
XenForo_Db::commit($db);
    }

    
/**
     * Imports the add-on admin templates XML.
     *
     * @param SimpleXMLElement $xml XML element pointing to the root of the data
     * @param string $addOnId Add-on to import for
     * @param integer $maxExecution Maximum run time in seconds
     * @param integer $offset Number of elements to skip
     *
     * @return boolean|integer True on completion; false if the XML isn't correct; integer otherwise with new offset value
     */
    
public function importAdminTemplatesAddOnXml(SimpleXMLElement $xml, $addOnId, $maxExecution = 0, $offset = 0)
    {
        
$db = $this->_getDb();

        
XenForo_Db::beginTransaction($db);

        
$startTime = microtime(true);

        if (
$offset == 0)
        {
            
$this->deleteAdminTemplatesForAddOn($addOnId);
        }

        
$templates = XenForo_Helper_DevelopmentXml::fixPhpBug50670($xml->template);

        
$titles = array();
        
$current = 0;
        foreach (
$templates AS $template)
        {
            
$current++;
            if (
$current <= $offset)
            {
                continue;
            }
            
$titles[] = (string)$template['title'];
        }

        
$existingTemplates = $this->getAdminTemplatesByTitles($titles);

        
$current = 0;
        
$restartOffset = false;
        foreach (
$templates AS $template)
        {
            
$current++;
            if (
$current <= $offset)
            {
                continue;
            }

            
$templateName = (string)$template['title'];

            
$dw = XenForo_DataWriter::create('XenForo_DataWriter_AdminTemplate');
            if (isset(
$existingTemplates[$templateName]))
            {
                
$dw->setExistingData($existingTemplates[$templateName], true);
            }
            
$dw->setOption(XenForo_DataWriter_AdminTemplate::OPTION_DEV_OUTPUT_DIR, '');
            
$dw->setOption(XenForo_DataWriter_AdminTemplate::OPTION_FULL_COMPILE, false);
            
$dw->setOption(XenForo_DataWriter_AdminTemplate::OPTION_TEST_COMPILE, false);
            
$dw->set('title', $templateName);
            
$dw->set('template', XenForo_Helper_DevelopmentXml::processSimpleXmlCdata($template));
            
$dw->set('addon_id', $addOnId);
            
$dw->save();

            if (
$maxExecution && (microtime(true) - $startTime) > $maxExecution)
            {
                
$restartOffset = $current;
                break;
            }
        }

        
XenForo_Db::commit($db);

        return (
$restartOffset ? $restartOffset : true);
    }

    
/**
     * Appends the add-on admin template XML to a given DOM element.
     *
     * @param DOMElement $rootNode Node to append all elements to
     * @param string $addOnId Add-on ID to be exported
     */
    
public function appendAdminTemplatesAddOnXml(DOMElement $rootNode, $addOnId)
    {
        
$document = $rootNode->ownerDocument;

        
$templates = $this->getAdminTemplatesByAddOn($addOnId);
        foreach (
$templates AS $template)
        {
            
$templateNode = $document->createElement('template');
            
$templateNode->setAttribute('title', $template['title']);
            
$templateNode->appendChild(XenForo_Helper_DevelopmentXml::createDomCdataSection($document, $template['template']));

            
$rootNode->appendChild($templateNode);
        }
    }

    
/**
     * Gets the admin templates development XML.
     *
     * @return DOMDocument
     */
    
public function getAdminTemplatesDevelopmentXml()
    {
        
$document = new DOMDocument('1.0', 'utf-8');
        
$document->formatOutput = true;
        
$rootNode = $document->createElement('admin_templates');
        
$document->appendChild($rootNode);

        
$this->appendAdminTemplatesAddOnXml($rootNode, 'XenForo');

        return 
$document;
    }

    
/**
     * Updates the last modified date of the admin style.
     */
    
public function updateAdminStyleLastModifiedDate()
    {
        
// make sure when updating, the time is reflected as late as possible
        
$this->_getDataRegistryModel()->set('adminStyleModifiedDate', time());
    }

    public function 
getIdsToCompileByTemplateIds(array $templateIds)
    {
        
$templateIds = array_merge($templateIds, $this->getIncludingTemplateIds($templateIds));

        return 
array_unique($templateIds);
    }

    public function 
reparseTemplate($templateId, $fullCompile = true)
    {
        
$dw = XenForo_DataWriter::create('XenForo_DataWriter_AdminTemplate', XenForo_DataWriter::ERROR_SILENT);
        
$dw->setExistingData($templateId);
        
$dw->reparseTemplate();
        
$dw->setOption(XenForo_DataWriter_AdminTemplate::OPTION_FULL_COMPILE, $fullCompile);
        
$dw->save();
        return 
$dw;
    }

    
/**
     * Reparses all admin templates
     *
     * @param integer $maxExecution The approx maximum length of time this function will run for
     * @param integer $startTemplate The number of the template to start with in that style (not ID, just counter)
     *
     * @return boolean|int True if completed successfully, otherwise int of restart template counter
     */
    
public function reparseAllAdminTemplates($maxExecution = 0, $startTemplate = 0)
    {
        
$db = $this->_getDb();

        
$startTime = microtime(true);
        
$complete = true;
        
$lastTemplate = 0;

        
XenForo_Db::beginTransaction($db);

        
$templates = $this->getAllAdminTemplates();

        foreach (
$templates AS $template)
        {
            
$lastTemplate++;
            if (
$lastTemplate < $startTemplate)
            {
                continue;
            }

            
$this->reparseTemplate($template, false)->getMergedData();

            if (
$maxExecution && (microtime(true) - $startTime) > $maxExecution)
            {
                
$complete = false;
                break;
            }
        }

        
XenForo_Db::commit($db);

        if (
$complete)
        {
            return 
true;
        }
        else
        {
            return 
$lastTemplate + 1;
        }
    }

    
/**
     * Compiles all admin templates
     *
     * @param integer $maxExecution The approx maximum length of time this function will run for
     * @param integer $startTemplate The number of the template to start with in that style (not ID, just counter)
     * @param array $priority List of templates that have priority to be compiled on the first run (eg, cache rebuild and page container)
     *
     * @return boolean|int True if completed successfully, otherwise int of restart template counter
     */
    
public function compileAllParsedAdminTemplates($maxExecution = 0, $startTemplate = 0, array $priority = array())
    {
        
$db = $this->_getDb();

        
$startTime = microtime(true);
        
$complete = true;
        
$lastTemplate = 0;

        
XenForo_Db::beginTransaction($db);

        
$templates = $this->getAllAdminTemplates();

        if (
$startTemplate == 0)
        {
            foreach (
$priority AS $priorityTemplate)
            {
                if (isset(
$templates[$priorityTemplate]))
                {
                    
$template = $templates[$priorityTemplate];
                    
$template = $this->reparseTemplate($template, false)->getMergedData();
                    
$this->compileParsedAdminTemplate(
                        
$template['template_id'], unserialize($template['template_parsed']), $template['title']
                    );
                }
            }
        }

        foreach (
$templates AS $template)
        {
            
$lastTemplate++;
            if (
$lastTemplate < $startTemplate)
            {
                continue;
            }

            
$this->compileParsedAdminTemplate(
                
$template['template_id'], unserialize($template['template_parsed']), $template['title']
            );

            if (
$maxExecution && (microtime(true) - $startTime) > $maxExecution)
            {
                
$complete = false;
                break;
            }
        }

        if (
$complete)
        {
            
$compiledRemove = $db->fetchAll("
                SELECT DISTINCT c.title
                FROM xf_admin_template_compiled AS c
                LEFT JOIN xf_admin_template AS m ON (c.title = m.title)
                WHERE m.title IS NULL
            "
);
            foreach (
$compiledRemove AS $remove)
            {
                
$db->delete('xf_admin_template_compiled',
                    
"title = " . $db->quote($remove['title'])
                );
            }

            
$this->updateAdminStyleLastModifiedDate();
        }

        
XenForo_Db::commit($db);

        if (
$complete)
        {
            return 
true;
        }
        else
        {
            return 
$lastTemplate + 1;
        }
    }

    
/**
     * Compiles the specified, pre-parsed admin templates.
     *
     * @param array $templates
     */
    
public function compileParsedAdminTemplates(array $templates)
    {
        if (!
$templates)
        {
            return;
        }

        
$db = $this->_getDb();
        
XenForo_Db::beginTransaction($db);

        foreach (
$templates AS $template)
        {
            
$this->compileParsedAdminTemplate(
                
$template['template_id'], unserialize($template['template_parsed']), $template['title']
            );
        }

        
XenForo_Db::commit($db);
    }

    
/**
     * Compiles any admin templates that include the specified phrase title.
     *
     * @param string $phraseTitle
     * @param boolean $deferred
     */
    
public function compileAdminTemplatesThatIncludePhrase($phraseTitle, $deferred = true)
    {
        
$templates = $this->getAdminTemplatesThatIncludePhrase($phraseTitle);
        if (
$deferred)
        {
            
XenForo_Application::defer('AdminTemplatePartialCompile', array(
                
'recompileTemplateIds' => array_keys($templates)
            ), 
null, true);
        }
        else
        {
            
$this->compileParsedAdminTemplates($templates);
        }
    }

    
/**
     * Compiles a single admin template
     *
     * @param array Template
     */
    
public function compileParsedAdminTemplate($templateId, array $parsedTemplate, $title)
    {
        
$isCss = (substr($title, -4) == '.css');

        
$languages = $this->getModelFromCache('XenForo_Model_Language')->getAllLanguages();
        
$db = $this->_getDb();

        
$compiler = new XenForo_Template_Compiler_Admin('');

        if (
$isCss)
        {
            
$compiledTemplate = $compiler->compileParsed($parsedTemplate, $title, 0, 0);
            
$db->query('
                INSERT INTO xf_admin_template_compiled
                    (language_id, title, template_compiled)
                VALUES
                    (?, ?, ?)
                ON DUPLICATE KEY UPDATE template_compiled = VALUES(template_compiled)
            '
, array(0, $title, $compiledTemplate));
        }
        else
        {
            foreach (
$languages AS $language)
            {
                
$compiledTemplate = $compiler->compileParsed($parsedTemplate, $title, 0, $language['language_id']);
                
$db->query('
                    INSERT INTO xf_admin_template_compiled
                        (language_id, title, template_compiled)
                    VALUES
                        (?, ?, ?)
                    ON DUPLICATE KEY UPDATE template_compiled = VALUES(template_compiled)
                '
, array($language['language_id'], $title, $compiledTemplate));
            }
        }

        
$ins = array();
        foreach (
$compiler->getIncludedTemplates() AS $includedId)
        {
            
$ins[] = '(' . $db->quote($templateId) . ', ' . $db->quote($includedId) . ')';
            
//TODO: this system doesn't handle includes for templates that don't exist yet
        
}
        
$db->delete('xf_admin_template_include', 'source_id = ' . $db->quote($templateId));
        if (
$ins)
        {
            
$db->query("
                INSERT IGNORE INTO xf_admin_template_include
                    (source_id, target_id)
                VALUES
                    " 
. implode(',', $ins)
            );
        }

        
$ins = array();
        foreach (
$compiler->getIncludedPhrases() AS $includedPhrase)
        {
            if (
strlen($includedPhrase) > 75)
            {
                continue; 
// too long, can't be a valid phrase
            
}

            
$ins[] = '(' . $db->quote($templateId) . ', ' . $db->quote($includedPhrase) . ')';
        }
        
$db->delete('xf_admin_template_phrase', 'template_id = ' . $db->quote($templateId));
        if (
$ins)
        {
            
$db->query('
                INSERT IGNORE INTO xf_admin_template_phrase
                    (template_id, phrase_title)
                VALUES
                    ' 
. implode(',', $ins)
            );
        }
    }
}
Онлайн: 1
Реклама