Вход Регистрация
Файл: contao-3.5.8/system/modules/core/forms/Form.php
Строк: 258
<?php

/**
 * Contao Open Source CMS
 *
 * Copyright (c) 2005-2016 Leo Feyer
 *
 * @license LGPL-3.0+
 */

namespace Contao;


/**
 * Provide methods to handle front end forms.
 *
 * @property integer $id
 * @property string  $title
 * @property string  $formID
 * @property string  $method
 * @property boolean $tableless
 * @property boolean $allowTags
 * @property string  $attributes
 * @property boolean $novalidate
 * @property integer $jumpTo
 * @property boolean $sendViaEmail
 * @property boolean $skipEmpty
 * @property string  $format
 * @property string  $recipient
 * @property string  $subject
 * @property boolean $storeValues
 * @property string  $targetTable
 *
 * @author Leo Feyer <https://github.com/leofeyer>
 */
class Form extends Hybrid
{

    
/**
     * Model
     * @var FormModel
     */
    
protected $objModel;

    
/**
     * Key
     * @var string
     */
    
protected $strKey 'form';

    
/**
     * Table
     * @var string
     */
    
protected $strTable 'tl_form';

    
/**
     * Template
     * @var string
     */
    
protected $strTemplate 'form';

    
/**
     * Form usages during same request
     * @var array
     */
    
static protected $arrFormUsages = array();


    
/**
     * Remove name attributes in the back end so the form is not validated
     *
     * @return string
     */
    
public function generate()
    {
        if (
TL_MODE == 'BE')
        {
            
/** @var BackendTemplate|object $objTemplate */
            
$objTemplate = new BackendTemplate('be_wildcard');

            
$objTemplate->wildcard '### ' utf8_strtoupper($GLOBALS['TL_LANG']['CTE']['form'][0]) . ' ###';
            
$objTemplate->id $this->id;
            
$objTemplate->link $this->title;
            
$objTemplate->href 'contao/main.php?do=form&amp;table=tl_form_field&amp;id=' $this->id;

            return 
$objTemplate->parse();
        }

        return 
parent::generate();
    }


    
/**
     * Generate the form
     *
     * @return string
     */
    
protected function compile()
    {
        
$hasUpload false;
        
$doNotSubmit false;
        
$arrSubmitted = array();

        
$this->loadDataContainer('tl_form_field');
        
$formId = ($this->formID != '') ? 'auto_'.$this->formID 'auto_form_'.$this->id;

        
$this->Template->fields '';
        
$this->Template->hidden '';
        
$this->Template->formSubmit $formId;
        
$this->Template->tableless $this->tableless true false;
        
$this->Template->method = ($this->method == 'GET') ? 'get' 'post';

        
$this->initializeSession($formId);
        
$arrLabels = array();

        
// Get all form fields
        
$arrFields = array();
        
$objFields FormFieldModel::findPublishedByPid($this->id);

        if (
$objFields !== null)
        {
            while (
$objFields->next())
            {
                
$arrFields[] = $objFields->current();
            }
        }

        
// HOOK: compile form fields
        
if (isset($GLOBALS['TL_HOOKS']['compileFormFields']) && is_array($GLOBALS['TL_HOOKS']['compileFormFields']))
        {
            foreach (
$GLOBALS['TL_HOOKS']['compileFormFields'] as $callback)
            {
                
$this->import($callback[0]);
                
$arrFields $this->{$callback[0]}->{$callback[1]}($arrFields$formId$this);
            }
        }

        
// Process the fields
        
if (!empty($arrFields) && is_array($arrFields))
        {
            
$row 0;
            
$max_row count($arrFields);

            foreach (
$arrFields as $objField)
            {
                
/** @var FormFieldModel $objField */
                
$strClass $GLOBALS['TL_FFL'][$objField->type];

                
// Continue if the class is not defined
                
if (!class_exists($strClass))
                {
                    continue;
                }

                
$arrData $objField->row();

                
$arrData['decodeEntities'] = true;
                
$arrData['allowHtml'] = $this->allowTags;
                
$arrData['rowClass'] = 'row_'.$row . (($row == 0) ? ' row_first' : (($row == ($max_row 1)) ? ' row_last' '')) . ((($row 2) == 0) ? ' even' ' odd');
                
$arrData['tableless'] = $this->tableless;

                
// Increase the row count if its a password field
                
if ($objField->type == 'password')
                {
                    ++
$row;
                    ++
$max_row;

                    
$arrData['rowClassConfirm'] = 'row_'.$row . (($row == ($max_row 1)) ? ' row_last' '') . ((($row 2) == 0) ? ' even' ' odd');
                }

                
// Submit buttons do not use the name attribute
                
if ($objField->type == 'submit')
                {
                    
$arrData['name'] = '';
                }

                
// Unset the default value depending on the field type (see #4722)
                
if (!empty($arrData['value']))
                {
                    if (!
in_array('value'trimsplit('[,;]'$GLOBALS['TL_DCA']['tl_form_field']['palettes'][$objField->type])))
                    {
                        
$arrData['value'] = '';
                    }
                }

                
/** @var Widget $objWidget */
                
$objWidget = new $strClass($arrData);
                
$objWidget->required $objField->mandatory true false;

                
// HOOK: load form field callback
                
if (isset($GLOBALS['TL_HOOKS']['loadFormField']) && is_array($GLOBALS['TL_HOOKS']['loadFormField']))
                {
                    foreach (
$GLOBALS['TL_HOOKS']['loadFormField'] as $callback)
                    {
                        
$this->import($callback[0]);
                        
$objWidget $this->{$callback[0]}->{$callback[1]}($objWidget$formId$this->arrData$this);
                    }
                }

                
// Validate the input
                
if (Input::post('FORM_SUBMIT') == $formId)
                {
                    
$objWidget->validate();

                    
// HOOK: validate form field callback
                    
if (isset($GLOBALS['TL_HOOKS']['validateFormField']) && is_array($GLOBALS['TL_HOOKS']['validateFormField']))
                    {
                        foreach (
$GLOBALS['TL_HOOKS']['validateFormField'] as $callback)
                        {
                            
$this->import($callback[0]);
                            
$objWidget $this->{$callback[0]}->{$callback[1]}($objWidget$formId$this->arrData$this);
                        }
                    }

                    if (
$objWidget->hasErrors())
                    {
                        
$doNotSubmit true;
                    }

                    
// Store current value in the session
                    
elseif ($objWidget->submitInput())
                    {
                        
$arrSubmitted[$objField->name] = $objWidget->value;
                        
$_SESSION['FORM_DATA'][$objField->name] = $objWidget->value;
                        unset(
$_POST[$objField->name]); // see #5474
                    
}
                }

                if (
$objWidget instanceof uploadable)
                {
                    
$hasUpload true;
                }

                if (
$objWidget instanceof FormHidden)
                {
                    
$this->Template->hidden .= $objWidget->parse();
                    --
$max_row;
                    continue;
                }

                if (
$objWidget->name != '' && $objWidget->label != '')
                {
                    
$arrLabels[$objWidget->name] = $this->replaceInsertTags($objWidget->label); // see #4268
                
}

                
$this->Template->fields .= $objWidget->parse();
                ++
$row;
            }
        }

        
// Process the form data
        
if (Input::post('FORM_SUBMIT') == $formId && !$doNotSubmit)
        {
            
$this->processFormData($arrSubmitted$arrLabels$arrFields);
        }

        
// Add a warning to the page title
        
if ($doNotSubmit && !Environment::get('isAjaxRequest'))
        {
            
/** @var PageModel $objPage */
            
global $objPage;

            
$title $objPage->pageTitle ?: $objPage->title;
            
$objPage->pageTitle $GLOBALS['TL_LANG']['ERR']['form'] . ' - ' $title;
            
$_SESSION['FILES'] = array(); // see #3007
        
}

        
$strAttributes '';
        
$arrAttributes deserialize($this->attributestrue);

        if (
$arrAttributes[1] != '')
        {
            
$strAttributes .= ' class="' $arrAttributes[1] . '"';
        }

        
$formId $arrAttributes[0] ?: 'f'.$this->id;

        
// Count up form usages
        
if (isset(static::$arrFormUsages[$formId]))
        {
            static::
$arrFormUsages[$formId]++;
        }
        else
        {
            static::
$arrFormUsages[$formId] = 1;
        }

        
// Adjust form id
        
if (static::$arrFormUsages[$formId] > 1)
        {
            
$formId .= '_' . static::$arrFormUsages[$formId];
        }

        
$this->Template->hasError $doNotSubmit;
        
$this->Template->attributes $strAttributes;
        
$this->Template->enctype $hasUpload 'multipart/form-data' 'application/x-www-form-urlencoded';
        
$this->Template->formId $formId;
        
$this->Template->action Environment::get('indexFreeRequest');
        
$this->Template->maxFileSize $hasUpload $this->objModel->getMaxUploadFileSize() : false;
        
$this->Template->novalidate $this->novalidate ' novalidate' '';

        
// Get the target URL
        
if ($this->method == 'GET' && $this->jumpTo && ($objTarget $this->objModel->getRelated('jumpTo')) !== null)
        {
            
/** @var PageModel $objTarget */
            
$this->Template->action $objTarget->getFrontendUrl();
        }

        return 
$this->Template->parse();
    }


    
/**
     * Process form data, store it in the session and redirect to the jumpTo page
     *
     * @param array $arrSubmitted
     * @param array $arrLabels
     * @param array $arrFields
     */
    
protected function processFormData($arrSubmitted$arrLabels$arrFields)
    {
        
// HOOK: prepare form data callback
        
if (isset($GLOBALS['TL_HOOKS']['prepareFormData']) && is_array($GLOBALS['TL_HOOKS']['prepareFormData']))
        {
            foreach (
$GLOBALS['TL_HOOKS']['prepareFormData'] as $callback)
            {
                
$this->import($callback[0]);
                
$this->{$callback[0]}->{$callback[1]}($arrSubmitted$arrLabels$this$arrFields);
            }
        }

        
// Send form data via e-mail
        
if ($this->sendViaEmail)
        {
            
$keys = array();
            
$values = array();
            
$fields = array();
            
$message '';

            foreach (
$arrSubmitted as $k=>$v)
            {
                if (
$k == 'cc')
                {
                    continue;
                }

                
$v deserialize($v);

                
// Skip empty fields
                
if ($this->skipEmpty && !is_array($v) && !strlen($v))
                {
                    continue;
                }

                
// Add field to message
                
$message .= (isset($arrLabels[$k]) ? $arrLabels[$k] : ucfirst($k)) . ': ' . (is_array($v) ? implode(', '$v) : $v) . "n";

                
// Prepare XML file
                
if ($this->format == 'xml')
                {
                    
$fields[] = array
                    (
                        
'name' => $k,
                        
'values' => (is_array($v) ? $v : array($v))
                    );
                }

                
// Prepare CSV file
                
if ($this->format == 'csv')
                {
                    
$keys[] = $k;
                    
$values[] = (is_array($v) ? implode(','$v) : $v);
                }
            }

            
$recipients StringUtil::splitCsv($this->recipient);

            
// Format recipients
            
foreach ($recipients as $k=>$v)
            {
                
$recipients[$k] = str_replace(array('['']''"'), array('<''>'''), $v);
            }

            
$email = new Email();

            
// Get subject and message
            
if ($this->format == 'email')
            {
                
$message $arrSubmitted['message'];
                
$email->subject $arrSubmitted['subject'];
            }

            
// Set the admin e-mail as "from" address
            
$email->from $GLOBALS['TL_ADMIN_EMAIL'];
            
$email->fromName $GLOBALS['TL_ADMIN_NAME'];

            
// Get the "reply to" address
            
if (strlen(Input::post('email'true)))
            {
                
$replyTo Input::post('email'true);

                
// Add name
                
if (strlen(Input::post('name')))
                {
                    
$replyTo '"' Input::post('name') . '" <' $replyTo '>';
                }

                
$email->replyTo($replyTo);
            }

            
// Fallback to default subject
            
if (!strlen($email->subject))
            {
                
$email->subject $this->replaceInsertTags($this->subjectfalse);
            }

            
// Send copy to sender
            
if (strlen($arrSubmitted['cc']))
            {
                
$email->sendCc(Input::post('email'true));
                unset(
$_SESSION['FORM_DATA']['cc']);
            }

            
// Attach XML file
            
if ($this->format == 'xml')
            {
                
/** @var FrontendTemplate|object $objTemplate */
                
$objTemplate = new FrontendTemplate('form_xml');

                
$objTemplate->fields $fields;
                
$objTemplate->charset Config::get('characterSet');

                
$email->attachFileFromString($objTemplate->parse(), 'form.xml''application/xml');
            }

            
// Attach CSV file
            
if ($this->format == 'csv')
            {
                
$email->attachFileFromString(StringUtil::decodeEntities('"' implode('";"'$keys) . '"' "n" '"' implode('";"'$values) . '"'), 'form.csv''text/comma-separated-values');
            }

            
$uploaded '';

            
// Attach uploaded files
            
if (!empty($_SESSION['FILES']))
            {
                foreach (
$_SESSION['FILES'] as $file)
                {
                    
// Add a link to the uploaded file
                    
if ($file['uploaded'])
                    {
                        
$uploaded .= "n" Environment::get('base') . str_replace(TL_ROOT '/'''dirname($file['tmp_name'])) . '/' rawurlencode($file['name']);
                        continue;
                    }

                    
$email->attachFileFromString(file_get_contents($file['tmp_name']), $file['name'], $file['type']);
                }
            }

            
$uploaded strlen(trim($uploaded)) ? "nn---n" $uploaded '';
            
$email->text StringUtil::decodeEntities(trim($message)) . $uploaded "nn";

            
// Send the e-mail
            
try
            {
                
$email->sendTo($recipients);
            }
            catch (
Swift_SwiftException $e)
            {
                
$this->log('Form "' $this->title '" could not be sent: ' $e->getMessage(), __METHOD__TL_ERROR);
            }
        }

        
// Store the values in the database
        
if ($this->storeValues && $this->targetTable != '')
        {
            
$arrSet = array();

            
// Add the timestamp
            
if ($this->Database->fieldExists('tstamp'$this->targetTable))
            {
                
$arrSet['tstamp'] = time();
            }

            
// Fields
            
foreach ($arrSubmitted as $k=>$v)
            {
                if (
$k != 'cc' && $k != 'id')
                {
                    
$arrSet[$k] = $v;
                }
            }

            
// Files
            
if (!empty($_SESSION['FILES']))
            {
                foreach (
$_SESSION['FILES'] as $k=>$v)
                {
                    if (
$v['uploaded'])
                    {
                        
$arrSet[$k] = str_replace(TL_ROOT '/'''$v['tmp_name']);
                    }
                }
            }

            
// HOOK: store form data callback
            
if (isset($GLOBALS['TL_HOOKS']['storeFormData']) && is_array($GLOBALS['TL_HOOKS']['storeFormData']))
            {
                foreach (
$GLOBALS['TL_HOOKS']['storeFormData'] as $callback)
                {
                    
$this->import($callback[0]);
                    
$arrSet $this->{$callback[0]}->{$callback[1]}($arrSet$this);
                }
            }

            
// Set the correct empty value (see #6284, #6373)
            
foreach ($arrSet as $k=>$v)
            {
                if (
$v === '')
                {
                    
$arrSet[$k] = Widget::getEmptyValueByFieldType($GLOBALS['TL_DCA'][$this->targetTable]['fields'][$k]['sql']);
                }
            }

            
// Do not use Models here (backwards compatibility)
            
$this->Database->prepare("INSERT INTO " $this->targetTable " %s")->set($arrSet)->execute();
        }

        
// Store all values in the session
        
foreach (array_keys($_POST) as $key)
        {
            
$_SESSION['FORM_DATA'][$key] = $this->allowTags Input::postHtml($keytrue) : Input::post($keytrue);
        }

        
$arrFiles $_SESSION['FILES'];

        
// HOOK: process form data callback
        
if (isset($GLOBALS['TL_HOOKS']['processFormData']) && is_array($GLOBALS['TL_HOOKS']['processFormData']))
        {
            foreach (
$GLOBALS['TL_HOOKS']['processFormData'] as $callback)
            {
                
$this->import($callback[0]);
                
$this->{$callback[0]}->{$callback[1]}($arrSubmitted$this->arrData$arrFiles$arrLabels$this);
            }
        }

        
$_SESSION['FILES'] = array(); // DO NOT CHANGE

        // Add a log entry
        
if (FE_USER_LOGGED_IN)
        {
            
$this->import('FrontendUser''User');
            
$this->log('Form "' $this->title '" has been submitted by "' $this->User->username '".'__METHOD__TL_FORMS);
        }
        else
        {
            
$this->log('Form "' $this->title '" has been submitted by ' System::anonymizeIp(Environment::get('ip')) . '.'__METHOD__TL_FORMS);
        }

        
// Check whether there is a jumpTo page
        
if (($objJumpTo $this->objModel->getRelated('jumpTo')) !== null)
        {
            
$this->jumpToOrReload($objJumpTo->row());
        }

        
$this->reload();
    }


    
/**
     * Get the maximum file size that is allowed for file uploads
     *
     * @return integer
     */
    
protected function getMaxFileSize()
    {
        return 
$this->objModel->getMaxUploadFileSize(); // Backwards compatibility
    
}


    
/**
     * Initialize the form in the current session
     *
     * @param string $formId
     */
    
protected function initializeSession($formId)
    {
        if (
Input::post('FORM_SUBMIT') != $formId)
        {
            return;
        }

        
$arrMessageBox = array('TL_ERROR''TL_CONFIRM''TL_INFO');
        
$_SESSION['FORM_DATA'] = is_array($_SESSION['FORM_DATA']) ? $_SESSION['FORM_DATA'] : array();

        foreach (
$arrMessageBox as $tl)
        {
            if (
is_array($_SESSION[$formId][$tl]))
            {
                
$_SESSION[$formId][$tl] = array_unique($_SESSION[$formId][$tl]);

                foreach (
$_SESSION[$formId][$tl] as $message)
                {
                    
/** @var FrontendTemplate|object $objTemplate */
                    
$objTemplate = new FrontendTemplate('form_message');

                    
$objTemplate->message $message;
                    
$objTemplate->class strtolower($tl);
                    
$objTemplate->tableless $this->tableless true false;

                    
$this->Template->fields .= $objTemplate->parse() . "n";
                }

                
$_SESSION[$formId][$tl] = array();
            }
        }
    }
}
Онлайн: 0
Реклама