Файл: library/XenForo/Model/TemplateModificationAbstract.php
Строк: 412
<?php
abstract class XenForo_Model_TemplateModificationAbstract extends XenForo_Model
{
protected $_modTableName = '';
protected $_logTableName = '';
protected $_dataWriterName = '';
abstract public function onAddonActiveSwitch(array $addon);
public function getModificationById($id)
{
return $this->_getDb()->fetchRow("
SELECT *
FROM {$this->_modTableName}
WHERE modification_id = ?
", $id);
}
public function getModificationByKey($key)
{
return $this->_getDb()->fetchRow("
SELECT *
FROM {$this->_modTableName}
WHERE modification_key = ?
", $key);
}
public function getAllModifications()
{
return $this->fetchAllKeyed("
SELECT *
FROM {$this->_modTableName}
ORDER BY template, execution_order
", 'modification_id');
}
public function getModificationsByKeys(array $keys)
{
if (!$keys)
{
return array();
}
return $this->fetchAllKeyed("
SELECT *
FROM {$this->_modTableName}
WHERE modification_key IN (" . $this->_getDb()->quote($keys) . ")
", 'modification_key');
}
public function groupModificationsByAddon(array $modifications)
{
$results = array();
foreach ($modifications AS $id => $modification)
{
$results[$modification['addon_id']][$id] = $modification;
}
return $results;
}
public function getModificationsForTemplate($title)
{
return $this->fetchAllKeyed("
SELECT *
FROM {$this->_modTableName}
WHERE template = ?
ORDER BY execution_order
", 'modification_id', $title);
}
public function getActiveModificationsForTemplate($title)
{
return $this->fetchAllKeyed("
SELECT modification.*
FROM {$this->_modTableName} AS modification
LEFT JOIN xf_addon AS addon ON (addon.addon_id = modification.addon_id)
WHERE modification.template = ?
AND modification.enabled = 1
AND (addon.active IS NULL OR addon.active = 1)
ORDER BY modification.execution_order
", 'modification_id', $title);
}
public function getModificationLogSummary()
{
return $this->fetchAllKeyed("
SELECT modification_id,
SUM(apply_count) AS ok,
COUNT(IF(status = 'ok' AND apply_count = 0, 1, NULL)) AS not_found,
COUNT(IF(status LIKE 'error%', 1, NULL)) AS error
FROM {$this->_logTableName}
GROUP BY modification_id
", 'modification_id');
}
public function getModificationLogsForModification($modificationId)
{
return $this->fetchAllKeyed("
SELECT *
FROM {$this->_logTableName}
WHERE modification_id = ?
", 'template_id', $modificationId);
}
public function getModificationTemplateTitlesForAddon($addOnId)
{
return $this->_getDb()->fetchCol("
SELECT DISTINCT template
FROM {$this->_modTableName}
WHERE addon_id = ?
", $addOnId);
}
public function updateTemplateModificationLog($templateId, array $modificationStatuses)
{
$inserts = array();
$db = $this->_getDb();
$quotedTemplateId = $db->quote($templateId);
foreach ($modificationStatuses AS $id => $status)
{
if (is_int($status))
{
$inserts[] = '(' . $quotedTemplateId .
', ' . $db->quote($id) .
", 'ok', " . $db->quote($status) . ')';
}
else
{
$inserts[] = '(' . $quotedTemplateId .
', ' . $db->quote($id) .
', ' . $db->quote($status) . ', 0)';
}
}
$db->delete($this->_logTableName, 'template_id = ' . $quotedTemplateId);
if ($inserts)
{
$db->query("
INSERT INTO {$this->_logTableName}
(template_id, modification_id, status, apply_count)
VALUES " . implode(', ', $inserts)
);
}
}
public function applyModificationsToTemplate($title, $template, &$status = array())
{
$modifications = $this->getActiveModificationsForTemplate($title);
return $this->applyTemplateModifications($template, $modifications, $status);
}
public function applyTemplateModifications($template, array $modifications, &$status = array())
{
$status = array();
foreach ($modifications AS $id => $modification)
{
$template = str_replace("rn", "n", $template);
switch ($modification['action'])
{
case 'str_replace':
$modification['find'] = str_replace("rn", "n", $modification['find']);
$modification['replace'] = str_replace('$0', $modification['find'], $modification['replace']);
$status[$id] = substr_count($template, $modification['find']);
$template = str_replace($modification['find'], $modification['replace'], $template);
break;
case 'preg_replace':
case 'callback':
$modification['find'] = str_replace(
array("rn", 'rn'),
array("n", 'n'),
$modification['find']
);
try
{
if (preg_match('/W[sw]*e[sw]*$/', $modification['find']))
{
// can't run a /e regex
$status[$id] = 'error_invalid_regex';
}
else
{
$status[$id] = preg_match_all($modification['find'], $template, $null);
}
}
catch (ErrorException $e)
{
$status[$id] = 'error_invalid_regex';
break;
}
if ($modification['action'] == 'callback')
{
if (XenForo_Application::getConfig()->enableTemplateModificationCallbacks)
{
if (preg_match('/^([a-z0-9_\\]+)::([a-z0-9_]+)$/i', $modification['replace'], $match))
{
if (!class_exists($match[1]) || !is_callable(array($match[1], $match[2])))
{
$status[$id] = 'error_invalid_callback';
}
else
{
try
{
$template = preg_replace_callback(
$modification['find'],
array($match[1], $match[2]),
$template
);
}
catch (Exception $e)
{
$status[$id] = 'error_callback_failed';
XenForo_Error::logException($e, false, 'Template modification callback error: ');
}
}
}
else
{
$status[$id] = 'error_invalid_callback';
}
}
}
else
{
$template = preg_replace($modification['find'], $modification['replace'], $template);
}
break;
default:
$status[$id] = 'error_unknown_action';
}
}
return $template;
}
/**
* Gets all modifications that belong to the specified add-on,
* ordered by their modification keys.
*
* @param string $addOnId
*
* @return array Format: [modification_key] => info
*/
public function getModificationsByAddOnId($addOnId)
{
return $this->fetchAllKeyed("
SELECT *
FROM {$this->_modTableName}
WHERE addon_id = ?
ORDER BY modification_key
", 'modification_key', $addOnId);
}
/**
* Deletes the modifications that belong to the specified add-on.
*
* @param string $addOnId
*/
public function deleteModificationsForAddOn($addOnId)
{
$db = $this->_getDb();
$db->query("
DELETE log FROM {$this->_logTableName} AS log
INNER JOIN {$this->_modTableName} AS modification ON
(log.modification_id = modification.modification_id AND modification.addon_id = ?)
", $addOnId);
$db->delete($this->_modTableName, 'addon_id = ' . $db->quote($addOnId));
}
/**
* Imports the modifications for an add-on.
*
* @param SimpleXMLElement $xml XML element pointing to the root of the event data
* @param string $addOnId Add-on to import for
*/
public function importModificationAddOnXml(SimpleXMLElement $xml, $addOnId)
{
$db = $this->_getDb();
$addonMods = $this->getModificationsByAddOnId($addOnId);
XenForo_Db::beginTransaction($db);
$this->deleteModificationsForAddOn($addOnId);
$xmlEntries = XenForo_Helper_DevelopmentXml::fixPhpBug50670($xml->modification);
$keys = array();
foreach ($xmlEntries AS $entry)
{
$keys[] = (string)$entry['modification_key'];
}
$modifications = $this->getModificationsByKeys($keys);
foreach ($xmlEntries AS $modification)
{
$key = (string)$modification['modification_key'];
$dw = XenForo_DataWriter::create($this->_dataWriterName);
if (isset($modifications[$key]))
{
$dw->setExistingData($modifications[$key]);
}
if (isset($addonMods[$key]))
{
$enabled = $addonMods[$key]['enabled'];
}
else
{
$enabled = (string)$modification['enabled'];
}
$dw->setOption(XenForo_DataWriter_TemplateModificationAbstract::OPTION_FULL_TEMPLATE_COMPILE, false);
$dw->setOption(XenForo_DataWriter_TemplateModificationAbstract::OPTION_REPARSE_TEMPLATE, false);
$dw->bulkSet(array(
'addon_id' => $addOnId,
'template' => (string)$modification['template'],
'modification_key' => $key,
'description' => (string)$modification['description'],
'execution_order' => (int)$modification['execution_order'],
'enabled' => $enabled,
'action' => (string)$modification['action'],
'find' => XenForo_Helper_DevelopmentXml::processSimpleXmlCdata($modification->find[0]),
'replace' => XenForo_Helper_DevelopmentXml::processSimpleXmlCdata($modification->replace[0])
));
$this->_addExtraToAddonXmlImportDw($dw, $modification);
$dw->save();
}
XenForo_Db::commit($db);
}
protected function _addExtraToAddonXmlImportDw(XenForo_DataWriter_TemplateModificationAbstract $dw, SimpleXMLElement $modification)
{
}
/**
* Appends the add-on template modification XML to a given DOM element.
*
* @param DOMElement $rootNode Node to append all prefix elements to
* @param string $addOnId Add-on ID to be exported
*/
public function appendModificationAddOnXml(DOMElement $rootNode, $addOnId)
{
$modifications = $this->getModificationsByAddOnId($addOnId);
$document = $rootNode->ownerDocument;
foreach ($modifications AS $modification)
{
$modNode = $document->createElement('modification');
$modNode->setAttribute('template', $modification['template']);
$modNode->setAttribute('modification_key', $modification['modification_key']);
$modNode->setAttribute('description', $modification['description']);
$modNode->setAttribute('execution_order', $modification['execution_order']);
$modNode->setAttribute('enabled', $modification['enabled']);
$modNode->setAttribute('action', $modification['action']);
$findNode = $document->createElement('find');
$findNode->appendChild(XenForo_Helper_DevelopmentXml::createDomCdataSection($document, $modification['find']));
$modNode->appendChild($findNode);
$replaceNode = $document->createElement('replace');
$replaceNode->appendChild(XenForo_Helper_DevelopmentXml::createDomCdataSection($document, $modification['replace']));
$modNode->appendChild($replaceNode);
$this->_modifyAddOnXmlNode($modNode, $modification);
$rootNode->appendChild($modNode);
}
}
protected function _modifyAddOnXmlNode(DOMElement &$modNode, array $modification)
{
}
public function canEditModification(array $modification)
{
return XenForo_Application::debugMode()
|| empty($modification['addon_id'])
|| empty($modification['modification_id']);
}
}