1
0
Fork 0
mirror of https://github.com/Oreolek/ifhub.club.git synced 2024-06-26 03:30:48 +03:00

Черновой модуль Property для работы с дополнительными полями к произвольным сущностям

This commit is contained in:
Mzhelskiy Maxim 2013-10-01 17:26:39 +07:00
parent 15ea078d9b
commit 19410ce7b0
16 changed files with 1803 additions and 1 deletions

View file

@ -0,0 +1,110 @@
<?php
/**
* LiveStreet CMS
* Copyright © 2013 OOO "ЛС-СОФТ"
*
* ------------------------------------------------------
*
* Official site: www.livestreetcms.com
* Contact e-mail: office@livestreetcms.com
*
* GNU General Public License, version 2:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* ------------------------------------------------------
*
* @link http://www.livestreetcms.com
* @copyright 2013 OOO "ЛС-СОФТ"
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
*
*/
/**
* Хук для работы свойств(дополнительных полей сущности)
*/
class HookProperty extends Hook {
public function RegisterHook() {
$this->AddHook('lang_init_start','InitStart',null,-10000);
$this->AddHook('module_orm_GetItemsByFilter_after','GetItemsByFilterAfter',null,10000);
$this->AddHook('module_orm_GetItemsByFilter_before','GetItemsByFilterBefore',null,10000);
$this->AddHook('module_orm_GetByFilter_before','GetItemsByFilterBefore',null,10000);
}
public function InitStart() {
/**
* Регистрируем кастомный загрузчик классов
*/
spl_autoload_register(array($this,'autoload'),true,true);
/**
* Добавляем через наследование в объекты необходимый функционал по работе со свойствами EAV
*/
$aTargetTypes=$this->Property_GetTargetTypes();
foreach($aTargetTypes as $sType=>$aParams) {
$this->Plugin_Inherit($aParams['entity'],'ModuleProperty_Target_'.$aParams['entity'],'ModuleProperty');
}
}
/**
* Дополнительная пост-обработка результатов запроса ORM
*
* @param $aParams
*/
public function GetItemsByFilterAfter($aParams) {
$aEntities=$aParams['aEntities'];
$aFilter=$aParams['aFilter'];
$this->Property_RewriteGetItemsByFilter($aEntities,$aFilter);
}
/**
* Обработка фильтра для запросов к ORM
*
* @param $aParams
*/
public function GetItemsByFilterBefore($aParams) {
$aFilter=$this->Property_RewriteFilter($aParams['aFilter'],$aParams['sEntityFull']);
$aParams['aFilter']=$aFilter;
}
/**
* Автозагрузчик классов
* Создает новый фейковый класс для создания цепочки наследования
*
* @param string $sClassName
*/
public function autoload($sClassName) {
if (preg_match("#^ModuleProperty_Target_(.+)$#i",$sClassName,$aMatch)) {
$sClass="
class {$sClassName} extends ModuleProperty_Inherit_{$aMatch[1]} {
public function Init() {
parent::Init();
\$this->aValidateRules[]=array('properties','properties_check');
}
public function ValidatePropertiesCheck() {
return \$this->Property_ValidateEntityPropertiesCheck(\$this);
}
protected function afterSave() {
parent::afterSave();
\$this->Property_UpdatePropertiesValue(\$this->getPropertiesObject(),\$this);
}
protected function afterDelete() {
parent::afterDelete();
\$this->Property_RemovePropertiesValue(\$this);
}
public function getPropertyValue(\$sPropertyId) {
return \$this->Property_GetEntityPropertyValue(\$this,\$sPropertyId);
}
public function getProperty(\$sPropertyId) {
return \$this->Property_GetEntityProperty(\$this,\$sPropertyId);
}
public function getPropertyList() {
return \$this->Property_GetEntityPropertyList(\$this);
}
}";
eval($sClass);
}
}
}

View file

