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

/**
 * Model for add-ons.
 *
 * @package XenForo_AddOns
 */
class XenForo_Model_AddOn extends XenForo_Model
{
    
/**
     * Gets the specified add-on if it exists.
     *
     * @param string $addOnId
     *
     * @return array|false
     */
    
public function getAddOnById($addOnId)
    {
        return 
$this->_getDb()->fetchRow('
            SELECT *
            FROM xf_addon
            WHERE addon_id = ?
        '
$addOnId);
    }

    
/**
     * Gets the version ID/string for the specified add-on.
     *
     * @param string $addOnId
     *
     * @return array|false
     */
    
public function getAddOnVersion($addOnId)
    {
        if (
$addOnId === '')
        {
            return 
false;
        }
        else if (
$addOnId === 'XenForo')
        {
            return array(
                
'version_id' => XenForo_Application::$versionId,
                
'version_string' => XenForo_Application::$version
            
);
        }
        else
        {
            return 
$this->_getDb()->fetchRow('
                SELECT version_id, version_string
                FROM xf_addon
                WHERE addon_id = ?
            '
$addOnId);
        }
    }

    
/**
     * Gets all add-ons in title order.
     *
     * @return array Format: [addon id] => info
     */
    
public function getAllAddOns()
    {
        return 
$this->fetchAllKeyed('
            SELECT *
            FROM xf_addon
            ORDER BY title
        '
'addon_id');
    }

    
/**
     * Get all add-ons for use in an options list. Includes a "XenForo" option
     * before all custom add-ons.
     *
     * @param boolean $includeCustomOption If true, includes an option for "custom" (non-add-on associated)
     * @param boolean $includeForoOption If true, includes an option for "XenForo"
     *
     * @return array Format: [addon id] => title
     */
    
public function getAddOnOptionsList($includeCustomOption true$includeXenForoOption true)
    {
        
$options = array();
        if (
$includeCustomOption)
        {
            
$options[''] = '';
        }

        if (
$includeXenForoOption)
        {
            
$options['XenForo'] = 'XenForo';
        }

        
$addOns $this->getAllAddOns();
        foreach (
$addOns AS $addOn)
        {
            
$options[$addOn['addon_id']] = $addOn['title'];
        }

        return 
$options;
    }

    
/**
     * Conditionally gets the list of add-ons. Used for situations where
     * the add-ons options can only be edited if in debug mode.
     *
     * @param boolean $includeCustomOption If true, includes an option for "custom" (non-add-on associated)
     * @param boolean $includeForoOption If true, includes an option for "XenForo"
     *
     * @return array Format: [addon id] => title
     */
    
public function getAddOnOptionsListIfAvailable($includeCustomOption true$includeXenForoOption true)
    {
        if (!
XenForo_Application::debugMode())
        {
            return array();
        }
        else
        {
            return 
$this->getAddOnOptionsList($includeCustomOption$includeXenForoOption);
        }
    }

    
/**
     * Gets the default add-on ID to be used when not set.
     *
     * @return string
     */
    
public function getDefaultAddOnId()
    {
        if (
XenForo_Application::debugMode())
        {
            return 
XenForo_Application::get('config')->development->default_addon;
        }
        else
        {
            return 
'';
        }
    }

    
/**
     * Installs (or upgrades) an add-on using XML from a file.
     *
     * If an upgrade add-on is given, the XML add-on ID will be checked against if.
     * If matching, an upgrade will be performed. Otherwise, installing existing add-ons will
     * be blocked.
     *
     * @param string $fileName Path to file
     * @param string|false $upgradeAddOnId ID of the add-on to upgrade, if there is one
     *
     * @return bool
     */
    
public function installAddOnXmlFromFile($fileName$upgradeAddOnId false)
    {
        if (!
file_exists($fileName) || !is_readable($fileName))
        {
            throw new 
XenForo_Exception(new XenForo_Phrase('please_enter_valid_file_name_requested_file_not_read'), true);
        }

        try
        {
            
$document = new SimpleXMLElement($fileName0true);
        }
        catch (
Exception $e)
        {
            throw new 
XenForo_Exception(
                new 
XenForo_Phrase('provided_file_was_not_valid_xml_file'), true
            
);
        }

        return 
$this->installAddOnXml($document$upgradeAddOnId);
    }

    
/**
     * Installs add-on XML from a simple XML document.
     *
     * If an upgrade add-on is given, the XML add-on ID will be checked against if.
     * If matching, an upgrade will be performed. Otherwise, installing existing add-ons will
     * be blocked.
     *
     * @param SimpleXMLElement $xml
     * @param string $upgradeAddOnId ID of the add-on to upgrade, if there is one
     *
     * @return bool
     */
    
public function installAddOnXml(SimpleXMLElement $xml$upgradeAddOnId false)
    {
        if (
$xml->getName() != 'addon')
        {
            throw new 
XenForo_Exception(new XenForo_Phrase('provided_file_is_not_an_add_on_xml_file'), true);
        }

        
$addOnData = array(
            
'addon_id' => (string)$xml['addon_id'],
            
'title' => (string)$xml['title'],
            
'version_string' => (string)$xml['version_string'],
            
'version_id' => (int)$xml['version_id'],
            
'install_callback_class' => (string)$xml['install_callback_class'],
            
'install_callback_method' => (string)$xml['install_callback_method'],
            
'uninstall_callback_class' => (string)$xml['uninstall_callback_class'],
            
'uninstall_callback_method' => (string)$xml['uninstall_callback_method'],
            
'url' => (string)$xml['url'],
        );

        
$existingAddOn $this->verifyAddOnIsInstallable($addOnData$upgradeAddOnId);

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

        if (
$addOnData['install_callback_class'] && $addOnData['install_callback_method'])
        {
            
call_user_func(
                array(
$addOnData['install_callback_class'], $addOnData['install_callback_method']),
                
$existingAddOn,
                
$addOnData,
                
$xml
            
);
        }

        
$addOnDw XenForo_DataWriter::create('XenForo_DataWriter_AddOn');
        if (
$existingAddOn)
        {
            
$addOnDw->setExistingData($existingAddOntrue);
        }
        
$addOnDw->bulkSet($addOnData);
        
$addOnDw->save();

        
$this->importAddOnExtraDataFromXml($xml$addOnData['addon_id']);

        
XenForo_Db::commit($db);

        
$this->rebuildAddOnCaches();

        return 
true;
    }

    
/**
     * Verifies that the add-on given is installable (or upgradeable).
     *
     * @param array $addOnData Information about the add-on, from the root XML node
     * @param string|false $upgradeAddOnId Add-on we're trying to upgrade, if applicable
     *
     * @return array If doing an upgrade, returns information about the existing version
     */
    
public function verifyAddOnIsInstallable($addOnData$upgradeAddOnId false)
    {
        
$addOnId $addOnData['addon_id'];

        if (
$addOnId === '')
        {
            throw new 
XenForo_Exception(new XenForo_Phrase('add_on_xml_does_not_specify_valid_add_on_id_and_cannot_be_installed'), true);
        }

        
$existingAddOn $this->getAddOnById($addOnId);
        if (
$existingAddOn)
        {
            if (
$upgradeAddOnId === false)
            {
                throw new 
XenForo_Exception(new XenForo_Phrase('specified_add_on_is_already_installed'), true);
            }
            else if (
$existingAddOn['addon_id'] != $upgradeAddOnId)
            {
                throw new 
XenForo_Exception(new XenForo_Phrase('specified_add_on_does_not_match_add_on_you_chose_to_upgrade'), true);
            }

            if (
$addOnData['version_id'] < $existingAddOn['version_id'])
            {
                throw new 
XenForo_Exception(new XenForo_Phrase('specified_add_on_is_older_than_install_version'), true);
            }
        }

        if (
$upgradeAddOnId !== false && !$existingAddOn)
        {
            throw new 
XenForo_Exception(new XenForo_Phrase('specified_add_on_does_not_match_add_on_you_chose_to_upgrade'), true);
        }

        if (
$addOnData['install_callback_class'] && $addOnData['install_callback_method'])
        {
            if (!
XenForo_Application::autoload($addOnData['install_callback_class'])
                || !
method_exists($addOnData['install_callback_class'], $addOnData['install_callback_method'])
            )
            {
                throw new 
XenForo_Exception(new XenForo_Phrase('files_associated_with_addon_not_found'), true);
            }
        }
        if (
$addOnData['uninstall_callback_class'] && $addOnData['uninstall_callback_method'])
        {
            if (!
XenForo_Application::autoload($addOnData['uninstall_callback_class'])
                || !
method_exists($addOnData['uninstall_callback_class'], $addOnData['uninstall_callback_method'])
            )
            {
                throw new 
XenForo_Exception(new XenForo_Phrase('files_associated_with_addon_not_found'), true);
            }
        }

        return 
$existingAddOn;
    }

    
/**
     * Imports all the add-on associated XML into the DB and rebuilds the
     * caches.
     *
     * @param SimpleXMLElement $xml Root node that contains all of the "data" nodes below
     * @param string $addOnId Add-on to import for
     */
    
public function importAddOnExtraDataFromXml(SimpleXMLElement $xml$addOnId)
    {
        
$this->getModelFromCache('XenForo_Model_AdminNavigation')->importAdminNavigationAddOnXml($xml->admin_navigation$addOnId);

        
$this->getModelFromCache('XenForo_Model_Admin')->importAdminPermissionsAddOnXml($xml->admin_permissions$addOnId);

        
$this->getModelFromCache('XenForo_Model_AdminTemplate')->importAdminTemplatesAddOnXml($xml->admin_templates$addOnId);

        
$this->getModelFromCache('XenForo_Model_AdminTemplateModification')->importModificationAddOnXml($xml->admin_template_modifications$addOnId);

        
$this->getModelFromCache('XenForo_Model_CodeEvent')->importEventsAddOnXml($xml->code_events$addOnId);

        
$this->getModelFromCache('XenForo_Model_CodeEvent')->importEventListenersAddOnXml($xml->code_event_listeners$addOnId);

        
$this->getModelFromCache('XenForo_Model_Cron')->importCronEntriesAddOnXml($xml->cron$addOnId);

        
$this->getModelFromCache('XenForo_Model_EmailTemplate')->importEmailTemplatesAddOnXml($xml->email_templates$addOnIdfalse);

        
$this->getModelFromCache('XenForo_Model_EmailTemplateModification')->importModificationAddOnXml($xml->email_template_modifications$addOnId);

        
$this->getModelFromCache('XenForo_Model_Option')->importOptionsAddOnXml($xml->optiongroups$addOnId);

        
$this->getModelFromCache('XenForo_Model_Permission')->importPermissionsAddOnXml($xml->permissions$addOnId);

        
$this->getModelFromCache('XenForo_Model_Phrase')->importPhrasesAddOnXml($xml->phrases$addOnId);

        
$this->getModelFromCache('XenForo_Model_RoutePrefix')->importPrefixesAddOnXml($xml->route_prefixes$addOnId);

        
$this->getModelFromCache('XenForo_Model_StyleProperty')->importStylePropertyXml($xml->style_properties0$addOnId);
        
$this->getModelFromCache('XenForo_Model_StyleProperty')->importStylePropertyXml($xml->admin_style_properties, -1$addOnId);

        
$this->getModelFromCache('XenForo_Model_Template')->importTemplatesAddOnXml($xml->templates$addOnId);

        
$this->getModelFromCache('XenForo_Model_TemplateModification')->importModificationAddOnXml($xml->public_template_modifications$addOnId);

        
$this->getModelFromCache('XenForo_Model_BbCode')->importBbCodeMediaSitesAddOnXml($xml->bb_code_media_sites$addOnId);
        
$this->getModelFromCache('XenForo_Model_BbCode')->importBbCodesAddOnXml($xml->bb_codes$addOnId);
    }

    
/**
     * Gets the XML data for the specified add-on.
     *
     * @param array $addOn Add-on info
     *
     * @return DOMDocument
     */
    
public function getAddOnXml(array $addOn)
    {
        
$document = new DOMDocument('1.0''utf-8');
        
$document->formatOutput true;

        
$rootNode $document->createElement('addon');
        
$rootNode->setAttribute('addon_id'$addOn['addon_id']);
        
$rootNode->setAttribute('title'$addOn['title']);
        
$rootNode->setAttribute('version_string'$addOn['version_string']);
        
$rootNode->setAttribute('version_id'$addOn['version_id']);
        
$rootNode->setAttribute('url'$addOn['url']);
        
$rootNode->setAttribute('install_callback_class'$addOn['install_callback_class']);
        
$rootNode->setAttribute('install_callback_method'$addOn['install_callback_method']);
        
$rootNode->setAttribute('uninstall_callback_class'$addOn['uninstall_callback_class']);
        
$rootNode->setAttribute('uninstall_callback_method'$addOn['uninstall_callback_method']);
        
$document->appendChild($rootNode);

        
$addOnId $addOn['addon_id'];

        
$dataNode $rootNode->appendChild($document->createElement('admin_navigation'));
        
$this->getModelFromCache('XenForo_Model_AdminNavigation')->appendAdminNavigationAddOnXml($dataNode$addOnId);

        
$dataNode $rootNode->appendChild($document->createElement('admin_permissions'));
        
$this->getModelFromCache('XenForo_Model_Admin')->appendAdminPermissionsAddOnXml($dataNode$addOnId);

        
$dataNode $rootNode->appendChild($document->createElement('admin_style_properties'));
        
$this->getModelFromCache('XenForo_Model_StyleProperty')->appendStylePropertyXml($dataNode, -1$addOnId);

        
$dataNode $rootNode->appendChild($document->createElement('admin_templates'));
        
$this->getModelFromCache('XenForo_Model_AdminTemplate')->appendAdminTemplatesAddOnXml($dataNode$addOnId);

        
$dataNode $rootNode->appendChild($document->createElement('admin_template_modifications'));
        
$this->getModelFromCache('XenForo_Model_AdminTemplateModification')->appendModificationAddOnXml($dataNode$addOnId);

        
$dataNode $rootNode->appendChild($document->createElement('code_events'));
        
$this->getModelFromCache('XenForo_Model_CodeEvent')->appendEventsAddOnXml($dataNode$addOnId);

        
$dataNode $rootNode->appendChild($document->createElement('code_event_listeners'));
        
$this->getModelFromCache('XenForo_Model_CodeEvent')->appendEventListenersAddOnXml($dataNode$addOnId);

        
$dataNode $rootNode->appendChild($document->createElement('cron'));
        
$this->getModelFromCache('XenForo_Model_Cron')->appendCronEntriesAddOnXml($dataNode$addOnId);

        
$dataNode $rootNode->appendChild($document->createElement('email_templates'));
        
$this->getModelFromCache('XenForo_Model_EmailTemplate')->appendEmailTemplatesAddOnXml($dataNode$addOnId);

        
$dataNode $rootNode->appendChild($document->createElement('email_template_modifications'));
        
$this->getModelFromCache('XenForo_Model_EmailTemplateModification')->appendModificationAddOnXml($dataNode$addOnId);

        
$dataNode $rootNode->appendChild($document->createElement('optiongroups'));
        
$this->getModelFromCache('XenForo_Model_Option')->appendOptionsAddOnXml($dataNode$addOnId);

        
$dataNode $rootNode->appendChild($document->createElement('permissions'));
        
$this->getModelFromCache('XenForo_Model_Permission')->appendPermissionsAddOnXml($dataNode$addOnId);

        
$dataNode $rootNode->appendChild($document->createElement('phrases'));
        
$this->getModelFromCache('XenForo_Model_Phrase')->appendPhrasesAddOnXml($dataNode$addOnId);

        
$dataNode $rootNode->appendChild($document->createElement('route_prefixes'));
        
$this->getModelFromCache('XenForo_Model_RoutePrefix')->appendPrefixesAddOnXml($dataNode$addOnId);

        
$dataNode $rootNode->appendChild($document->createElement('style_properties'));
        
$this->getModelFromCache('XenForo_Model_StyleProperty')->appendStylePropertyXml($dataNode0$addOnId);

        
$dataNode $rootNode->appendChild($document->createElement('templates'));
        
$this->getModelFromCache('XenForo_Model_Template')->appendTemplatesAddOnXml($dataNode$addOnId);

        
$dataNode $rootNode->appendChild($document->createElement('public_template_modifications'));
        
$this->getModelFromCache('XenForo_Model_TemplateModification')->appendModificationAddOnXml($dataNode$addOnId);

        
$dataNode $rootNode->appendChild($document->createElement('bb_code_media_sites'));
        
$this->getModelFromCache('XenForo_Model_BbCode')->appendBbCodeMediaSitesAddOnXml($dataNode$addOnId);

        
$dataNode $rootNode->appendChild($document->createElement('bb_codes'));
        
$this->getModelFromCache('XenForo_Model_BbCode')->appendBbCodesAddOnXml($dataNode$addOnId);

        return 
$document;
    }

    
/**
     * Deletes all master data that is associated with an add-on. Customized data
     * (eg, templates) will be left.
     *
     * @param string $addOnId
     */
    
public function deleteAddOnMasterData($addOnId)
    {
        
$this->getModelFromCache('XenForo_Model_AdminNavigation')->deleteAdminNavigationForAddOn($addOnId);

        
$this->getModelFromCache('XenForo_Model_Admin')->deleteAdminPermissionsForAddOn($addOnId);

        
$this->getModelFromCache('XenForo_Model_AdminTemplate')->deleteAdminTemplatesForAddOn($addOnId);

        
$this->getModelFromCache('XenForo_Model_AdminTemplateModification')->deleteModificationsForAddOn($addOnId);

        
$this->getModelFromCache('XenForo_Model_CodeEvent')->deleteEventsForAddOn($addOnId);
        
$this->getModelFromCache('XenForo_Model_CodeEvent')->deleteEventListenersForAddOn($addOnId);

        
$this->getModelFromCache('XenForo_Model_Cron')->deleteCronEntriesForAddOn($addOnId);

        
$this->getModelFromCache('XenForo_Model_EmailTemplate')->deleteEmailTemplatesForAddOn($addOnId);

        
$this->getModelFromCache('XenForo_Model_EmailTemplateModification')->deleteModificationsForAddOn($addOnId);

        
$this->getModelFromCache('XenForo_Model_Option')->deleteOptionsForAddOn($addOnId);

        
$this->getModelFromCache('XenForo_Model_Permission')->deletePermissionsForAddOn($addOnId);

        
$this->getModelFromCache('XenForo_Model_Phrase')->deletePhrasesForAddOn($addOnId);

        
$this->getModelFromCache('XenForo_Model_RoutePrefix')->deletePrefixesForAddOn($addOnId);

        
$this->getModelFromCache('XenForo_Model_StyleProperty')->deleteStylePropertiesAndDefinitionsInStyle(-1$addOnIdtrue);
        
$this->getModelFromCache('XenForo_Model_StyleProperty')->deleteStylePropertiesAndDefinitionsInStyle(0$addOnIdtrue);
        
$this->getModelFromCache('XenForo_Model_StyleProperty')->deleteStylePropertyGroupsInStyle(-1$addOnId);
        
$this->getModelFromCache('XenForo_Model_StyleProperty')->deleteStylePropertyGroupsInStyle(0$addOnId);

        
$this->getModelFromCache('XenForo_Model_Template')->deleteTemplatesForAddOn($addOnId);

        
$this->getModelFromCache('XenForo_Model_TemplateModification')->deleteModificationsForAddOn($addOnId);

        
$this->getModelFromCache('XenForo_Model_BbCode')->deleteBbCodeMediaSitesForAddOn($addOnId);
        
$this->getModelFromCache('XenForo_Model_BbCode')->deleteBbCodesForAddOn($addOnId);
    }

    
/**
     * Rebuilds all caches that are touched by add-ons.
     */
    
public function rebuildAddOnCaches()
    {
        
$this->getModelFromCache('XenForo_Model_CodeEvent')->rebuildEventListenerCache();

        
$this->getModelFromCache('XenForo_Model_Cron')->updateMinimumNextRunTime();

        
$this->getModelFromCache('XenForo_Model_Option')->rebuildOptionCache();

        
$this->getModelFromCache('XenForo_Model_RoutePrefix')->rebuildRoutePrefixCache();

        
$this->getModelFromCache('XenForo_Model_StyleProperty')->rebuildPropertyCacheForAllStyles();

        
$this->getModelFromCache('XenForo_Model_BbCode')->rebuildBbCodeCache();

        
$this->getModelFromCache('XenForo_Model_ContentType')->rebuildContentTypeCache();

        
$this->getModelFromCache('XenForo_Model_AdminSearch')->rebuildSearchTypesCache();

        
$this->getModelFromCache('XenForo_Model_BbCode')->updateBbCodeParseCacheVersion();

        
XenForo_Application::defer('Atomic',
            array(
'simple' => array('Permission''Phrase''TemplateReparse''Template''AdminTemplateReparse''AdminTemplate''EmailTemplateReparse''EmailTemplate')),
            
'addonRebuild'true
        
);
    }

    
/**
     * Rebuilds any caches that need to change after an add-on is enabled/disabled.
     * This is a limited sub-set of all the caches that need to be rebuild when an
     * add-on is disabled. (This makes it easier to switch state.)
     *
     * @param array $addon
     */
    
public function rebuildAddOnCachesAfterActiveSwitch(array $addon)
    {
        
$this->getModelFromCache('XenForo_Model_CodeEvent')->rebuildEventListenerCache();

        
$this->getModelFromCache('XenForo_Model_Cron')->updateMinimumNextRunTime();

        
$this->getModelFromCache('XenForo_Model_RoutePrefix')->rebuildRoutePrefixCache();

        
$this->getModelFromCache('XenForo_Model_BbCode')->rebuildBbCodeCache();

        
$this->getModelFromCache('XenForo_Model_ContentType')->rebuildContentTypeCache();

        
$this->getModelFromCache('XenForo_Model_AdminSearch')->rebuildSearchTypesCache();

        
$this->getModelFromCache('XenForo_Model_BbCode')->updateBbCodeParseCacheVersion();

        
/** @var $modificationModel XenForo_Model_TemplateModification */
        
$modificationModel $this->getModelFromCache('XenForo_Model_TemplateModification');
        
$modificationModel->onAddonActiveSwitch($addon);

        
/** @var $modificationModel XenForo_Model_AdminTemplateModification */
        
$modificationModel $this->getModelFromCache('XenForo_Model_AdminTemplateModification');
        
$modificationModel->onAddonActiveSwitch($addon);

        
/** @var $modificationModel XenForo_Model_EmailTemplateModification */
        
$modificationModel $this->getModelFromCache('XenForo_Model_EmailTemplateModification');
        
$modificationModel->onAddonActiveSwitch($addon);
    }

    
/**
     * Returns true if the application is setup so that add-on development
     * areas can be accessed. (True when in debug mode.)
     *
     * @return boolean
     */
    
public function canAccessAddOnDevelopmentAreas()
    {
        return 
XenForo_Application::debugMode();
    }

    
/**
     * Returns true if the record has the xf_addon table joined, and active = 0
     *
     * @param array $record
     *
     * @return boolean
     */
    
public function isAddOnDisabled(array $record)
    {
        return (
array_key_exists('install_callback_class'$record) && !in_array($record['addon_id'], array('XenForo''')) && empty($record['active']));
    }

    
/**
     * Rebuilds the cache of addon_id -> version_id map of active add-ons.
     *
     * @return array
     */
    
public function rebuildActiveAddOnCache()
    {
        
$addOns $this->_getDb()->fetchPairs("
            SELECT addon_id, version_id
            FROM xf_addon
            WHERE active = 1
        "
);
        
$addOns['XenForo'] = XenForo_Application::$versionId;

        
$this->_getDataRegistryModel()->set('addOns'$addOns);

        return 
$addOns;
    }
}
Онлайн: 2
Реклама