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

/**
* Data writer for email templates.
*
* @package XenForo_EmailTemplate
*/
class XenForo_DataWriter_EmailTemplate extends XenForo_DataWriter
{
    
/**
     * Option that takes the path to the development template output directory.
     * If not specified, output will not be written. Defaults determined based
     * on config settings.
     *
     * @var string
     */
    
const OPTION_DEV_OUTPUT_DIR 'devOutputDir';

    
/**
     * Option that controls whether a full compile is performed when the template
     * is modified. If false, the template is only parsed into segments. Defaults
     * to true, but should be set to false for bulk imports; compilation should
     * happen in the second pass.
     *
     * @var string
     */
    
const OPTION_FULL_COMPILE 'fullCompile';

    
/**
     * Option that controls whether a test compile will be performed when setting
     * the value of a template. If false, the error will only be detected when a
     * full compile is done.
     *
     * Note that this does not prevent the template from being parsed. That will
     * always happen.
     *
     * @var string
     */
    
const OPTION_TEST_COMPILE 'testCompile';

    
/**
     * Title of the phrase that will be created when a call to set the
     * existing data fails (when the data doesn't exist).
     *
     * @var string
     */
    
protected $_existingDataErrorPhrase 'requested_email_template_not_found';

    
/**
     * If an array, updates the template modification status list
     *
     * @var array|null
     */
    
protected $_modificationStatuses null;

    
/**
    * Gets the fields that are defined for the table. See parent for explanation.
    *
    * @return array
    */
    
protected function _getFields()
    {
        return array(
            
'xf_email_template' => array(
                
'template_id'      => array('type' => self::TYPE_UINT,   'autoIncrement' => true),
                
'title'            => array('type' => self::TYPE_STRING'required' => true'maxLength' => 50,
                        
'verification' => array('$this''_verifyTitle'), 'requiredError' => 'please_enter_valid_title'
                
),
                
'custom'           => array('type' => self::TYPE_BOOLEAN'default' => 1),
                
'subject'          => array('type' => self::TYPE_STRING'verification' => array('$this''_verifySubject'), 'noTrim' => true),
                
'subject_parsed'   => array('type' => self::TYPE_BINARY),
                
'body_text'        => array('type' => self::TYPE_STRING'verification' => array('$this''_verifyBodyText'), 'noTrim' => true),
                
'body_text_parsed' => array('type' => self::TYPE_BINARY),
                
'body_html'        => array('type' => self::TYPE_STRING'verification' => array('$this''_verifyBodyHtml'), 'noTrim' => true),
                
'body_html_parsed' => array('type' => self::TYPE_BINARY),
                
'addon_id'         => array('type' => self::TYPE_STRING'maxLength' => 25'default' => '')
            )
        );
    }

    
/**
    * Gets the actual existing data out of data that was passed in. See parent for explanation.
    *
    * @param mixed
    *
    * @return array|false
    */
    
protected function _getExistingData($data)
    {
        if (!
$templateId $this->_getExistingPrimaryKey($data))
        {
            return 
false;
        }

        return array(
'xf_email_template' => $this->_getEmailTemplateModel()->getEmailTemplateById($templateId));
    }

    
/**
    * Gets SQL condition to update the existing record.
    *
    * @return string
    */
    
protected function _getUpdateCondition($tableName)
    {
        return 
'template_id = ' $this->_db->quote($this->getExisting('template_id'));
    }

    
/**
    * Gets the default set of options for this data writer.
    * If in debug mode and we have a development directory config, we set the template
    * dev output directory automatically.
    *
    * @return array
    */
    
protected function _getDefaultOptions()
    {
        
$options = array(
            
self::OPTION_DEV_OUTPUT_DIR => '',
            
self::OPTION_FULL_COMPILE => true,
            
self::OPTION_TEST_COMPILE => true
        
);

        
$config XenForo_Application::get('config');
        if (
$config->debug)
        {
            
$options[self::OPTION_DEV_OUTPUT_DIR] = $this->_getEmailTemplateModel()->getEmailTemplateDevelopmentDirectory();
        }

        return 
$options;
    }

    
/**
     * Verifies that the provided template title contains only valid characters
     *
     * @param string Title
     *
     * @return boolean
     */
    
protected function _verifyTitle(&$title)
    {
        if (
preg_match('/[^a-zA-Z0-9_.]/'$title))
        {
            
$this->error(new XenForo_Phrase('please_enter_title_using_only_alphanumeric_dot'), 'title');
            return 
false;
        }

        
$this->_templateModifications null;
        return 
true;
    }

    
/**
    * Verification callback for an email template subject.
    *
    * @param string Uncompiled subject
    *
    * @return boolean
    */
    
protected function _verifySubject(&$subject)
    {
        return 
$this->_verifyTemplateField($subject'subject');
    }

    
/**
    * Verification callback for an email template plain text body.
    *
    * @param string Uncompiled body
    *
    * @return boolean
    */
    
protected function _verifyBodyText(&$body)
    {
        return 
$this->_verifyTemplateField($body'body_text');
    }

    
/**
    * Verification callback for an email template plain text body.
    *
    * @param string Uncompiled body
    *
    * @return boolean
    */
    
protected function _verifyBodyHtml(&$body)
    {
        return 
$this->_verifyTemplateField($body'body_html');
    }