@ -0,0 +1,558 @@
<?php
/**
* LiveStreet CMS
* Copyright © 2013 OOO "ЛС-СОФТ"
*
* ------------------------------------------------------
*
* Official site: www.livestreetcms.com
* Contact e-mail: office@livestreetcms.com
*
* GNU General Public License, version 2:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* ------------------------------------------------------
*
* @link http://www.livestreetcms.com
* @copyright 2013 OOO "ЛС-СОФТ"
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
*
*/
class ModuleProperty extends ModuleORM {
/**
* Список возможных типов свойств/полей
*/
const PROPERTY_TYPE_INT='int';
const PROPERTY_TYPE_FLOAT='float';
const PROPERTY_TYPE_VARCHAR='varchar';
const PROPERTY_TYPE_TEXT='text';
const PROPERTY_TYPE_CHECKBOX='checkbox';
const PROPERTY_TYPE_TAGS='tags';
const PROPERTY_TYPE_VIDEO_LINK='video_link';
protected $oMapper=null;
/**
* Список доступных типов полей
*
* @var array
*/
protected $aPropertyTypes=array(
self::PROPERTY_TYPE_INT,self::PROPERTY_TYPE_FLOAT,self::PROPERTY_TYPE_VARCHAR,self::PROPERTY_TYPE_TEXT,self::PROPERTY_TYPE_CHECKBOX,self::PROPERTY_TYPE_TAGS,self::PROPERTY_TYPE_VIDEO_LINK
);
/**
* Список разрешенных типов
* На данный момент допустимы параметры entity=>ModuleTest_EntityTest - указывает на класс сущности
* name=>Статьи
*
* @var array
*/
protected $aTargetTypes=array(
);
public function Init() {
parent::Init();
$this->oMapper=Engine::GetMapper(__CLASS__);
}
/**
* Возвращает список типов объектов
*
* @return array
*/
public function GetTargetTypes() {
return $this->aTargetTypes;
}
/**
* Добавляет в разрешенные новый тип
*
* @param string $sTargetType Тип
* @param array $aParams Параметры
* @return bool
*/
public function AddTargetType($sTargetType,$aParams=array()) {
if (!array_key_exists($sTargetType,$this->aTargetTypes)) {
$this->aTargetTypes[$sTargetType]=$aParams;
return true;
}
return false;
}
/**
* Проверяет разрешен ли данный тип
*
* @param string $sTargetType Тип
* @return bool
*/
public function IsAllowTargetType($sTargetType) {
return in_array($sTargetType,array_keys($this->aTargetTypes));
}
/**
* Проверяет разрешен ли тип поля
*
* @param string $sType
*
* @return bool
*/
public function IsAllowPropertyType($sType) {
return in_array($sType,$this->aPropertyTypes);
}
/**
* Для каждого из свойств получает значение
*
* @param array $aProperties Список свойств
* @param string $sTargetType Тип объекта
* @param int $iTargetId ID объекта
*
* @return bool
*/
public function AttachValueForProperties($aProperties,$sTargetType,$iTargetId) {
if (!$aProperties) {
return false;
}
/**
* Формируем список ID свойств
*/
$aPropertyIds=array();
foreach($aProperties as $oProperty) {
$aPropertyIds[]=$oProperty->getId();
}
/**
* Получаем список значений
*/
$aValues=$this->Property_GetValueItemsByFilter(array('target_id'=>$iTargetId,'target_type'=>$sTargetType,'property_id in'=>$aPropertyIds,'#index-from'=>'property_id'));
/**
* Аттачим значения к свойствам
*/
foreach($aProperties as $oProperty) {
if (isset($aValues[$oProperty->getId()])) {
$oProperty->setValue($aValues[$oProperty->getId()]);
} else {
$oProperty->setValue(Engine::GetEntity('ModuleProperty_EntityValue',array('property_id'=>$oProperty->getId(),'property_type'=>$oProperty->getType(),'target_type'=>$sTargetType,'target_id'=>$iTargetId)));
}
$oProperty->getValue()->setProperty($oProperty);
}
return true;
}
/**
* Сохраняет текущие значения свойств
*
* @param array $aProperties
* @param Entity $oTarget
*/
public function UpdatePropertiesValue($aProperties,$oTarget) {
if ($aProperties) {
foreach($aProperties as $oProperty) {
$oValue=$oProperty->getValue();
$oValue->setTargetId($oTarget->getId());
$oValue->setPropertyType($oProperty->getType());
$oValue->Save();
}
}
}
/**
* Удаление всех свойств у конкретного объекта/сущности
*
* @param Entity $oTarget
*/
public function RemovePropertiesValue($oTarget) {
$aProperties=$this->Property_GetPropertyItemsByFilter(array('target_type'=>$oTarget->getPropertyTargetType()));
if ($aProperties) {
$this->AttachValueForProperties($aProperties,$oTarget->getPropertyTargetType(),$oTarget->getId());
foreach($aProperties as $oProperty) {
$oValue=$oProperty->getValue();
if ($oValue and $oValue->getId()) {
$oValueType=$oValue->getValueTypeObject();
/**
* Кастомное удаление
*/
$oValueType->removeValue();
/**
* Удаляем основные данные
*/
$oValue->Delete();
}
}
}
}
/**
* Валидирует значение свойств у объекта
*
* @param Entity $oTarget
*
* @return bool|string
*/
public function ValidateEntityPropertiesCheck($oTarget) {
/**
* Пробуем получить свойства из реквеста
*/
$oTarget->setProperties($oTarget->getProperties() ? $oTarget->getProperties() : getRequest('property'));
$aPropertiesValue=$oTarget->getProperties();
$aPropertiesResult=array();
/**
* Получаем весь список свойств у объекта
*/
$aPropertiesObject=$this->Property_GetPropertyItemsByFilter(array('target_type'=>$oTarget->getPropertyTargetType()));
$this->Property_AttachValueForProperties($aPropertiesObject,$oTarget->getPropertyTargetType(),$oTarget->getId());
foreach($aPropertiesObject as $oProperty) {
$oValue=$oProperty->getValue();
$sValue=isset($aPropertiesValue[$oProperty->getId()]) ? $aPropertiesValue[$oProperty->getId()] : null;
/**
* Валидируем значение
*/
$oValueType=$oValue->getValueTypeObject();
$oValueType->setValueForValidate($sValue);
if (true===($sRes=$oValueType->validate())) {
$oValueType->setValue($oValueType->getValueForValidate());
$aPropertiesResult[]=$oProperty;
} else {
return $sRes ? $sRes : 'Неверное значение аттрибута: '.$oProperty->getTitle();
}
}
$oTarget->setPropertiesObject($aPropertiesResult);
return true;
}
/**
* Возвращает значение свойсва у объекта
*
* @param Entity $oTarget Объект сущности
* @param int $sPropertyId ID свойства
*
* @return null|mixed
*/
public function GetEntityPropertyValue($oTarget,$sPropertyId) {
if ($oProperty=$this->GetEntityPropertyValueObject($oTarget,$sPropertyId)) {
return $oProperty->getValue()->getValueForDisplay();
}
return null;
}
/**
* Возвращает объект свойства сущности
*
* @param Entity $oTarget Объект сущности
* @param int $sPropertyId ID свойства
*
* @return null|ModuleProperty_EntityProperty
*/
public function GetEntityProperty($oTarget,$sPropertyId) {
if ($oProperty=$this->GetEntityPropertyValueObject($oTarget,$sPropertyId)) {
return $oProperty;
}
return null;
}
/**
* Возвращает список свойств сущности
*
* @param Entity $oTarget Объект сущности
*
* @return array
*/
public function GetEntityPropertyList($oTarget) {
if (!$oTarget->getPropertyIsLoadAll()) {
$aProperties=$this->oMapper->GetPropertiesValueByTarget($oTarget->getPropertyTargetType(),$oTarget->getId());
$this->AttachPropertiesForTarget($oTarget,$aProperties);
}
return $oTarget->_getDataOne('property_list');
}
/**
* Служебный метод для аттача свойст к сущности
*
* @param Entity $oTarget Объект сущности
* @param array $aProperties Список свойств
*/
protected function AttachPropertiesForTarget($oTarget,$aProperties) {
$oTarget->setPropertyList($aProperties);
$oTarget->setPropertyIsLoadAll(true);
$aMapperCode=array();
foreach($aProperties as $oProperty) {
$aMapperCode[$oProperty->getCode()]=$oProperty->getId();
}
$oTarget->setPropertyMapperCode($aMapperCode);
}
/**
* Возвращает объект свойства
*
* @param Entity $oTarget Объект сущности
* @param array $sPropertyId ID свойства
*
* @return null
*/
public function GetEntityPropertyValueObject($oTarget,$sPropertyId) {
if (!$oTarget->getPropertyIsLoadAll()) {
/**
* Загружаем все свойства
*/
$aProperties=$this->oMapper->GetPropertiesValueByTarget($oTarget->getPropertyTargetType(),$oTarget->getId());
$this->AttachPropertiesForTarget($oTarget,$aProperties);
}
if (!is_numeric($sPropertyId)) {
$aMapperCode=$oTarget->getPropertyMapperCode();
if (isset($aMapperCode[$sPropertyId])) {
$sPropertyId=$aMapperCode[$sPropertyId];
} else {
return null;
}
}
$aProperties=$oTarget->getPropertyList();
if (isset($aProperties[$sPropertyId])) {
return $aProperties[$sPropertyId];
}
return null;
}
/**
* Переопределяем метод для возможности цеплять свои кастомные данные при ORM запросах - свойства
*
* @param array $aEntitiesWork
* @param array $aFilter
* @param null|string $sEntityFull
*/
public function RewriteGetItemsByFilter($aEntitiesWork,$aFilter=array(),$sEntityFull=null) {
if (!$aEntitiesWork) {
return;
}
$oEntityFirst=reset($aEntitiesWork);
$sTargetType=$oEntityFirst->getPropertyTargetType();
/**
* Проверяем зарегистрирован ли такой тип
*/
if (!$this->IsAllowTargetType($sTargetType)) {
return;
}
/**
* Проверяем необходимость цеплять свойства
*/
if (isset($aFilter['#properties']) and $aFilter['#properties']) {
$aEntitiesId=array();
foreach($aEntitiesWork as $oEntity) {
$aEntitiesId[]=$oEntity->getId();
}
/**
* Получаем все свойства со значениями для всех объектов
*/
$aResult=$this->oMapper->GetPropertiesValueByTargetArray($sTargetType,$aEntitiesId);
if ($aResult) {
/**
* Формируем список свойств и значений
*/
$aProperties=array();
$aValues=array();
foreach($aResult as $aRow) {
$aPropertyData=array();
$aValueData=array();
foreach($aRow as $k=>$v) {
if (strpos($k,'prop_')===0) {
$aPropertyData[str_replace('prop_','',$k)]=$v;
} else {
$aValueData[$k]=$v;
}
}
if (!isset($aProperties[$aRow['prop_id']])) {
$oProperty=Engine::GetEntity('ModuleProperty_EntityProperty',$aPropertyData);
$aProperties[$aRow['prop_id']]=$oProperty;
}
if ($aRow['target_id']) {
$sKey=$aRow['property_id'].'_'.$aRow['target_id'];
$aValues[$sKey]=Engine::GetEntity('ModuleProperty_EntityValue',$aValueData);
}
}
/**
* Собираем данные
*/
foreach($aEntitiesWork as $oEntity) {
$aPropertiesClone=array();
foreach($aProperties as $oProperty) {
$oPropertyNew=clone $oProperty;
$sKey=$oProperty->getId().'_'.$oEntity->getId();
if (isset($aValues[$sKey])) {
$oValue=$aValues[$sKey];
} else {
$oValue=Engine::GetEntity('ModuleProperty_EntityValue',array('property_type'=>$oProperty->getType(),'property_id'=>$oProperty->getId(),'target_type'=>$oProperty->getTargetType(),'target_id'=>$oEntity->getId()));
}
$oPropertyNew->setValue($oValue);
$oValue->setProperty($oPropertyNew);
$aPropertiesClone[$oPropertyNew->getId()]=$oPropertyNew;
}
$this->AttachPropertiesForTarget($oEntity,$aPropertiesClone);
}
}
}
}
/**
* Обработка фильтра ORM запросов
*
* @param array $aFilter
* @param array $sEntityFull
*
* @return array
*/
public function RewriteFilter($aFilter,$sEntityFull) {
$oEntitySample=Engine::GetEntity($sEntityFull);
if (!isset($aFilter['#join'])) {
$aFilter['#join']=array();
}
$aPropFields=array();
foreach ($aFilter as $k=>$v) {
if (preg_match('@^#prop:(.+)$@i',$k,$aMatch)) {
/**
* Сначала формируем список полей с операндами
*/
$aK=explode(' ',trim($aMatch[1]),2);
$sPropCurrent=$aK[0];
$sConditionCurrent=' = ';
if (count($aK)>1) {
$sConditionCurrent=strtolower($aK[1]);
}
$aPropFields[$sPropCurrent]=array('value'=>$v,'condition'=>$sConditionCurrent);
}
}
/**
* Проверяем на наличие сортировки по полям
*/
$aOrders=array();
if (isset($aFilter['#order'])) {
if(!is_array($aFilter['#order'])) {
$aFilter['#order'] = array($aFilter['#order']);
}
foreach ($aFilter['#order'] as $key=>$value) {
$aKeys=explode(':',$key);
if (count($aKeys)==2 and strtolower($aKeys[0])=='prop') {
$aOrders[$aKeys[1]]=array('way'=>$value,'replace'=>$key);
}
}
}
/**
* Получаем данные по полям
*/
if ($aPropFields) {
$sTargetType=$oEntitySample->getPropertyTargetType();
$aProperties=$this->Property_GetPropertyItemsByFilter(array('code in'=>array_keys($aPropFields),'target_type'=>$sTargetType));
$iPropNum=0;
foreach($aProperties as $oProperty) {
/**
* По каждому полю строим JOIN запрос
*/
$sCondition=$aPropFields[$oProperty->getCode()]['condition'];
$bIsArray=in_array(strtolower($sCondition),array('in','not in')) ? true : false;
if (in_array($oProperty->getType(),array(ModuleProperty::PROPERTY_TYPE_INT,ModuleProperty::PROPERTY_TYPE_CHECKBOX))) {
$sFieldValue="value_int";
$sConditionFull=$sCondition.($bIsArray ? ' (?a) ' : ' ?d ');
} elseif ($oProperty->getType()==ModuleProperty::PROPERTY_TYPE_FLOAT) {
$sFieldValue="value_float";
$sConditionFull=$sCondition.($bIsArray ? ' (?a) ' : ' ?f ');
} elseif (in_array($oProperty->getType(),array(ModuleProperty::PROPERTY_TYPE_VARCHAR,ModuleProperty::PROPERTY_TYPE_TAGS,ModuleProperty::PROPERTY_TYPE_VIDEO_LINK))) {
$sFieldValue="value_varchar";
$sConditionFull=$sCondition.($bIsArray ? ' (?a) ' : ' ? ');
} elseif ($oProperty->getType()==ModuleProperty::PROPERTY_TYPE_TEXT) {
$sFieldValue="value_text";
$sConditionFull=$sCondition.($bIsArray ? ' (?a) ' : ' ? ');
} else {
$sFieldValue="value_varchar";
$sConditionFull=$sCondition.($bIsArray ? ' (?a) ' : ' ? ');
}
$iPropNum++;
$sJoin="JOIN prefix_property_value propv{$iPropNum} ON
t.`{$oEntitySample->_getPrimaryKey()}` = propv{$iPropNum}.target_id and
propv{$iPropNum}.target_type = '{$sTargetType}' and
propv{$iPropNum}.property_id = {$oProperty->getId()} and
propv{$iPropNum}.{$sFieldValue} {$sConditionFull}";
$aFilter['#join'][$sJoin]=array($aPropFields[$oProperty->getCode()]['value']);
/**
* Проверяем на сортировку по текущему полю
*/
if (isset($aOrders[$oProperty->getCode()])) {
$aOrders[$oProperty->getCode()]['field']="propv{$iPropNum}.{$sFieldValue}";
}
}
}
/**
* Подменяем сортировку
*/
foreach($aOrders as $aItem) {
if (isset($aFilter['#order'][$aItem['replace']])) {
$aFilter['#order']=$this->ArrayReplaceKey($aFilter['#order'],$aItem['replace'],$aItem['field']);
}
}
return $aFilter;
}
/**
* Служебный метод для замены ключа в массиве
*
* @param array $aArray
* @param string $sKeyOld
* @param string $sKeyNew
*
* @return array|bool
*/
protected function ArrayReplaceKey($aArray,$sKeyOld,$sKeyNew) {
$aKeys = array_keys($aArray);
if (false === $iIndex = array_search($sKeyOld, $aKeys)) {
return false;
}
$aKeys[$iIndex] = $sKeyNew;
return array_combine($aKeys,array_values($aArray));
}
/**
* Удаляет теги свойства у сущности
*
* @param string $sTargetType Тип объекта сущности
* @param int $iTargetId ID объекта сущности
* @param int $iPropertyId ID свойства
*
* @return mixed
*/
public function RemoveValueTagsByTarget($sTargetType,$iTargetId,$iPropertyId) {
return $this->oMapper->RemoveValueTagsByTarget($sTargetType,$iTargetId,$iPropertyId);
}
/**
* Возвращает список тегов/знаяений свойства. Используется для авкомплиттера тегов.
*
* @param string $sTag
* @param int $iPropertyId
* @param int $iLimit
*
* @return mixed
*/
public function GetPropertyTagsByLike($sTag,$iPropertyId,$iLimit) {
return $this->oMapper->GetPropertyTagsByLike($sTag,$iPropertyId,$iLimit);
}
/**
* Возвращет список группированных тегов с их количеством для необходимого свойства
*
* @param int $iPropertyId
* @param int $iLimit
*
* @return mixed
*/
public function GetPropertyTagsGroup($iPropertyId,$iLimit) {
return $this->oMapper->GetPropertyTagsGroup($iPropertyId,$iLimit);
}
/**
* Формирует и возвращает облако тегов необходимого свойства
*
* @param int $iPropertyId
* @param int $iLimit
*
* @return mixed
*/
public function GetPropertyTagsCloud($iPropertyId,$iLimit) {
$aTags=$this->Property_GetPropertyTagsGroup($iPropertyId,$iLimit);
if ($aTags) {
$this->Tools_MakeCloud($aTags);
}
return $aTags;
}
/**
* Список ID сущностей по тегу конкретного свойства
*
* @param int $iPropertyId
* @param string $sTag
* @param int $iCurrPage
* @param int $iPerPage
*
* @return array
*/
public function GetTargetsByTag($iPropertyId,$sTag,$iCurrPage,$iPerPage) {
return array('collection'=>$this->oMapper->GetTargetsByTag($iPropertyId,$sTag,$iCount,$iCurrPage,$iPerPage),'count'=>$iCount);
}
}

