<?php
/**
* СодеÑÐ¶Ð¸Ñ ÐºÐ»Ð°ÑÑ DataSet
*
* @package energine
* @author dr.Pavka
* @copyright ColoCall 2006
* @version $Id: DataSet.class.php,v 1.22 2008/04/04 10:37:55 pavka Exp $
*/
//require_once('core/framework/Component.class.php');
//require_once('core/framework/DataDescription.class.php');
//require_once('core/framework/Data.class.php');
//require_once('core/framework/SimpleBuilder.class.php');
//require_once('core/framework/Pager.class.php');
//require_once('core/modules/share/components/Toolbar.class.php');
/**
* ÐÑедок Ð´Ð»Ñ ÑоÑмÑ, ÑпиÑка, и деÑева; ÑодеÑÐ¶Ð¸Ñ Ð¼ÐµÑÐ¾Ð´Ñ ÑабоÑÑ Ñ Ð¿Ð°Ð½ÐµÐ»ÑÑ Ð¸Ð½ÑÑÑÑменÑов и набоÑом даннÑÑ
.
*
* @package energine
* @subpackage share
* @abstract
*/
abstract class DataSet extends Component {
/**
* Тип компоненÑа - ÑпиÑок
*/
const COMPONENT_TYPE_LIST = 'list';
/**
* Тип компоненÑа - ÑоÑма
*/
const COMPONENT_TYPE_FORM = 'form';
/**
* Тип ÑоÑÐ¼Ñ - ÑоÑма добавлениÑ
*/
const COMPONENT_TYPE_FORM_ADD = QAL::INSERT;
/**
* Тип ÑоÑÐ¼Ñ - ÑоÑма ÑедакÑиÑованиÑ
*/
const COMPONENT_TYPE_FORM_ALTER = QAL::UPDATE;
/**
* ÐÑеÑÐ¸ÐºÑ Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ Ð¿Ð°Ð½ÐµÐ»Ð¸ инÑÑÑÑменÑов
*/
const TB_PREFIX = 'toolbar_';
/**
* ÐпиÑание даннÑÑ
*
* @var DataDescription
* @access private
*/
private $dataDescription = false;
/**
* ÐаннÑе
*
* @var Data
* @access private
*/
private $data = false;
/**
* ÐÐ°Ð½ÐµÐ»Ñ Ð¸Ð½ÑÑÑÑменÑов
*
* @var Toolbar
* @access private
*/
private $toolbar = false;
/**
* JavaScript
*
* @var DOMNode
* @access protected
*/
protected $js;
/**
* Тип компоненÑа
*
* @var string
* @access private
*/
private $type;
/**
* ÐеÑÐµÐ²Ð¾Ð´Ñ ÐºÐ¾ÑоÑÑе добавлÑÑÑÑÑ Ðº ÑоÑме/ÑпиÑкÑ
*
* @var array
* @access private
*/
private $translations = array();
/**
* СпиÑок ÑÑÑÐ°Ð½Ð¸Ñ (pager)
*
* @var Pager
*/
protected $pager;
/**
* ÐÐ°Ð±Ð¾Ñ Ñабов
*
* @var array
* @access protected
*/
protected $tabs = array();
/**
* ÐонÑÑÑÑкÑÐ¾Ñ ÐºÐ»Ð°ÑÑа
*
* @return void
*/
public function __construct($name, $module, Document $document, array $params = null) {
parent::__construct($name, $module, $document, $params);
$this->setType(self::COMPONENT_TYPE_FORM);
if(!$this->getParam('recordsPerPage'))$this->setParam('recordsPerPage', 20);
}
/**
* ÐобавленÑ:
* ÐаÑамеÑÑ datasetAction
* ÐаÑамеÑÑ recordsPerPage
*
* @return array
* @access protected
*/
protected function defineParams() {
$this->setProperty('action', '');
return array_merge(
parent::defineParams(),
array(
'datasetAction' => '',
'recordsPerPage' => false
)
);
}
/**
* УÑÑÐ°Ð½Ð°Ð²Ð»Ð¸Ð²Ð°ÐµÑ Ð´Ð°Ð½Ð½Ñе
*
* @return void
* @access protected
* @final
*/
final protected function setData(Data $data) {
$this->data = $data;
}
/**
* ÐозвÑаÑÐ°ÐµÑ Ð¾Ð±ÑÐµÐºÑ Ð´Ð°Ð½Ð½ÑÑ
*
* @return Data
* @access protected
* @final
*/
final protected function getData() {
return $this->data;
}
/**
* ÐозвÑаÑÐ°ÐµÑ ÑÑлбаÑ
*
* @return ToolBar
* @access protected
*/
protected function getToolbar() {
return $this->toolbar;
}
/**
* УÑÑÐ°Ð½Ð°Ð²Ð»Ð¸Ð²Ð°ÐµÑ Ð¾Ð±ÑÐµÐºÑ ÑÑлбаÑа
*
* @return void
* @access protected
*/
protected function setToolbar(Toolbar $toolbar) {
$this->toolbar = $toolbar;
}
/**
* УÑÑÐ°Ð½Ð°Ð²Ð»Ð¸Ð²Ð°ÐµÑ Ð¾Ð¿Ð¸Ñание даннÑÑ
*
* @return void
* @access protected
* @final
*/
final protected function setDataDescription(DataDescription $dataDescription) {
$this->dataDescription = $dataDescription;
}
/**
* ÐозвÑаÑÐ°ÐµÑ Ð¾Ð¿Ð¸Ñание даннÑÑ
*
* @return DataDescription
* @access protected
* @final
*/
final protected function getDataDescription() {
// СÑÑеÑÑвÑÐµÑ Ð»Ð¸ опиÑание даннÑÑ
?
// Ðез опиÑÐ°Ð½Ð¸Ñ Ð´Ð°Ð½Ð½ÑÑ
ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ Ð½Ðµ ÑÐ¼Ð¾Ð¶ÐµÑ Ð½Ð¾ÑмалÑно ÑабоÑаÑÑ.
if (!$this->dataDescription) {
throw new SystemException('ERR_DEV_NO_DATA_DESCRIPTION', SystemException::ERR_DEVELOPER, $this->getName());
}
// ÐпиÑание даннÑÑ
не должно бÑÑÑ Ð¿ÑÑÑÑм
if ($this->dataDescription->getLength() == 0) {
//throw new SystemException('ERR_DEV_EMPTY_DATA_DESCRIPTION', SystemException::ERR_DEVELOPER, $this->getName());
}
return $this->dataDescription;
}
/**
* ÐодгоÑовиÑелÑнÑе дейÑÑÐ²Ð¸Ñ Ð¿ÐµÑед вÑзовом оÑновного дейÑÑвиÑ.
*
* @return void
* @access protected
*/
protected function prepare() {
$this->setBuilder($this->createBuilder());
$this->setDataDescription($this->createDataDescription());
$this->createPager();
$data = $this->createData();
if ($data instanceof Data) {
$this->setData($data);
}
if ($toolbar = $this->createToolbar()) {
$this->setToolbar($toolbar);
}
$this->js = $this->buildJS();
}
/**
* Ð¡Ð¾Ð·Ð´Ð°ÐµÑ Ð¿Ð¾ÑÑÑоиÑелÑ
*
* @return Builder
* @access protected
*/
protected function createBuilder() {
return new SimpleBuilder($this->getTitle());
}
/**
* Создаем обÑÐµÐºÑ Ð¾Ð¿Ð¸ÑÐ°Ð½Ð¸Ñ Ð´Ð°Ð½Ð½ÑÑ
*
* @return DataDescription
* @access protected
*/
protected function createDataDescription() {
// опиÑание даннÑÑ
из конÑигÑÑаÑии
$configDataDescriptionObject = new DataDescription();
if ($this->config->getCurrentMethodConfig()) {
$configDataDescriptionObject->loadXML($this->config->getCurrentMethodConfig()->fields);
}
// внеÑнее опиÑание даннÑÑ
$externalDataDescription = $this->loadDataDescription();
if (is_null($externalDataDescription)) {
throw new SystemException('ERR_DEV_LOAD_DATA_DESCR_IS_FUNCTION', SystemException::ERR_DEVELOPER);
}
// еÑли ÑÑÑеÑÑвÑÐµÑ Ð²Ð½ÐµÑнее опиÑание даннÑÑ
- пеÑеÑекаем Ñ Ð¾Ð¿Ð¸Ñанием из конÑига
if ($externalDataDescription) {
$externalDataDescriptionObject = new DataDescription();
$externalDataDescriptionObject->load($externalDataDescription);
$configDataDescriptionObject = $configDataDescriptionObject->intersect($externalDataDescriptionObject);
}
return $configDataDescriptionObject;
}
/**
* Создание панели инÑÑÑÑменÑов
*
* @return void
* @access protected
*/
protected function createToolbar() {
$toolbar = false;
if ($this->config->getCurrentMethodConfig()) {
$toolbar = new Toolbar(self::TB_PREFIX.$this->getName());
$toolbar->attachToComponent($this);
$toolbar->loadXML($this->config->getCurrentMethodConfig()->toolbar);
$toolbar->translate();
}
return $toolbar;
}
/**
* Ð¡Ð¾Ð·Ð´Ð°ÐµÑ Ð»Ð¸ÑÑалкÑ
*
* @return void
* @access protected
*/
protected function createPager() {
$recordsPerPage = intval($this->getParam('recordsPerPage'));
if ($recordsPerPage > 0) {
$this->pager = new Pager($recordsPerPage);
if ($this->isActive() && $this->getType() == self::COMPONENT_TYPE_LIST) {
$actionParams = $this->getActionParams();
if (isset($actionParams[0])) {
$page = intval($actionParams[0]);
}
else {
$page = 1;
}
$this->pager->setCurrentPage($page);
}
$this->pager->setProperty('title', $this->translate('TXT_PAGES'));
}
}
/**
* ÐбÑÑÑакÑнÑй меÑод загÑÑзки даннÑÑ
*
* @return mixed
* @access protected
*/
protected function loadData() {
return false;
}
/**
* ÐбÑÑÑакÑнÑй меÑод загÑÑзки опиÑÐ°Ð½Ð¸Ñ Ð´Ð°Ð½Ð½ÑÑ
* ÐÑполÑзÑеÑÑÑ Ð´Ð»Ñ Ð·Ð°Ð³ÑÑзки внеÑнего опиÑÐ°Ð½Ð¸Ñ Ð´Ð°Ð½Ð½ÑÑ
(не из конÑигÑÑаÑии)
*
* @return mixed
* @access protected
*/
protected function loadDataDescription() {
return false;
}
/**
* ÐÑовеÑÑÐµÑ Ð½Ð°Ð»Ð¸Ñие поÑÑÑиÑелÑ
* пеÑÐµÐ´Ð°ÐµÑ ÐµÐ¼Ñ Ð´Ð°Ð½Ð½Ñе и опиÑание даннÑÑ
*
* @return DOMDocument
* @access public
*/
public function build() {
if (!$this->getBuilder()) {
throw new SystemException('ERR_DEV_NO_BUILDER', SystemException::ERR_CRITICAL, $this->getName());
}
// пеÑедаем даннÑе и опиÑание даннÑÑ
поÑÑÑоиÑелÑ
if ($this->getData()) {
$this->getBuilder()->setData($this->getData());
}
$this->getBuilder()->setDataDescription($this->getDataDescription());
// вÑзÑваем ÑодиÑелÑÑкий меÑод поÑÑÑоениÑ
$result = parent::build();
if ($this->js) {
$result->documentElement->appendChild($result->importNode($this->js, true));
}
if (($toolbar = $this->getToolbar()) && ($toolbar = $toolbar->build())) {
$result->documentElement->appendChild($result->importNode($toolbar, true));
}
if ($this->pager && $this->getType() == self::COMPONENT_TYPE_LIST && $pagerData = $this->pager->build()) {
$pager = $result->importNode($pagerData, true);
$result->documentElement->appendChild($pager);
}
//РабоÑа Ñ ÐºÐ¾Ð½ÑÑанÑами пеÑеводов
if (($methodConfig = $this->config->getCurrentMethodConfig()) && $methodConfig->translations) {
foreach ($methodConfig->translations->translation as $translation) {
$this->addTranslation($translation['const']);
}
}
if (!empty($this->translations)) {
$translationsXML = $this->doc->createElement('translations');
foreach ($this->translations as $tag) {
$translationXML = $this->doc->createElement('translation', $this->translate($tag));
$translationXML->setAttribute('const', $tag);
$translationsXML->appendChild($translationXML);
}
$result->documentElement->appendChild($translationsXML);
}
if (!empty($this->tabs)) {
$tabsXML = $this->doc->createElement('tabs');
foreach ($this->tabs as $tab) {
$tabsXML->appendChild($tab);
}
$result->documentElement->appendChild($tabsXML);
}
return $result;
}
/**
* ÐагÑÑÐ¶Ð°ÐµÑ Ð´Ð°Ð½Ð½Ñе
*
* @return Data
* @access protected
*/
protected function createData() {
$result = false;
$data = $this->loadData();
if (is_null($data)) {
throw new SystemException('ERR_DEV_LOAD_DATA_IS_FUNCTION', SystemException::ERR_DEVELOPER);
}
if (is_array($data)) {
$result = new Data();
$result->load($data);
}
return $result;
}
/**
* СÑÑÐ¾Ð¸Ñ Ð¾Ð¿Ð¸Ñание JS обÑекÑов
*
* @return DOMNode
* @access protected
*/
protected function buildJS() {
$result = false;
if (($config = $this->config->getCurrentMethodConfig()) && $config->javascript) {
$result = $this->doc->createElement('javascript');
foreach ($config->javascript->include as $value) {
$JSIncludeXML = $this->doc->createElement('include');
$JSIncludeXML->setAttribute('name', $value['name']);
$JSIncludeXML->setAttribute('path', 'scripts/');
$result->appendChild($JSIncludeXML);
}
foreach ($config->javascript->object as $value) {
$JSObjectXML = $this->doc->createElement('object');
$JSObjectXML->setAttribute('name', $value['name']);
$JSObjectXML->setAttribute('path', 'scripts/');
$result->appendChild($JSObjectXML);
}
foreach ($config->javascript->param as $value) {
$JSParamXML = $this->doc->createElement('param', $value);
$JSParamXML->setAttribute('name', $value['name']);
$result->appendChild($JSParamXML);
}
}
return $result;
}
/**
* УÑÑÐ°Ð½Ð°Ð²Ð»Ð¸Ð²Ð°ÐµÑ Ð°Ð´ÑÐµÑ Ð¾Ð±ÑабоÑÑика ÑоÑмÑ
*
* @param string
* @param bool
* @access public
*/
final protected function setDataSetAction($action, $isFullURI = false) {
// еÑли Ñ Ð½Ð°Ñ Ð½Ðµ полноÑÑÑÑ ÑÑоÑмиÑованнÑй пÑÑÑ, Ñо добавлÑем инÑоÑмаÑÐ¸Ñ Ð¾ ÑзÑке + пÑÑÑ Ðº ÑаблонÑ
if (!$isFullURI) {
$action = $this->request->getLangSegment().
$this->request->getPath(Request::PATH_TEMPLATE, true).
$action;
// еÑли в конÑе Ð½ÐµÑ ÑлеÑа - добавлÑем его
if (substr($action, -1) != '/') {
$action .= '/';
}
}
$this->setParam('datasetAction', $action);
$this->setProperty('action', $action);
}
/**
* ÐозвÑаÑÐ°ÐµÑ Ð°Ð´ÑÐµÑ Ð¾Ð±ÑабоÑÑика ÑоÑмÑ
*
* @return string
* @access public
*/
final protected function getDataSetAction() {
return $this->getParam('datasetAction');
}
/**
* УÑÑÐ°Ð½Ð°Ð²Ð»Ð¸Ð²Ð°ÐµÑ Ñип компоненÑа
*
* @param string
* @return void
* @access protected
*/
final protected function setType($type) {
$this->type = $type;
if (in_array($type, array(self::COMPONENT_TYPE_FORM_ADD, self::COMPONENT_TYPE_FORM_ALTER ))) {
$type = self::COMPONENT_TYPE_FORM;
}
$this->setProperty('type', $type);
}
/**
* ÐозвÑаÑÐ°ÐµÑ Ñип компоненÑа
*
* @return string
* @access protected
*/
final protected function getType() {
return $this->type;
}
/**
* УÑÑÐ°Ð½Ð°Ð²Ð»Ð¸Ð²Ð°ÐµÑ Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ðµ компоненÑа
*
* @param string $title
*/
final protected function setTitle($title) {
$this->setProperty('title', $title);
}
/**
* ÐозвÑаÑÐ°ÐµÑ Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ðµ компоненÑа
*
* @return string
*/
final protected function getTitle() {
return $this->getProperty('title');
}
/**
* ÐобавлÑÐµÑ Ð¿ÐµÑеводÑ
*
* @return void
* @access protected
* @final
*/
final protected function addTranslation($tag) {
array_push($this->translations, $tag);
}
/**
* Ð¡Ð¾Ð·Ð´Ð°ÐµÑ tab
*
* @param string
* @param array
* @return DOMNode
* @access protected
*/
protected function buildTab($tabName, $tabProperties = false) {
$tabXML = $this->doc->createElement('tab');
$tabXML->setAttribute('name', $tabName);
if ($tabProperties)
foreach ($tabProperties as $key => $value) {
$tabXML->setAttribute($key, $value);
}
return $tabXML;
}
/**
* ÐобавлÑÐµÑ Ð²ÐºÐ»Ð°Ð´ÐºÑ Ðº пеÑеÑÐ½Ñ Ð²ÐºÐ»Ð°Ð´Ð¾Ðº
*
* @return void
* @access protected
* @final
*/
final protected function addTab($tab) {
array_push($this->tabs, $tab);
}
/**
* ЧиÑÑка Ð¾Ñ Ð»Ð¸ÑниÑ
и веÑдоноÑнÑÑ
html Ñегов
* ÐÑзÑваеÑÑÑ Ð² single Ñежиме
*
* @return void
* @access protected
*/
protected function cleanup() {
$data = isset($_POST['data']) ? $_POST['data'] : '';
$data = self::cleanupHTML($data);
$this->response->setHeader('Content-Type', 'text/html; charset=utf-8');
$this->response->write($data);
$this->response->commit();
}
/**
* УдалÑÐµÑ Ð¿Ð¾ÑенÑиалÑно опаÑнÑй и лиÑний HTML код
*
* @param string
* @return string
* @access protected
* @static
*/
protected static function cleanupHTML($data) {
$aggressive = isset($_GET['aggressive']);
$data = str_replace('Ð ', '^Ñ^', $data); // cyrillic
$data = str_replace(' ', ' ', $data);
$data = str_replace('Ã ', '^a^', $data);
$tidy = new tidy;
$config = array(
'bare' => $aggressive,
//'clean' => true,
'drop-font-tags' => true,
'drop-proprietary-attributes' => true,
'hide-comments' => true,
'indent' => true,
'logical-emphasis' => true,
'numeric-entities' => true,
'show-body-only' => true,
'input-encoding' => 'utf8',
'output-encoding' => 'utf8',
'output-xhtml' => true,
'merge-spans' => true,
'merge-divs' => true,
);
$tidy->parseString($data, $config);
$tidy->cleanRepair();
$data = tidy_get_output($tidy);
// FIX THE PROBLEMS:
$data = str_replace('^Ñ^', 'Ð ', $data); // cyrillic
$data = str_replace("\r", '', $data);
$data = str_replace('^a^', 'Ã ', $data);
//$data = str_replace(array("\r", "\n"), ' ', $data);
//$data = preg_replace('/style="text-align: ([^"]+)"/', 'align="$1"', $data);
$allowedTags = array(
'a', 'abbr', 'acronym', 'address', 'b', 'big', 'blockquote', 'br', 'cite',
'code', 'col', 'colgroup', 'dd', 'del', 'dfn', 'div', 'dl', 'dt', 'em',
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'ins', 'kbd', 'li', 'ol',
'p', 'pre', 'q', 's', 'samp', 'small', 'span', 'strong', 'sub', 'sup',
'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'u', 'ul', 'var'
);
if (!$aggressive) $allowedTags[] = 'img';
// strip all tags except allowed
$data = preg_replace('/<\/(?!'.join('[ >]|', $allowedTags).'[ >])(.*?)>/ims', '', $data);
$data = preg_replace('/<(?!\/)(?!'.join('[ >]|', $allowedTags).'[ >])(.*?)>/ims', '', $data);
$data = preg_replace('/<([^\/][^>]+)>/ems', '\'<\'.stripHtmlAttributes(\'$1\', $aggressive).\'>\'', $data);
return $data;
}
}
/**
* ФÑнкÑÐ¸Ñ Ð¾ÑиÑÑки лиÑниÑ
аÑÑÑибÑÑов
* ÐÑнеÑена оÑделÑно изза ÑпеÑиÑики ÑабоÑÑ preg_replace
*
* @param string $tagSource
* @param boolean $aggressive
* @return string
*/
function stripHtmlAttributes($tagSource, $aggressive) {
$request = Request::getInstance();
$tagSource = urldecode($tagSource);
$tagSource = str_replace($request->getBasePath(), '', $tagSource);
$uri = $request->getURI();
$tagSource = str_replace($uri->getScheme().'://'.$uri->getHost().'/', '', $tagSource);
$allowedAttrs = array(
'align', 'alt', 'strong', 'border', 'cellpadding', 'cellspacing', 'colspan',
'height', 'href', 'hspace', 'id', 'rowspan', 'src', 'target', 'title', 'vspace', 'width'
);
if (!$aggressive) {
$allowedAttrs[] = 'style';
$allowedAttrs[] = 'class';
}
$tagSource = stripslashes($tagSource);
$tagSource = str_replace(array("\r", "\n"), ' ', $tagSource);
$result = preg_replace('/\b(?!'.join('|', $allowedAttrs).')[^ =]+=\s*"[^"]+"/i', '', $tagSource);
return $result;
}