Source for file DataSet.class.php

Documentation is available at DataSet.class.php

  1. /**
  2.  * Содержит класс DataSet
  3.  *
  4.  * @package energine
  5.  * @author dr.Pavka
  6.  * @copyright ColoCall 2006
  7.  * @version $Id: fsource_energine__modulessharecomponentsDataSet.class.php.html,v 1.1 2007/09/17 14:32:31 pavka Exp $
  8.  */
  9.  
  10. require_once 'core/framework/Component.class.php';
  11. require_once 'core/framework/DataDescription.class.php';
  12. require_once 'core/framework/Data.class.php';
  13. require_once 'core/framework/SimpleBuilder.class.php';
  14. require_once 'core/framework/Pager.class.php';
  15. require_once 'core/modules/share/components/Toolbar.class.php';
  16.  
  17. /**
  18.  * Предок для формы, списка, и дерева; содержит методы работы с панелью инструментов и набором данных.
  19.  *
  20.  * @package energine
  21.  * @subpackage share
  22.  * @abstract
  23.  */
  24. abstract class DataSet extends Component {
  25.  
  26.     /**
  27.      * Тип компонента - список
  28.      */
  29.     const COMPONENT_TYPE_LIST = 'list';
  30.  
  31.     /**
  32.      * Тип компонента - форма
  33.      */
  34.     const COMPONENT_TYPE_FORM = 'form';
  35.  
  36.     /**
  37.      * Тип формы - форма добавления
  38.      */
  39.     const COMPONENT_TYPE_FORM_ADD = QAL::INSERT;
  40.  
  41.     /**
  42.      * Тип формы - форма редактирования
  43.      */
  44.     const COMPONENT_TYPE_FORM_ALTER = QAL::UPDATE;
  45.  
  46.     /**
  47.      * Префикс названия панели инструментов
  48.      */
  49.     const TB_PREFIX = 'toolbar_';
  50.  
  51.     /**
  52.      * Описание данных
  53.      *
  54.      * @var DataDescription 
  55.      * @access private
  56.      */
  57.     private $dataDescription = false;
  58.  
  59.     /**
  60.      * Данные
  61.      *
  62.      * @var Data 
  63.      * @access private
  64.      */
  65.     private $data = false;
  66.  
  67.     /**
  68.      * Панель инструментов
  69.      *
  70.      * @var Toolbar 
  71.      * @access private
  72.      */
  73.     private $toolbar = false;
  74.  
  75.     /**
  76.      * JavaScript
  77.      *
  78.      * @var DOMNode 
  79.      * @access protected
  80.      */
  81.     protected $js;
  82.  
  83.     /**
  84.      * Тип компонента
  85.      *
  86.      * @var string 
  87.      * @access private
  88.      */
  89.     private $type;
  90.  
  91.     /**
  92.      * Переводы которые добавляются к форме/списку
  93.      *
  94.      * @var array 
  95.      * @access private
  96.      */
  97.     private $translations = array();
  98.  
  99.  
  100.     /**
  101.      * Список страниц (pager)
  102.      *
  103.      * @var Pager 
  104.      */
  105.     protected $pager;
  106.  
  107.     /**
  108.      * Набор табов
  109.      *
  110.      * @var array 
  111.      * @access protected
  112.      */
  113.     protected $tabs = array();
  114.  
  115.     /**
  116.      * Конструктор класса
  117.      *
  118.      * @return void 
  119.      */
  120.     public function __construct($name$moduleDocument $document,  array $params null{
  121.         parent::__construct($name$module$document,  $params);
  122.         $this->setType(self::COMPONENT_TYPE_FORM);
  123.         if(!$this->getParam('recordsPerPage'))$this->setParam('recordsPerPage'20);
  124.     }
  125.  
  126.     /**
  127.      * Добавлены:
  128.      * Параметр datasetAction
  129.      * Параметр recordsPerPage
  130.      *
  131.      * @return array 
  132.      * @access protected
  133.      */
  134.     protected function defineParams({
  135.         $this->setProperty('action''');
  136.         return array_merge(
  137.         parent::defineParams(),
  138.         array(
  139.         'datasetAction' => '',
  140.         'recordsPerPage' => false
  141.         )
  142.         );
  143.     }
  144.  
  145.     /**
  146.      * Устанавливает данные
  147.      *
  148.      * @return void 
  149.      * @access protected
  150.      * @final
  151.      */
  152.     final protected function setData(Data $data{
  153.         $this->data $data;
  154.     }
  155.  
  156.     /**
  157.      * Возвращает объект данных
  158.      *
  159.      * @return Data 
  160.      * @access protected
  161.      * @final
  162.      */
  163.     final protected function getData({
  164.         return $this->data;
  165.     }
  166.  
  167.     /**
  168.      * Возвращает тулбар
  169.      *
  170.      * @return ToolBar 
  171.      * @access protected
  172.      */
  173.  
  174.     protected function getToolbar({
  175.         return $this->toolbar;
  176.     }
  177.     /**
  178.       * Устанавливает обїект тулбара
  179.       *
  180.       * @return void 
  181.       * @access protected
  182.       */
  183.  
  184.     protected function setToolbar(Toolbar $toolbar{
  185.         $this->toolbar $toolbar;
  186.     }
  187.  
  188.     /**
  189.      * Устанавливает описание данных
  190.      *
  191.      * @return void 
  192.      * @access protected
  193.      * @final
  194.      */
  195.     final protected function setDataDescription(DataDescription $dataDescription{
  196.         $this->dataDescription $dataDescription;
  197.     }
  198.  
  199.     /**
  200.      * Возвращает описание данных
  201.      *
  202.      * @return DataDescription 
  203.      * @access protected
  204.      * @final
  205.      */
  206.     final protected function getDataDescription({
  207.         // Существует ли описание данных?
  208.         // Без описания данных компонент не сможет нормально работать.
  209.         if (!$this->dataDescription{
  210.             throw new SystemException('ERR_DEV_NO_DATA_DESCRIPTION'SystemException::ERR_DEVELOPER$this->getName());
  211.         }
  212.  
  213.         // Описание данных не должно быть пустым
  214.         if ($this->dataDescription->getLength(== 0{
  215.             throw new SystemException('ERR_DEV_EMPTY_DATA_DESCRIPTION'SystemException::ERR_DEVELOPER$this->getName());
  216.         }
  217.  
  218.         return $this->dataDescription;
  219.     }
  220.  
  221.     /**
  222.      * Подготовительные действия перед вызовом основного действия.
  223.      *
  224.      * @return void 
  225.      * @access protected
  226.      */
  227.     protected function prepare({
  228.         $this->setBuilder($this->createBuilder());
  229.         $this->setDataDescription($this->createDataDescription());
  230.         $this->createPager();
  231.         $data $this->createData();
  232.         if ($data instanceof Data{
  233.             $this->setData($data);
  234.         }
  235.         if ($toolbar $this->createToolbar()) {
  236.             $this->setToolbar($toolbar);
  237.         }
  238.         $this->js $this->buildJS();
  239.     }
  240.  
  241.     /**
  242.      * Создает построитель
  243.      *
  244.      * @return Builder 
  245.      * @access protected
  246.      */
  247.     protected function createBuilder({
  248.         return new SimpleBuilder();
  249.     }
  250.  
  251.     /**
  252.      * Создаем объект описания данных
  253.      *
  254.      * @return DataDescription 
  255.      * @access protected
  256.      */
  257.     protected function createDataDescription({
  258.         // описание данных из конфигурации
  259.         $configDataDescriptionObject new DataDescription();
  260.         if ($this->config->getCurrentMethodConfig()) {
  261.             $configDataDescriptionObject->loadXML($this->config->getCurrentMethodConfig()->fields);
  262.         }
  263.  
  264.  
  265.         // внешнее описание данных
  266.         $externalDataDescription $this->loadDataDescription();
  267.         if (is_null($externalDataDescription)) {
  268.             throw new SystemException('ERR_DEV_LOAD_DATA_DESCR_IS_FUNCTION'SystemException::ERR_DEVELOPER);
  269.         }
  270.  
  271.         // если существует внешнее описание данных - пересекаем с описанием из конфига
  272.         if ($externalDataDescription{
  273.             $externalDataDescriptionObject new DataDescription();
  274.             $externalDataDescriptionObject->load($externalDataDescription);
  275.             $configDataDescriptionObject $configDataDescriptionObject->intersect($externalDataDescriptionObject);
  276.         }
  277.  
  278.         return $configDataDescriptionObject;
  279.     }
  280.  
  281.     /**
  282.      * Создание панели инструментов
  283.      *
  284.      * @return void 
  285.      * @access protected
  286.      */
  287.     protected function createToolbar({
  288.         $toolbar false;
  289.         if ($this->config->getCurrentMethodConfig()) {
  290.             $toolbar new Toolbar(self::TB_PREFIX.$this->getName());
  291.             $toolbar->attachToComponent($this);
  292.             $toolbar->loadXML($this->config->getCurrentMethodConfig()->toolbar);
  293.             $toolbar->translate();
  294.         }
  295.  
  296.         return $toolbar;
  297.     }
  298.  
  299.     /**
  300.      * Создает листалку
  301.      *
  302.      * @return void 
  303.      * @access protected
  304.      */
  305.  
  306.     protected function createPager({
  307.         $recordsPerPage = intval($this->getParam('recordsPerPage'));
  308.         if ($recordsPerPage 0{
  309.             $this->pager new Pager($recordsPerPage);
  310.             if ($this->isActive(&& $this->getType(== self::COMPONENT_TYPE_LIST{
  311.                 $actionParams $this->getActionParams();
  312.                 if (isset($actionParams[0])) {
  313.                     $page = intval($actionParams[0]);
  314.                 }
  315.                 else {
  316.                     $page 1;
  317.                 }
  318.                 $this->pager->setCurrentPage($page);
  319.             }
  320.  
  321.             $this->pager->setProperty('title'$this->translate('TXT_PAGES'));
  322.         }
  323.     }
  324.  
  325.     /**
  326.      * Абстрактный метод загрузки данных
  327.      *
  328.      * @return mixed 
  329.      * @access protected
  330.      */
  331.     protected function loadData({
  332.         return false;
  333.     }
  334.  
  335.     /**
  336.      * Абстрактный метод загрузки описания данных
  337.      * Используется для загрузки внешнего описания данных (не из конфигурации)
  338.      *
  339.      * @return mixed 
  340.      * @access protected
  341.      */
  342.     protected function loadDataDescription({
  343.         return false;
  344.     }
  345.  
  346.     /**
  347.      * Проверяет наличие пострителя
  348.      * передает ему данные и описание данных
  349.      *
  350.      * @return DOMDocument 
  351.      * @access public
  352.      */
  353.     public function build({
  354.         if (!$this->getBuilder()) {
  355.             throw new SystemException('ERR_DEV_NO_BUILDER'SystemException::ERR_CRITICAL$this->getName());
  356.         }
  357.  
  358.         // передаем данные и описание данных построителю
  359.         if ($this->getData()) {
  360.             $this->getBuilder()->setData($this->getData());
  361.         }
  362.         $this->getBuilder()->setDataDescription($this->getDataDescription());
  363.  
  364.         // вызываем родительский метод построения
  365.         $result parent::build();
  366.  
  367.  
  368.         if ($this->js{
  369.             $result->documentElement->appendChild($result->importNode($this->jstrue));
  370.         }
  371.  
  372.         if (($toolbar $this->getToolbar()) && ($toolbar $toolbar->build())) {
  373.             $result->documentElement->appendChild($result->importNode($toolbartrue));
  374.         }
  375.  
  376.         if ($this->pager && $this->getType(== self::COMPONENT_TYPE_LIST && $pagerData $this->pager->build()) {
  377.             $pager $result->importNode($pagerDatatrue);
  378.             $result->documentElement->appendChild($pager);
  379.         }
  380.  
  381.         if (!empty($this->translations)) {
  382.             $translationsXML $this->doc->createElement('translations');
  383.             foreach ($this->translations as $tag{
  384.                 $translationXML $this->doc->createElement('translation'$this->translate($tag));
  385.                 $translationXML->setAttribute('const'$tag);
  386.                 $translationsXML->appendChild($translationXML);
  387.             }
  388.             $result->documentElement->appendChild($translationsXML);
  389.         }
  390.  
  391.         if (!empty($this->tabs)) {
  392.             $tabsXML $this->doc->createElement('tabs');
  393.  
  394.             foreach ($this->tabs as $tab{
  395.                 $tabsXML->appendChild($tab);
  396.             }
  397.  
  398.             $result->documentElement->appendChild($tabsXML);
  399.         }
  400.  
  401.         return $result;
  402.     }
  403.  
  404.     /**
  405.      * Загружает данные
  406.      *
  407.      * @return Data 
  408.      * @access protected
  409.      */
  410.     protected function createData({
  411.         $result false;
  412.         $data $this->loadData();
  413.         if (is_null($data)) {
  414.             throw new SystemException('ERR_DEV_LOAD_DATA_IS_FUNCTION'SystemException::ERR_DEVELOPER);
  415.         }
  416.  
  417.         if (is_array($data)) {
  418.             $result new Data();
  419.             $result->load($data);
  420.         }
  421.         return $result;
  422.     }
  423.  
  424.     /**
  425.      * Строит описание JS объектов
  426.      *
  427.      * @return DOMNode 
  428.      * @access protected
  429.      */
  430.     protected function buildJS({
  431.         $result false;
  432.         if (($config $this->config->getCurrentMethodConfig()) && $config->javascript{
  433.             $result $this->doc->createElement('javascript');
  434.             foreach ($config->javascript->include as $value{
  435.                 $JSIncludeXML $this->doc->createElement('include');
  436.                 $JSIncludeXML->setAttribute('name'$value['name']);
  437.                 $JSIncludeXML->setAttribute('path'isset($value['is_user_defined']'scripts/' 'scripts/default/');
  438.                 $result->appendChild($JSIncludeXML);
  439.             }
  440.             foreach ($config->javascript->object as $value{
  441.                 $JSObjectXML $this->doc->createElement('object');
  442.                 $JSObjectXML->setAttribute('name'$value['name']);
  443.                 $JSObjectXML->setAttribute('path'isset($value['is_user_defined']'scripts/' 'scripts/default/');
  444.                 $result->appendChild($JSObjectXML);
  445.             }
  446.             foreach ($config->javascript->param as $value{
  447.                 $JSParamXML $this->doc->createElement('param'$value);
  448.                 $JSParamXML->setAttribute('name'$value['name']);
  449.                 $result->appendChild($JSParamXML);
  450.             }
  451.         }
  452.         return $result;
  453.     }
  454.  
  455.     /**
  456.      * Устанавливает адрес обработчика формы
  457.      *
  458.      * @param string 
  459.      * @param bool 
  460.      * @access public
  461.      */
  462.     final protected function setDataSetAction($action$isFullURI false{
  463.         // если у нас не полностью сформированный путь, то добавляем информацию о языке + путь к шаблону
  464.         if (!$isFullURI{
  465.             $action $this->request->getLangSegment().
  466.             $this->request->getPath(Request::PATH_TEMPLATEtrue).
  467.             $action;
  468.  
  469.             // если в конце нет слеша - добавляем его
  470.             if (substr($action-1!= '/'{
  471.                 $action .= '/';
  472.             }
  473.         }
  474.  
  475.  
  476.  
  477.         $this->setParam('datasetAction'$action);
  478.         $this->setProperty('action'$action);
  479.     }
  480.  
  481.     /**
  482.      * Возвращает адрес обработчика формы
  483.      *
  484.      * @return string 
  485.      * @access public
  486.      */
  487.     final protected function getDataSetAction({
  488.         return $this->getParam('datasetAction');
  489.     }
  490.  
  491.     /**
  492.      * Устанавливает тип компонента
  493.      *
  494.      * @param string 
  495.      * @return void 
  496.      * @access protected
  497.      */
  498.     final protected function setType($type{
  499.         $this->type $type;
  500.         if (in_array($typearray(self::COMPONENT_TYPE_FORM_ADDself::COMPONENT_TYPE_FORM_ALTER ))) {
  501.             $type self::COMPONENT_TYPE_FORM;
  502.         }
  503.         $this->setProperty('type'$type);
  504.     }
  505.  
  506.     /**
  507.      * Возвращает тип компонента
  508.      *
  509.      * @return string 
  510.      * @access protected
  511.      */
  512.     final protected function getType({
  513.         return $this->type;
  514.     }
  515.  
  516.     /**
  517.      * Устанавливает название компонента
  518.      *
  519.      * @param string $title 
  520.      */
  521.     final protected function setTitle($title{
  522.         $this->setProperty('title'$title);
  523.     }
  524.  
  525.     /**
  526.      * Возвращает название компонента
  527.      *
  528.      * @return string 
  529.      */
  530.     final protected function getTitle({
  531.         return $this->getProperty('title');
  532.     }
  533.  
  534.     /**
  535.      * Добавляет переводы
  536.      *
  537.      * @return void 
  538.      * @access protected
  539.      * @final
  540.      */
  541.  
  542.     final protected function addTranslation($tag{
  543.         array_push($this->translations$tag);
  544.     }
  545.     /**
  546.      * Создает tab
  547.      *
  548.      * @param string 
  549.      * @param array 
  550.      * @return DOMNode 
  551.      * @access protected
  552.      */
  553.  
  554.     protected function buildTab($tabName$tabProperties false{
  555.         $tabXML    $this->doc->createElement('tab');
  556.         $tabXML->setAttribute('name'$tabName);
  557.         if ($tabProperties)
  558.         foreach ($tabProperties as $key => $value{
  559.             $tabXML->setAttribute($key$value);
  560.         }
  561.         return $tabXML;
  562.     }
  563.  
  564.     /**
  565.      * Добавляет вкладку к перечню вкладок
  566.      *
  567.      * @return void 
  568.      * @access protected
  569.      * @final
  570.      */
  571.  
  572.     final protected function addTab($tab{
  573.         array_push($this->tabs$tab);
  574.     }
  575.     /**
  576.      * Чистка от лишних и вердоносных html тегов
  577.      * Вызывается в single режиме
  578.      *
  579.      * @return void 
  580.      * @access protected
  581.      */
  582.  
  583.     protected function cleanup({
  584.         $data = isset($_POST['data']$_POST['data''';
  585.         $data self::cleanupHTML($data);
  586.         $this->response->setHeader('Content-Type''text/html; charset=utf-8');
  587.         $this->response->write($data);
  588.         $this->response->commit();
  589.     }
  590.  
  591.     /**
  592.      * Удаляет потенциально опасный и лишний HTML код
  593.      *
  594.      * @param string 
  595.      * @return string 
  596.      * @access protected
  597.      * @static
  598.      */
  599.  
  600.     protected static function cleanupHTML($data{
  601.         $aggressive = isset($_GET['aggressive']);
  602.  
  603.         $data = str_replace('Р''^р^'$data)// cyrillic
  604.         $data = str_replace(' '' '$data);
  605.  
  606.         $tidy new tidy;
  607.         $config array(
  608.         'bare' => $aggressive,
  609.         //'clean' => true,
  610.         'drop-font-tags' => true,
  611.         'drop-proprietary-attributes' => true,
  612.         'hide-comments' => true,
  613.         'indent' => true,
  614.         'logical-emphasis' => true,
  615.         'numeric-entities' => true,
  616.         'show-body-only' => true,
  617.         'input-encoding' => 'utf8',
  618.         'output-encoding' => 'utf8'
  619.         );
  620.         $tidy->parseString($data$config);
  621.         $tidy->cleanRepair();
  622.         $data = tidy_get_output($tidy);
  623.  
  624.         // FIX THE PROBLEMS:
  625.         $data = str_replace('^р^''Р'$data)// cyrillic
  626.         $data = str_replace("\r"''$data);
  627.         //$data = str_replace(array("\r", "\n"), ' ', $data);
  628.         //$data = preg_replace('/style="text-align: ([^"]+)"/', 'align="$1"', $data);
  629.  
  630.         $allowedTags array(
  631.         'a''abbr''acronym''address''b''big''blockquote''br''cite',
  632.         'code''col''colgroup''dd''del''dfn''div''dl''dt''em',
  633.         'h1''h2''h3''h4''h5''h6''hr''i''ins''kbd''li''ol',
  634.         'p''pre''q''s''samp''small''span''strong''sub''sup',
  635.         'table''tbody''td''tfoot''th''thead''tr''tt''u''ul''var'
  636.         );
  637.         if (!$aggressive$allowedTags['img';
  638.  
  639.         // strip all tags except allowed
  640.         $data = preg_replace('/<\/(?!'.join('[ >]|'$allowedTags).'[ >])(.*?)>/ims'''$data);
  641.         $data = preg_replace('/<(?!\/)(?!'.join('[ >]|'$allowedTags).'[ >])(.*?)>/ims'''$data);
  642.         $data = preg_replace('/<([^\/][^>]+)>/ems''\'<\'.stripHtmlAttributes(\'$1\', $aggressive).\'>\''$data);
  643.  
  644.         return $data;
  645.     }
  646. }
  647.  
  648. /**
  649.  * Функция очистки лишних аттрибутов
  650.  * Вынесена отдельно изза специфики работы preg_replace
  651.  *
  652.  * @param string $tagSource 
  653.  * @param boolean $aggressive 
  654.  * @return string 
  655.  */
  656. function stripHtmlAttributes($tagSource$aggressive{
  657.     $request Request::getInstance();
  658.     $tagSource = urldecode($tagSource);
  659.     $tagSource = str_replace($request->getBasePath()''$tagSource);
  660.     $uri $request->getURI();
  661.     $tagSource = str_replace($uri->getScheme().'://'.$uri->getHost().'/'''$tagSource);
  662.  
  663.     $allowedAttrs array(
  664.     'align''alt''strong''border''cellpadding''cellspacing',  'colspan',
  665.     'height''href''hspace''id''longdesc''rowspan''src''target''title''vspace''width'
  666.     );
  667.     if (!$aggressive{
  668.         $allowedAttrs['style';
  669.         $allowedAttrs['class';
  670.     }
  671.     $tagSource = stripslashes($tagSource);
  672.     $tagSource = str_replace(array("\r""\n")' '$tagSource);
  673.     $result = preg_replace('/\b(?!'.join('|'$allowedAttrs).')[^ =]+=\s*"[^"]+"/i'''$tagSource);
  674.     return $result;
  675. }

Documentation generated on Mon, 17 Sep 2007 13:26:44 +0300 by phpDocumentor 1.4.0a2