View file

@ -0,0 +1,150 @@
<?php
/**
* LiveStreet CMS
* Copyright © 2013 OOO "ЛС-СОФТ"
*
* ------------------------------------------------------
*
* Official site: www.livestreetcms.com
* Contact e-mail: office@livestreetcms.com
*
* GNU General Public License, version 2:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* ------------------------------------------------------
*
* @link http://www.livestreetcms.com
* @copyright 2013 OOO "ЛС-СОФТ"
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
*
*/
class ModuleProperty_EntityProperty extends EntityORM {
protected $aValidateRules=array(
array('type','check_type','on'=>array('create')),
array('code','regexp','allowEmpty'=>false,'pattern'=>'#^[a-z0-9\_]+$#i','on'=>array('create','update')),
array('title','string','allowEmpty'=>false,'min'=>1,'max'=>250,'on'=>array('create','update')),
array('sort','number','allowEmpty'=>false,'integerOnly'=>true,'min'=>0,'on'=>array('update')),
array('validate_rules_raw','check_validate_rules_raw','on'=>array('update')),
array('params_raw','check_params_raw','on'=>array('update')),
array('title','check_title','on'=>array('create','update')),
);
protected $aRelations=array(
);
public function ValidateCheckType() {
if ($this->Property_IsAllowPropertyType($this->getType())) {
return true;
}
return 'Неверный тип поля';
}
public function ValidateCheckTitle() {
$this->setTitle(htmlspecialchars($this->getTitle()));
return true;
}
public function ValidateCheckValidateRulesRaw() {
$aRulesRaw=$this->getValidateRulesRaw();
/**
* Валидация зависит от типа
*/
$oValue=Engine::GetEntity('ModuleProperty_EntityValue',array('property_type'=>$this->getType(),'property_id'=>$this->getId(),'target_type'=>$this->getTargetType(),'target_id'=>$this->getId()));
$oValueType=$oValue->getValueTypeObject();
$aRules=$oValueType->prepareValidateRulesRaw($aRulesRaw);
$this->setValidateRules($aRules);
return true;
}
public function ValidateCheckParamsRaw() {
$aParamsRaw=$this->getParamsRaw();
/**
* Валидация зависит от типа
*/
$oValue=Engine::GetEntity('ModuleProperty_EntityValue',array('property_type'=>$this->getType(),'property_id'=>$this->getId(),'target_type'=>$this->getTargetType(),'target_id'=>$this->getId()));
$oValueType=$oValue->getValueTypeObject();
$aParams=$oValueType->prepareParamsRaw($aParamsRaw);
$this->setParams($aParams);
return true;
}
protected function beforeSave() {
if ($this->_isNew()) {
$this->setDateCreate(date("Y-m-d H:i:s"));
}
return true;
}
/**
* Возвращает правила валидации поля
*
* @return array
*/
public function getValidateRules() {
$aData=@unserialize($this->_getDataOne('validate_rules'));
if (!$aData) {
$aData=array();
}
return $aData;
}
/**
* Устанавливает правила валидации поля
*
* @param array $aRules
*/
public function setValidateRules($aRules) {
$this->_aData['validate_rules']=@serialize($aRules);
}
/**
* Возвращает список дополнительных параметров поля
*
* @return array|mixed
*/
public function getParams() {
$aData=@unserialize($this->_getDataOne('params'));
if (!$aData) {
$aData=array();
}
return $aData;
}
/**
* Устанавливает список дополнительных параметров поля
*
* @param $aParams
*/
public function setParams($aParams) {
$this->_aData['params']=@serialize($aParams);
}
/**
* Возвращает конкретный параметр поля
*
* @param $sName
*
* @return null
*/
public function getParam($sName) {
$aParams=$this->getParams();
return isset($aParams[$sName]) ? $aParams[$sName] : null;
}
/**
* Возвращает URL админки для редактирования поля
*
* @return string
*/
public function getUrlAdminUpdate() {
return Router::GetPath('admin/properties/'.$this->getTargetType().'/update/'.$this->getId());
}
/**
* Возвращает описание типа поля
*
* @return mixed
*/
public function getTypeTitle() {
/**
* TODO: использовать текстовку из языкового
*/
return $this->getType();
}
}