    protected 
$_templateModifications null;

    protected function 
_getTemplateModifications()
    {
        if (
$this->_templateModifications === null)
        {
            
$this->_templateModifications $this->_getModificationModel()->getActiveModificationsForTemplate($this->get('title'));
        }

        return 
$this->_templateModifications;
    }

    protected function 
_verifyTemplateField($string$fieldName)
    {
        
$modifications $this->_getTemplateModifications();
        foreach (
$modifications AS $k => $modification)
        {
            if (
$modification['search_location'] != $fieldName)
            {
                unset(
$modifications[$k]);
            }
        }

        
$templateWithModifications $this->_getModificationModel()->applyTemplateModifications(
            
$string$modifications$modificationStatuses
        
);
        
$standardParse true;
        
$parsed null;

        if (
$modificationStatuses)
        {
            try
            {
                
$compiler = new XenForo_Template_Compiler_Email($templateWithModifications);
                
$parsed $compiler->lexAndParse();

                if (
$this->getOption(self::OPTION_TEST_COMPILE))
                {
                    
$compiler->setFollowExternal(false);
                    
$compiler->compileParsed($parsed$this->get('title'), 00);
                }
                
$standardParse false;
            }
            catch (
XenForo_Template_Compiler_Exception $e)
            {
                foreach (
$modificationStatuses AS &$status)
                {
                    if (
is_int($status))
                    {
                        
$status 'error_compile';
                    }
                }
            }
        }

        if (
$standardParse)
        {
            try
            {
                
$compiler = new XenForo_Template_Compiler_Email($string);
                
$parsed $compiler->lexAndParse();

                if (
$this->getOption(self::OPTION_TEST_COMPILE))
                {
                    
$compiler->setFollowExternal(false);
                    
$compiler->compileParsed($parsed$this->get('title'), 00);
                }
            }
            catch (
XenForo_Template_Compiler_Exception $e)
            {
                
$this->error($e->getMessage(), $fieldName);
                return 
false;
            }
        }

        
$this->set($fieldName '_parsed'serialize($parsed));

        if (!
is_array($this->_modificationStatuses))
        {
            
$this->_modificationStatuses = array();
        }
        
$this->_modificationStatuses += $modificationStatuses;

        return 
true;
    }

    public function 
reparseTemplate()
    {
        
$subject $this->get('subject');
        
$this->_verifySubject($subject);

        
$bodyText $this->get('body_text');
        
$this->_verifyBodyText($bodyText);

        
$bodyHtml $this->get('body_html');
        
$this->_verifyBodyHtml($bodyHtml);
    }

    
/**
     * Pre-save handler.
     */
    
protected function _preSave()
    {
        if (
$this->isChanged('title') || $this->isChanged('custom'))
        {
            
$existingTemplate $this->_getEmailTemplateModel()->getEmailTemplateByTitleAndType(
                
$this->get('title'), $this->get('custom')
            );
            if (
$existingTemplate)
            {
                
$this->error(new XenForo_Phrase('template_titles_must_be_unique'), 'title');
            }
        }
    }

    
/**
    * Post-save handler.
    */
    
protected function _postSave()
    {
        if (
is_array($this->_modificationStatuses))
        {
            
$this->_getModificationModel()->updateTemplateModificationLog($this->get('template_id'), $this->_modificationStatuses);
        }

        if (
$this->getOption(self::OPTION_FULL_COMPILE))
        {
            
XenForo_Template_Compiler_Email::removeTemplateFromCache($this->get('title'));
            
XenForo_Template_Compiler_Email::removeTemplateFromCache($this->getExisting('title'));

            
$this->_recompileTemplate();
        }

        if (
$devDir $this->_getDevOutputDir())
        {
            
$this->_writeDevFileOutput($devDir);
        }
    }

    
/**
     * Recompiles this template.
     */
    
protected function _recompileTemplate()
    {
        
$this->_getEmailTemplateModel()->compileAndInsertNamedEmailTemplate($this->get('title'));
    }

    
/**
     * Helper to get the developer data output directory only if it is enabled
     * and applicable to this situation.
     *
     * @return string
     */
    
protected function _getDevOutputDir()
    {
        if (
$this->get('addon_id') == 'XenForo' && $this->get('custom') == 0)
        {
            return 
$this->getOption(self::OPTION_DEV_OUTPUT_DIR);
        }
        else
        {
            return 
'';
        }
    }

    
/**
    * Writes the development files output to the specified directory. This will write
    * each template into an individual file for easier tracking in source control.
    *
    * @param string Path to directory to write to
    */
    
protected function _writeDevFileOutput($dir)
    {
        if (!
is_dir($dir) || !is_writable($dir))
        {
            throw new 
XenForo_Exception("Email template development directory $dir is not writable");
        }

        
$filePrefix $dir '/' $this->get('title');
        
$files = array(
            
$filePrefix '.subject.txt' => $this->get('subject'),
            
$filePrefix '.text.txt' => $this->get('body_text'),
            
$filePrefix '.html.txt' => $this->get('body_html'),
        );

        foreach (
$files AS $filePath => $data)
        {
            
$fp fopen($filePath'w');
            if (
$fp)
            {
                
fwrite($fp$data);
                
fclose($fp);
            }
        }

        if (
$this->isUpdate() && $this->isChanged('title'))
        {
            
$this->_deleteExistingDevOutput($dir);
        }
    }

    
/**
     * Post-delete handler.
     */
    
protected function _postDelete()
    {
        
$this->_db->delete('xf_email_template_modification_log''template_id = ' $this->_db->quote($this->get('template_id')));

        if (
$this->get('custom'))
        {
            
$this->_recompileTemplate();
        }
        else
        {
            
$titleQuoted $this->_db->quote($this->get('title'));

            
$this->_db->delete('xf_email_template''title = ' $titleQuoted);
            
$this->_db->delete('xf_email_template_compiled''title = ' $titleQuoted);
            
$this->_db->delete('xf_email_template_phrase''title = ' $titleQuoted);
        }

        if (
$devDir $this->_getDevOutputDir())
        {
            
$this->_deleteExistingDevOutput($devDir);
        }
    }

    
/**
     * Deletes the corresponding files when a template is deleted from the database
     *
     * @param string Path to email templates directory
     */
    
protected function _deleteExistingDevOutput($dir)
    {
        
$filePrefix $dir '/' $this->getExisting('title');
        
$files = array(
            
$filePrefix '.subject.txt',
            
$filePrefix '.text.txt',
            
$filePrefix '.html.txt',
        );

        
// ensure all files are writable before unlinking any
        
foreach ($files AS $file)
        {
            if (
file_exists($file) && !is_writable($file))
            {
                throw new 
XenForo_Exception("Email template development file $dir is not writable");
            }
        }

        foreach (
$files AS $file)
        {
            if (
file_exists($file) && is_writable($file))
            {
                
unlink($file);
            }
        }
    }

    
/**
     * @return XenForo_Model_EmailTemplate
     */
    
protected function _getEmailTemplateModel()
    {
        return 
$this->getModelFromCache('XenForo_Model_EmailTemplate');
    }

    
/**
     * @return XenForo_Model_EmailTemplateModification
     */
    
protected function _getModificationModel()
    {
        return 
$this->getModelFromCache('XenForo_Model_EmailTemplateModification');
    }
}
Онлайн: 2
Реклама