View file

@ -0,0 +1,73 @@
<?php
/**
* LiveStreet CMS
* Copyright © 2013 OOO "ЛС-СОФТ"
*
* ------------------------------------------------------
*
* Official site: www.livestreetcms.com
* Contact e-mail: office@livestreetcms.com
*
* GNU General Public License, version 2:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* ------------------------------------------------------
*
* @link http://www.livestreetcms.com
* @copyright 2013 OOO "ЛС-СОФТ"
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
*
*/
class ModuleProperty_EntityValue extends EntityORM {
protected $aRelations=array(
);
public function getValueForDisplay() {
$oValueType=$this->getValueTypeObject();
return $oValueType->getValueForDisplay();
}
public function getValueForForm() {
$oValueType=$this->getValueTypeObject();
return $oValueType->getValueForForm();
}
public function getValueTypeObject() {
if (!$this->_getDataOne('value_type_object')) {
$oObject=Engine::GetEntity('ModuleProperty_EntityValueType'.func_camelize($this->getPropertyType()));
$oObject->setValueObject($this);
$this->setValueTypeObject($oObject);
}
return $this->_getDataOne('value_type_object');
}
public function getData() {
$aData=@unserialize($this->_getDataOne('data'));
if (!$aData) {
$aData=array();
}
return $aData;
}
public function setData($aRules) {
$this->_aData['data']=@serialize($aRules);
}
public function getDataOne($sKey) {
$aData=$this->getData();
if (isset($aData[$sKey])) {
return $aData[$sKey];
}
return null;
}
public function setDataOne($sKey,$mValue) {
$aData=$this->getData();
$aData[$sKey]=$mValue;
$this->setData($aData);
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
* LiveStreet CMS
* Copyright © 2013 OOO "ЛС-СОФТ"
*
* ------------------------------------------------------
*
* Official site: www.livestreetcms.com
* Contact e-mail: office@livestreetcms.com
*
* GNU General Public License, version 2:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* ------------------------------------------------------
*
* @link http://www.livestreetcms.com
* @copyright 2013 OOO "ЛС-СОФТ"
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
*
*/
class ModuleProperty_EntityValueTag extends EntityORM {
protected $aRelations=array(
);
}

View file

@ -0,0 +1,85 @@
<?php
/**
* LiveStreet CMS
* Copyright © 2013 OOO "ЛС-СОФТ"
*
* ------------------------------------------------------
*
* Official site: www.livestreetcms.com
* Contact e-mail: office@livestreetcms.com
*
* GNU General Public License, version 2:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* ------------------------------------------------------
*
* @link http://www.livestreetcms.com
* @copyright 2013 OOO "ЛС-СОФТ"
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
*
*/
class ModuleProperty_EntityValueType extends Entity {
public function getValueForDisplay() {
return $this->getValueObject()->getValue();
}
public function getValueForForm() {
return htmlspecialchars($this->getValueObject()->getValue());
}
public function validate() {
return 'Неверное значение';
}
protected function validateStandart($sTypeValidator,$aParamsAdditional=array()) {
$oProperty=$this->getValueObject()->getProperty();
/**
* Получаем параметры валидации
*/
$aParams=$oProperty->getValidateRules();
if (!isset($aParams['label'])) {
$aParams['label']=$oProperty->getTitle();
}
$aParams=array_merge($aParams,$aParamsAdditional);
$oValidator=$this->Validate_CreateValidator($sTypeValidator,$this,null,$aParams);
$oValidator->fields=array('value_for_validate');
$oValidator->validateEntity($this);
if ($this->_hasValidateErrors()) {
return $this->_getValidateError();
} else {
return true;
}
}
public function setValue($mValue) {
$this->resetAllValue();
}
public function resetAllValue() {
$oValue=$this->getValueObject();
$oValue->setValueInt(null);
$oValue->setValueFloat(null);
$oValue->setValueVarchar(null);
$oValue->setValueText(null);
$oValue->setData(null);
/**
* Удаляем из таблицы тегов
*/
$this->Property_RemoveValueTagsByTarget($oValue->getTargetType(),$oValue->getTargetId(),$oValue->getPropertyId());
}
public function prepareValidateRulesRaw($aRulesRaw) {
return array();
}
public function prepareParamsRaw($aParamsRaw) {
return array();
}
public function removeValue() {
}
}

View file

@ -0,0 +1,37 @@
<?php
/**
* LiveStreet CMS
* Copyright © 2013 OOO "ЛС-СОФТ"
*
* ------------------------------------------------------
*
* Official site: www.livestreetcms.com
* Contact e-mail: office@livestreetcms.com
*
* GNU General Public License, version 2:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* ------------------------------------------------------
*
* @link http://www.livestreetcms.com
* @copyright 2013 OOO "ЛС-СОФТ"
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
*
*/
class ModuleProperty_EntityValueTypeCheckbox extends ModuleProperty_EntityValueType {
public function getValueForDisplay() {
return (bool)$this->getValueObject()->getValueInt();
}
public function validate() {
return $this->validateStandart('boolean');
}
public function setValue($mValue) {
$this->resetAllValue();
$oValue=$this->getValueObject();
$oValue->setValueInt($mValue ? 1 : 0);
}
}

View file

@ -0,0 +1,50 @@
<?php
/**
* LiveStreet CMS
* Copyright © 2013 OOO "ЛС-СОФТ"
*
* ------------------------------------------------------
*
* Official site: www.livestreetcms.com
* Contact e-mail: office@livestreetcms.com
*
* GNU General Public License, version 2:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* ------------------------------------------------------
*
* @link http://www.livestreetcms.com
* @copyright 2013 OOO "ЛС-СОФТ"
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
*
*/
class ModuleProperty_EntityValueTypeFloat extends ModuleProperty_EntityValueType {
public function getValueForDisplay() {
return $this->getValueObject()->getValueFloat();
}
public function validate() {
return $this->validateStandart('number',array('integerOnly'=>false));
}
public function setValue($mValue) {
$this->resetAllValue();
$oValue=$this->getValueObject();
$oValue->setValueFloat($mValue ? $mValue : null);
}
public function prepareValidateRulesRaw($aRulesRaw) {
$aRules=array();
$aRules['allowEmpty']=isset($aRulesRaw['allowEmpty']) ? false : true;
if (isset($aRulesRaw['max']) and is_numeric($aRulesRaw['max'])) {
$aRules['max']=(int)$aRulesRaw['max'];
}
if (isset($aRulesRaw['min']) and is_numeric($aRulesRaw['min'])) {
$aRules['min']=(int)$aRulesRaw['min'];
}
return $aRules;
}
}

View file

@ -0,0 +1,50 @@
<?php
/**
* LiveStreet CMS
* Copyright © 2013 OOO "ЛС-СОФТ"
*
* ------------------------------------------------------
*
* Official site: www.livestreetcms.com
* Contact e-mail: office@livestreetcms.com
*
* GNU General Public License, version 2:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* ------------------------------------------------------
*
* @link http://www.livestreetcms.com
* @copyright 2013 OOO "ЛС-СОФТ"
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
*
*/
class ModuleProperty_EntityValueTypeInt extends ModuleProperty_EntityValueType {
public function getValueForDisplay() {
return $this->getValueObject()->getValueInt();
}
public function validate() {
return $this->validateStandart('number',array('integerOnly'=>true));
}
public function setValue($mValue) {
$this->resetAllValue();
$oValue=$this->getValueObject();
$oValue->setValueInt($mValue ? $mValue : null);
}
public function prepareValidateRulesRaw($aRulesRaw) {
$aRules=array();
$aRules['allowEmpty']=isset($aRulesRaw['allowEmpty']) ? false : true;
if (isset($aRulesRaw['max']) and is_numeric($aRulesRaw['max'])) {
$aRules['max']=(int)$aRulesRaw['max'];
}
if (isset($aRulesRaw['min']) and is_numeric($aRulesRaw['min'])) {
$aRules['min']=(int)$aRulesRaw['min'];
}
return $aRules;
}
}

View file

@ -0,0 +1,80 @@
<?php
/**
* LiveStreet CMS
* Copyright © 2013 OOO "ЛС-СОФТ"
*
* ------------------------------------------------------
*
* Official site: www.livestreetcms.com
* Contact e-mail: office@livestreetcms.com
*
* GNU General Public License, version 2:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* ------------------------------------------------------
*
* @link http://www.livestreetcms.com
* @copyright 2013 OOO "ЛС-СОФТ"
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
*
*/
class ModuleProperty_EntityValueTypeTags extends ModuleProperty_EntityValueType {
public function getValueForDisplay() {
return $this->getValueObject()->getValueVarchar();
}
public function validate() {
return $this->validateStandart('tags');
}
public function setValue($mValue) {
$this->resetAllValue();
$oValue=$this->getValueObject();
$oValue->setValueVarchar($mValue ? $mValue : null);
/**
* Заливаем теги в отдельную таблицу
*/
if ($aTags=$this->getTagsArray()) {
foreach($aTags as $sTag) {
$oTag=Engine::GetEntity('ModuleProperty_EntityValueTag');
$oTag->setPropertyId($oValue->getPropertyId());
$oTag->setTargetType($oValue->getTargetType());
$oTag->setTargetId($oValue->getTargetId());
$oTag->setText($sTag);
$oTag->Add();
}
}
}
public function getTagsArray() {
$sTags=$this->getValueObject()->getValueVarchar();
if ($sTags) {
return explode(',',$sTags);
}
return array();
}
public function prepareValidateRulesRaw($aRulesRaw) {
$aRules=array();
$aRules['allowEmpty']=isset($aRulesRaw['allowEmpty']) ? false : true;
if (isset($aRulesRaw['count']) and ($iCount=(int)$aRulesRaw['count']) > 0) {
$aRules['count']=$iCount;
}
return $aRules;
}
public function removeValue() {
$oValue=$this->getValueObject();
/**
* Удаляем теги из дополнительной таблицы
*/
if ($aTags=$this->Property_GetValueTagItemsByFilter(array('property_id'=>$oValue->getPropertyId(),'target_id'=>$oValue->getTargetId()))) {
foreach($aTags as $oTag) {
$oTag->Delete();
}
}
}
}

View file

@ -0,0 +1,70 @@
<?php
/**
* LiveStreet CMS
* Copyright © 2013 OOO "ЛС-СОФТ"
*
* ------------------------------------------------------
*
* Official site: www.livestreetcms.com
* Contact e-mail: office@livestreetcms.com
*
* GNU General Public License, version 2:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* ------------------------------------------------------
*
* @link http://www.livestreetcms.com
* @copyright 2013 OOO "ЛС-СОФТ"
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
*
*/
class ModuleProperty_EntityValueTypeText extends ModuleProperty_EntityValueType {
public function getValueForDisplay() {
return $this->getValueObject()->getValueText();
}
public function getValueForForm() {
$oValue=$this->getValueObject();
return htmlspecialchars($oValue->getDataOne('text_source'));
}
public function validate() {
return $this->validateStandart('string');
}
public function setValue($mValue) {
$this->resetAllValue();
$oValue=$this->getValueObject();
$oProperty=$oValue->getProperty();
$oValue->setDataOne('text_source',$mValue);
if ($oProperty->getParam('use_html')) {
$mValue=$this->Text_Parser($mValue);
} else {
$mValue=htmlspecialchars($mValue);
}
$oValue->setValueText($mValue ? $mValue : null);
}
public function prepareValidateRulesRaw($aRulesRaw) {
$aRules=array();
$aRules['allowEmpty']=isset($aRulesRaw['allowEmpty']) ? false : true;
if (isset($aRulesRaw['max']) and is_numeric($aRulesRaw['max'])) {
$aRules['max']=(int)$aRulesRaw['max'];
}
if (isset($aRulesRaw['min']) and is_numeric($aRulesRaw['min'])) {
$aRules['min']=(int)$aRulesRaw['min'];
}
return $aRules;
}
public function prepareParamsRaw($aParamsRaw) {
$aParams=array();
$aParams['use_html']=isset($aParamsRaw['use_html']) ? true : false;
return $aParams;
}
}

View file

@ -0,0 +1,50 @@
<?php
/**
* LiveStreet CMS
* Copyright © 2013 OOO "ЛС-СОФТ"
*
* ------------------------------------------------------
*
* Official site: www.livestreetcms.com
* Contact e-mail: office@livestreetcms.com
*
* GNU General Public License, version 2:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* ------------------------------------------------------
*
* @link http://www.livestreetcms.com
* @copyright 2013 OOO "ЛС-СОФТ"
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
*
*/
class ModuleProperty_EntityValueTypeVarchar extends ModuleProperty_EntityValueType {
public function getValueForDisplay() {
return $this->getValueObject()->getValueVarchar();
}
public function validate() {
return $this->validateStandart('string');
}
public function setValue($mValue) {
$this->resetAllValue();
$oValue=$this->getValueObject();
$oValue->setValueVarchar($mValue ? htmlspecialchars($mValue) : null);
}
public function prepareValidateRulesRaw($aRulesRaw) {
$aRules=array();
$aRules['allowEmpty']=isset($aRulesRaw['allowEmpty']) ? false : true;
if (isset($aRulesRaw['max']) and is_numeric($aRulesRaw['max'])) {
$aRules['max']=(int)$aRulesRaw['max'];
}
if (isset($aRulesRaw['min']) and is_numeric($aRulesRaw['min'])) {
$aRules['min']=(int)$aRulesRaw['min'];
}
return $aRules;
}
}

View file

@ -0,0 +1,189 @@
<?php
/**
* LiveStreet CMS
* Copyright © 2013 OOO "ЛС-СОФТ"
*
* ------------------------------------------------------
*
* Official site: www.livestreetcms.com
* Contact e-mail: office@livestreetcms.com
*
* GNU General Public License, version 2:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* ------------------------------------------------------
*
* @link http://www.livestreetcms.com
* @copyright 2013 OOO "ЛС-СОФТ"
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
*
*/
class ModuleProperty_EntityValueTypeVideoLink extends ModuleProperty_EntityValueType {
const VIDEO_PROVIDER_YOUTUBE='youtube';
const VIDEO_PROVIDER_VIMEO='vimeo';
const VIDEO_PROVIDER_RUTUBE='rutube';
public function getValueForDisplay() {
return $this->getVideoCodeFrame();
}
public function validate() {
$mRes=$this->validateStandart('url',array('defaultScheme'=>'http'));
if ($mRes===true) {
/**
* Теперь проверяем на принадлежность к разным видео-хостингам
*/
if ($this->getValueForValidate() and !$this->checkVideo($this->getValueForValidate())) {
return 'Необходимо указать корректную ссылку на видео: YouTube, Vimeo';
}
return true;
} else {
return $mRes;
}
}
public function prepareValidateRulesRaw($aRulesRaw) {
$aRules=array();
$aRules['allowEmpty']=isset($aRulesRaw['allowEmpty']) ? false : true;
return $aRules;
}
public function setValue($mValue) {
$this->resetAllValue();
$oValue=$this->getValueObject();
$oValue->setValueVarchar($mValue ? $mValue : null);
/**
* Получаем и сохраняем ссылку на превью
*/
$this->retrievePreview($oValue);
}
protected function retrievePreview($oValue) {
$sLink=$oValue->getValueVarchar();
$sProvider=$this->getVideoProvider($sLink);
$sId=$this->getVideoId($sLink);
if ($sProvider==self::VIDEO_PROVIDER_YOUTUBE) {
$oValue->setDataOne('preview_small',"http://img.youtube.com/vi/{$sId}/default.jpg");
$oValue->setDataOne('preview_normal',"http://img.youtube.com/vi/{$sId}/0.jpg");
} elseif ($sProvider==self::VIDEO_PROVIDER_VIMEO) {
$aRetrieveData=@json_decode(file_get_contents("http://vimeo.com/api/v2/video/{$sId}.json"),true);
if (isset($aRetrieveData[0]['thumbnail_medium'])) {
$oValue->setDataOne('preview_small',$aRetrieveData[0]['thumbnail_medium']);
$oValue->setDataOne('preview_normal',$aRetrieveData[0]['thumbnail_large']);
}
} elseif ($sProvider==self::VIDEO_PROVIDER_RUTUBE) {
$aRetrieveData=@json_decode(file_get_contents("http://rutube.ru/api/video/{$sId}/?format=json"),true);
if (isset($aRetrieveData['thumbnail_url'])) {
$oValue->setDataOne('preview_small',$aRetrieveData['thumbnail_url'].'?size=s');
$oValue->setDataOne('preview_normal',$aRetrieveData['thumbnail_url']);
}
}
}
public function checkVideo($sLink) {
return $this->getVideoId($sLink) ? true : false;
}
public function getVideoId($sLink=null) {
if (is_null($sLink)) {
$sLink=$this->getValueObject()->getValueVarchar();
}
$sProvider=$this->getVideoProvider($sLink);
/**
* youtube
* http://www.youtube.com/watch?v=LZaCb5Y9SyM
* http://youtu.be/LZaCb5Y9SyM
*/
if ($sProvider==self::VIDEO_PROVIDER_YOUTUBE) {
if (preg_match("#(?<=v=)[a-zA-Z0-9-]+(?=&)|(?<=v\/)[^&\n]+|(?<=v=)[^&\n]+|(?<=youtu.be/)[^&\n]+#", $sLink, $aMatch)) {
return $aMatch[0];
}
}
/**
* vimeo
* http://vimeo.com/72359144
*/
if ($sProvider==self::VIDEO_PROVIDER_VIMEO) {
return substr(parse_url($sLink, PHP_URL_PATH), 1);
}
/**
* rutube
* http://rutube.ru/video/ee523c9164c8f9fc8b267c66a0a3adae/
* http://rutube.ru/video/6fd81c1c212c002673280850a1c56415/#.UMQYln9yTWQ
* http://rutube.ru/tracks/6032725.html
* http://rutube.ru/video/embed/6032725
*/
if ($sProvider==self::VIDEO_PROVIDER_RUTUBE) {
if (preg_match('/(?:http|https)+:\/\/(?:www\.|)rutube\.ru\/video\/embed\/([a-zA-Z0-9_\-]+)/i', $sLink, $aMatch) || preg_match('/(?:http|https)+:\/\/(?:www\.|)rutube\.ru\/(?:tracks|video)\/([a-zA-Z0-9_\-]+)(&.+)?/i', $sLink, $aMatch)) {
return $aMatch[1];
}
}
return null;
}
public function getVideoProvider($sLink) {
if (preg_match("#(youtube\.)|(youtu\.be)#i",$sLink)) {
return self::VIDEO_PROVIDER_YOUTUBE;
}
if (preg_match("#(vimeo\.)#i",$sLink)) {
return self::VIDEO_PROVIDER_VIMEO;
}
if (preg_match("#(rutube\.ru)#i",$sLink)) {
return self::VIDEO_PROVIDER_RUTUBE;
}
return null;
}
public function getVideoCodeFrame() {
$sLink=$this->getValueObject()->getValueVarchar();
$sProvider=$this->getVideoProvider($sLink);
$sId=$this->getVideoId($sLink);
if ($sProvider==self::VIDEO_PROVIDER_YOUTUBE) {
return '
<iframe style="max-width: 100%;width: 100%;height: 495px;" src="//www.youtube.com/embed/'.$sId.'" frameborder="0" allowfullscreen></iframe>
';
} elseif ($sProvider==self::VIDEO_PROVIDER_VIMEO) {
return '
<iframe src="http://player.vimeo.com/video/'.$sId.'?title=0&amp;byline=0&amp;portrait=0&amp;badge=0&amp;color=e6ae9e" style="max-width: 100%;width: 100%;height: 495px;" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>
';
} elseif ($sProvider==self::VIDEO_PROVIDER_RUTUBE) {
return '
<iframe src="http://rutube.ru/video/embed/'.$sId.'" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowfullscreen style="max-width: 100%;width: 100%;height: 495px;"></iframe>
';
}
return '';
}
public function getPreview($sType='small') {
$oValue=$this->getValueObject();
return $oValue->getDataOne("preview_{$sType}");
}
public function getCountView() {
$oValue=$this->getValueObject();
$sLink=$oValue->getValueVarchar();
$sProvider=$this->getVideoProvider($sLink);
$sId=$this->getVideoId($sLink);
if ($sProvider==self::VIDEO_PROVIDER_YOUTUBE) {
$iCount=(int)$oValue->getDataOne("count_view");
$iCountViewLastTime=(int)$oValue->getDataOne("count_view_last_time");
if (time()-$iCountViewLastTime > 60*60*1) {
$aData = @json_decode(file_get_contents("https://gdata.youtube.com/feeds/api/videos/{$sId}?v=2&alt=json"),true);
if (isset($aData['entry']['yt$statistics']['viewCount'])) {
$iCount=$aData['entry']['yt$statistics']['viewCount'];
}
$oValue->setDataOne("count_view",$iCount);
$oValue->setDataOne("count_view_last_time",time());
$oValue->Update();
}
return $iCount;
} elseif ($sProvider==self::VIDEO_PROVIDER_VIMEO) {
} elseif ($sProvider==self::VIDEO_PROVIDER_RUTUBE) {
}
return null;
}
}

View file

@ -0,0 +1,197 @@
<?php
/**
* LiveStreet CMS
* Copyright © 2013 OOO "ЛС-СОФТ"
*
* ------------------------------------------------------
*
* Official site: www.livestreetcms.com
* Contact e-mail: office@livestreetcms.com
*
* GNU General Public License, version 2:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* ------------------------------------------------------
*
* @link http://www.livestreetcms.com
* @copyright 2013 OOO "ЛС-СОФТ"
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
*
*/
/**
* Маппер для работы с БД
*
* @package modules.property
* @since 1.0
*/
class ModuleProperty_MapperProperty extends Mapper {
public function GetPropertiesValueByTarget($sTargetType,$iTargetId) {
$sql = "SELECT
v.*,
p.id as prop_id,
p.target_type as prop_target_type,
p.type as prop_type ,
p.code as prop_code,
p.title as prop_title,
p.date_create as prop_date_create,
p.sort as prop_sort
FROM ".Config::Get('db.table.property')." AS p
LEFT JOIN ".Config::Get('db.table.property_value')." as v on ( v.property_id=p.id and v.target_id = ?d )
WHERE
p.target_type = ?
ORDER BY
p.sort desc
limit 0,100";
$aResult = array();
if ($aRows = $this->oDb->select($sql,$iTargetId, $sTargetType)) {
foreach ($aRows as $aRow) {
$aProperty=array();
$aValue=array();
foreach($aRow as $k=>$v) {
if (strpos($k,'prop_')===0) {
$aProperty[str_replace('prop_','',$k)]=$v;
} else {
$aValue[$k]=$v;
}
}
$oProperty=Engine::GetEntity('ModuleProperty_EntityProperty',$aProperty);
/**
* На случай, если нет еще значения свойства в БД
*/
$aValue['property_id']=$oProperty->getId();
$aValue['property_type']=$oProperty->getType();
$aValue['target_type']=$sTargetType;
$aValue['target_id']=$iTargetId;
$oProperty->setValue(Engine::GetEntity('ModuleProperty_EntityValue',$aValue));
$aResult[$oProperty->getId()] = $oProperty;
}
}
return $aResult;
}
public function GetPropertiesValueByTargetArray($sTargetType,$aTargetId) {
if (!is_array($aTargetId)) {
$aTargetId=array($aTargetId);
}
if (!$aTargetId) {
return array();
}
$sql = "SELECT
v.*,
p.id as prop_id,
p.target_type as prop_target_type,
p.type as prop_type ,
p.code as prop_code,
p.title as prop_title,
p.date_create as prop_date_create,
p.sort as prop_sort
FROM ".Config::Get('db.table.property')." AS p
LEFT JOIN ".Config::Get('db.table.property_value')." as v on ( v.property_id=p.id and v.target_id IN ( ?a ) )
WHERE
p.target_type = ?
ORDER BY
p.sort desc ";
$aResult = array();
if ($aRows = $this->oDb->select($sql,$aTargetId, $sTargetType)) {
return $aRows;
}
return $aResult;
}
public function RemoveValueTagsByTarget($sTargetType,$iTargetId,$iPropertyId) {
$sql = "DELETE
FROM ".Config::Get('db.table.property_value_tag')."
WHERE
target_id = ?d
and
target_type = ?
and
property_id = ?d
";
if ($this->oDb->query($sql,$iTargetId, $sTargetType, $iPropertyId)!==false) {
return true;
}
return false;
}
public function GetPropertyTagsByLike($sTag,$iPropertyId,$iLimit) {
$sTag=mb_strtolower($sTag,"UTF-8");
$sql = "SELECT
text
FROM
".Config::Get('db.table.property_value_tag')."
WHERE
property_id = ?d and text LIKE ?
GROUP BY
text
LIMIT 0, ?d
";
$aReturn=array();
if ($aRows=$this->oDb->select($sql,$iPropertyId,$sTag.'%',$iLimit)) {
foreach ($aRows as $aRow) {
$aReturn[]=Engine::GetEntity('ModuleProperty_EntityValueTag',$aRow);
}
}
return $aReturn;
}
public function GetPropertyTagsGroup($iPropertyId,$iLimit) {
$sql = "SELECT
text,
count(text) as count
FROM
".Config::Get('db.table.property_value_tag')."
WHERE
1=1
property_id = ?d
GROUP BY
text
ORDER BY
count desc
LIMIT 0, ?d
";
$aReturn=array();
$aReturnSort=array();
if ($aRows=$this->oDb->select(
$sql,
$iPropertyId,
$iLimit
)
) {
foreach ($aRows as $aRow) {
$aReturn[mb_strtolower($aRow['text'],'UTF-8')]=$aRow;
}
ksort($aReturn);
foreach ($aReturn as $aRow) {
$aReturnSort[]=Engine::GetEntity('ModuleProperty_EntityValueTag',$aRow);
}
}
return $aReturnSort;
}
public function GetTargetsByTag($iPropertyId,$sTag,&$iCount,$iCurrPage,$iPerPage) {
$sql = "
SELECT
target_id
FROM
".Config::Get('db.table.property_value_tag')."
WHERE
property_id = ?d
and
text = ?
ORDER BY target_id DESC
LIMIT ?d, ?d ";
$aReturn=array();
if ($aRows=$this->oDb->selectPage($iCount,$sql,$iPropertyId,$sTag,($iCurrPage-1)*$iPerPage, $iPerPage)) {
foreach ($aRows as $aTopic) {
$aReturn[]=$aTopic['target_id'];
}
}
return $aReturn;
}
}

View file

@ -282,6 +282,9 @@ $config['db']['table']['geo_region'] = '___db.table.prefix___geo_region
$config['db']['table']['geo_city'] = '___db.table.prefix___geo_city';
$config['db']['table']['geo_target'] = '___db.table.prefix___geo_target';
$config['db']['table']['user_changemail'] = '___db.table.prefix___user_changemail';
$config['db']['table']['property'] = '___db.table.prefix___property';
$config['db']['table']['property_value'] = '___db.table.prefix___property_value';
$config['db']['table']['property_value_tag'] = '___db.table.prefix___property_value_tag';
$config['db']['tables']['engine'] = 'InnoDB'; // InnoDB или MyISAM

View file

@ -29,4 +29,76 @@ ADD INDEX ( `category_id` ) ;
ALTER TABLE `prefix_blog` ADD FOREIGN KEY ( `category_id` ) REFERENCES `prefix_blog_category` (
`id`
) ON DELETE CASCADE ON UPDATE CASCADE ;
) ON DELETE CASCADE ON UPDATE CASCADE ;
-- 01-10-2013
--
-- Структура таблицы `prefix_property`
--
CREATE TABLE IF NOT EXISTS `prefix_property` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`target_type` varchar(50) NOT NULL,
`type` enum('int','float','varchar','text','checkbox','select','tags','video_link') NOT NULL DEFAULT 'text',
`code` varchar(50) NOT NULL,
`title` varchar(250) NOT NULL,
`date_create` datetime NOT NULL,
`sort` int(11) NOT NULL,
`validate_rules` varchar(500) DEFAULT NULL,
`params` text,
PRIMARY KEY (`id`),
KEY `target_type` (`target_type`),
KEY `code` (`code`),
KEY `type` (`type`),
KEY `date_create` (`date_create`),
KEY `sort` (`sort`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Структура таблицы `prefix_property_value`
--
CREATE TABLE IF NOT EXISTS `prefix_property_value` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`property_id` int(11) NOT NULL,
`property_type` varchar(30) NOT NULL,
`target_type` varchar(50) NOT NULL,
`target_id` int(11) NOT NULL,
`value_int` int(11) DEFAULT NULL,
`value_float` float(11,2) DEFAULT NULL,
`value_varchar` varchar(250) DEFAULT NULL,
`value_text` text,
`data` text,
PRIMARY KEY (`id`),
KEY `property_id` (`property_id`),
KEY `target_type` (`target_type`),
KEY `target_id` (`target_id`),
KEY `value_int` (`value_int`),
KEY `property_type` (`property_type`),
KEY `value_float` (`value_float`),
KEY `value_varchar` (`value_varchar`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Структура таблицы `prefix_property_value_tag`
--
CREATE TABLE IF NOT EXISTS `prefix_property_value_tag` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`property_id` int(11) NOT NULL,
`target_type` varchar(50) NOT NULL,
`target_id` int(11) NOT NULL,
`text` varchar(50) NOT NULL,
PRIMARY KEY (`id`),
KEY `target_type` (`target_type`),
KEY `target_id` (`target_id`),
KEY `text` (`text`),
KEY `property_id` (`property_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;