mirror of
https://github.com/Oreolek/ifhub.club.git
synced 2024-06-26 03:30:48 +03:00
Наброски нового механизма управления изображениями в топиках
This commit is contained in:
parent
593e2871fb
commit
51b1e75786
|
@ -51,7 +51,7 @@ class ActionAjax extends Action {
|
|||
$this->AddEventPreg('/^vote$/i','/^blog$/','EventVoteBlog');
|
||||
$this->AddEventPreg('/^vote$/i','/^user$/','EventVoteUser');
|
||||
$this->AddEventPreg('/^vote$/i','/^question$/','EventVoteQuestion');
|
||||
$this->AddEventPreg('/^vote/i','/^get/','/^info/','EventVoteGetInfo');
|
||||
$this->AddEventPreg('/^vote$/i','/^get$/','/^info$/','EventVoteGetInfo');
|
||||
|
||||
$this->AddEventPreg('/^favourite$/i','/^save-tags/','EventFavouriteSaveTags');
|
||||
$this->AddEventPreg('/^favourite$/i','/^topic$/','EventFavouriteTopic');
|
||||
|
@ -67,7 +67,7 @@ class ActionAjax extends Action {
|
|||
$this->AddEventPreg('/^blogs$/i','/^get-by-category$/','EventBlogsGetByCategory');
|
||||
|
||||
$this->AddEventPreg('/^preview$/i','/^text$/','EventPreviewText');
|
||||
$this->AddEventPreg('/^preview$/i','/^topic/','EventPreviewTopic');
|
||||
$this->AddEventPreg('/^preview$/i','/^topic$/','EventPreviewTopic');
|
||||
|
||||
$this->AddEventPreg('/^upload$/i','/^image$/','EventUploadImage');
|
||||
|
||||
|
@ -76,10 +76,17 @@ class ActionAjax extends Action {
|
|||
|
||||
$this->AddEventPreg('/^comment$/i','/^delete$/','EventCommentDelete');
|
||||
|
||||
$this->AddEventPreg('/^geo/i','/^get/','/^regions$/','EventGeoGetRegions');
|
||||
$this->AddEventPreg('/^geo/i','/^get/','/^cities/','EventGeoGetCities');
|
||||
$this->AddEventPreg('/^geo$/i','/^get/','/^regions$/','EventGeoGetRegions');
|
||||
$this->AddEventPreg('/^geo$/i','/^get/','/^cities$/','EventGeoGetCities');
|
||||
|
||||
$this->AddEventPreg('/^infobox/i','/^info/','/^blog/','EventInfoboxInfoBlog');
|
||||
$this->AddEventPreg('/^infobox$/i','/^info$/','/^blog$/','EventInfoboxInfoBlog');
|
||||
|
||||
$this->AddEventPreg('/^media$/i','/^upload$/','/^$/','EventMediaUpload');
|
||||
$this->AddEventPreg('/^media$/i','/^generate-target-tmp$/','/^$/','EventMediaGenerateTargetTmp');
|
||||
$this->AddEventPreg('/^media$/i','/^submit-insert$/','/^$/','EventMediaSubmitInsert');
|
||||
$this->AddEventPreg('/^media$/i','/^submit-create-photoset$/','/^$/','EventMediaSubmitCreatePhotoset');
|
||||
$this->AddEventPreg('/^media$/i','/^load-gallery$/','/^$/','EventMediaLoadGallery');
|
||||
$this->AddEventPreg('/^media$/i','/^remove-file$/','/^$/','EventMediaRemoveFile');
|
||||
}
|
||||
|
||||
|
||||
|
@ -88,6 +95,179 @@ class ActionAjax extends Action {
|
|||
**********************************************************************************
|
||||
*/
|
||||
|
||||
protected function EventMediaRemoveFile() {
|
||||
/**
|
||||
* Пользователь авторизован?
|
||||
*/
|
||||
if (!$this->oUserCurrent) {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('need_authorization'),$this->Lang_Get('error'));
|
||||
return;
|
||||
}
|
||||
$sId=getRequestStr('id');
|
||||
if ($oMedia=$this->Media_GetMediaByIdAndUserId($sId,$this->oUserCurrent->getId())) {
|
||||
$this->Media_DeleteFile($oMedia);
|
||||
} else {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('system_error'));
|
||||
}
|
||||
}
|
||||
|
||||
protected function EventMediaLoadGallery() {
|
||||
/**
|
||||
* Пользователь авторизован?
|
||||
*/
|
||||
if (!$this->oUserCurrent) {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('need_authorization'),$this->Lang_Get('error'));
|
||||
return;
|
||||
}
|
||||
|
||||
$sType=getRequestStr('target_type');
|
||||
$sId=getRequestStr('target_id');
|
||||
$sTmp=getRequestStr('target_tmp');
|
||||
|
||||
$aMediaItems=array();
|
||||
if ($sId) {
|
||||
$aMediaItems=$this->Media_GetMediaByTarget($sType,$sId,$this->oUserCurrent->getId());
|
||||
} elseif($sTmp) {
|
||||
$aMediaItems=$this->Media_GetMediaByTargetTmp($sTmp,$this->oUserCurrent->getId());
|
||||
}
|
||||
|
||||
$oViewer=$this->Viewer_GetLocalViewer();
|
||||
$sTemplate='';
|
||||
foreach($aMediaItems as $oMediaItem) {
|
||||
$oViewer->Assign('oMediaItem',$oMediaItem);
|
||||
$sTemplate.=$oViewer->Fetch('modals/modal.upload_image.gallery.item.tpl');
|
||||
}
|
||||
|
||||
$this->Viewer_AssignAjax('sTemplate',$sTemplate);
|
||||
}
|
||||
|
||||
protected function EventMediaSubmitInsert() {
|
||||
$aIds=array(0);
|
||||
foreach((array)getRequest('ids') as $iId) {
|
||||
$aIds[]=(int)$iId;
|
||||
}
|
||||
|
||||
$iUserId=$this->oUserCurrent ? $this->oUserCurrent->getId() : null;
|
||||
|
||||
$aMediaItems=$this->Media_GetMediaItemsByFilter(array(
|
||||
'#where'=>array('id in (?a) AND ( user_id is null OR user_id = ?d )'=>array($aIds,$iUserId))
|
||||
)
|
||||
);
|
||||
if (!$aMediaItems) {
|
||||
$this->Message_AddError('Необходимо выбрать элементы');
|
||||
return false;
|
||||
}
|
||||
|
||||
$aParams=array(
|
||||
'align'=>getRequestStr('align'),
|
||||
'size'=>getRequestStr('size')
|
||||
);
|
||||
|
||||
$sTextResult='';
|
||||
foreach($aMediaItems as $oMedia) {
|
||||
$sTextResult.=$this->Media_BuildCodeForEditor($oMedia,$aParams)."\r\n";
|
||||
}
|
||||
$this->Viewer_AssignAjax('sTextResult',$sTextResult);
|
||||
}
|
||||
|
||||
protected function EventMediaSubmitCreatePhotoset() {
|
||||
$aIds=array(0);
|
||||
foreach((array)getRequest('ids') as $iId) {
|
||||
$aIds[]=(int)$iId;
|
||||
}
|
||||
|
||||
$iUserId=$this->oUserCurrent ? $this->oUserCurrent->getId() : null;
|
||||
|
||||
$aMediaItems=$this->Media_GetMediaItemsByFilter(array(
|
||||
'#where'=>array('id in (?a) AND ( user_id is null OR user_id = ?d )'=>array($aIds,$iUserId))
|
||||
)
|
||||
);
|
||||
if (!$aMediaItems) {
|
||||
$this->Message_AddError('Необходимо выбрать элементы');
|
||||
return false;
|
||||
}
|
||||
|
||||
$aParams=array(
|
||||
'size'=>'100crop',
|
||||
);
|
||||
$sTextResult='<div class="fotorama" data-nav="thumbs">'."\r\n";
|
||||
foreach($aMediaItems as $oMedia) {
|
||||
$sTextResult.="\t".$this->Media_BuildCodeForEditor($oMedia,$aParams)."\r\n";
|
||||
}
|
||||
$sTextResult.="</div>\r\n";
|
||||
$this->Viewer_AssignAjax('sTextResult',$sTextResult);
|
||||
}
|
||||
|
||||
protected function EventMediaGenerateTargetTmp() {
|
||||
$sType=getRequestStr('type');
|
||||
if ($this->Media_IsAllowTargetType($sType)) {
|
||||
$sTmp=func_generator();
|
||||
setcookie('media_target_tmp_'.$sType,$sTmp, time()+24*3600,Config::Get('sys.cookie.path'),Config::Get('sys.cookie.host'));
|
||||
$this->Viewer_AssignAjax('sTmpKey',$sTmp);
|
||||
}
|
||||
}
|
||||
|
||||
protected function EventMediaUpload() {
|
||||
if (getRequest('is_iframe')) {
|
||||
$this->Viewer_SetResponseAjax('jsonIframe', false);
|
||||
} else {
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
}
|
||||
/**
|
||||
* Пользователь авторизован?
|
||||
*/
|
||||
if (!$this->oUserCurrent) {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('need_authorization'),$this->Lang_Get('error'));
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Файл был загружен?
|
||||
*/
|
||||
if (!isset($_FILES['filedata']['tmp_name'])) {
|
||||
$this->Message_AddError($this->Lang_Get('system_error'), $this->Lang_Get('error'));
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Проверяем корректность target'а
|
||||
*/
|
||||
$sTargetType=getRequestStr('target_type');
|
||||
$sTargetId=getRequestStr('target_id');
|
||||
|
||||
$sTargetTmp=empty($_COOKIE['media_target_tmp_'.$sTargetType]) ? getRequestStr('target_tmp') : $_COOKIE['media_target_tmp_'.$sTargetType];
|
||||
if ($sTargetId) {
|
||||
$sTargetTmp=null;
|
||||
if (!$this->Media_CheckTarget($sTargetType,$sTargetId)) {
|
||||
$this->Message_AddError($this->Lang_Get('system_error'), $this->Lang_Get('error'));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$sTargetId=null;
|
||||
if (!$sTargetTmp or !$this->Media_IsAllowTargetType($sTargetType)) {
|
||||
$this->Message_AddError($this->Lang_Get('system_error'), $this->Lang_Get('error'));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: необходима проверка на максимальное общее количество файлов, на максимальный размер файла
|
||||
* Эти настройки можно хранить в конфиге: module.media.type.topic.max_file_count=30 и т.п.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Выполняем загрузку файла
|
||||
*/
|
||||
if ($mResult=$this->Media_Upload($_FILES['filedata'],$sTargetType,$sTargetId,$sTargetTmp) and is_object($mResult)) {
|
||||
$oViewer=$this->Viewer_GetLocalViewer();
|
||||
$oViewer->Assign('oMediaItem',$mResult);
|
||||
|
||||
$sTemplateFile=$oViewer->Fetch('modals/modal.upload_image.gallery.item.tpl');
|
||||
|
||||
$this->Viewer_AssignAjax('sTemplateFile',$sTemplateFile);
|
||||
} else {
|
||||
$this->Message_AddError(is_string($mResult) ? $mResult : $this->Lang_Get('system_error'), $this->Lang_Get('error'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Вывод информации о блоге
|
||||
*/
|
||||
|
|
|
@ -348,6 +348,18 @@ class ActionTopic extends Action {
|
|||
* Обновляем количество топиков в блоге
|
||||
*/
|
||||
$this->Blog_RecalculateCountTopicByBlogId($oTopic->getBlogId());
|
||||
/**
|
||||
* Фиксируем ID у media файлов топика
|
||||
*/
|
||||
if (isset($_COOKIE['media_target_tmp_topic']) and is_string($_COOKIE['media_target_tmp_topic'])) {
|
||||
$aTargetItems=$this->Media_GetTargetItemsByTargetTmpAndTargetType($_COOKIE['media_target_tmp_topic'],'topic');
|
||||
foreach($aTargetItems as $oTarget) {
|
||||
$oTarget->setTargetTmp(null);
|
||||
$oTarget->setTargetId($oTopic->getId());
|
||||
$oTarget->Update();
|
||||
}
|
||||
}
|
||||
setcookie('media_target_tmp_topic',null);
|
||||
/**
|
||||
* Добавляем автора топика в подписчики на новые комментарии к этому топику
|
||||
*/
|
||||
|
|
397
application/classes/modules/media/Media.class.php
Normal file
397
application/classes/modules/media/Media.class.php
Normal file
|
@ -0,0 +1,397 @@
|
|||
<?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 ModuleMedia extends ModuleORM {
|
||||
/**
|
||||
* Список типов медиа
|
||||
* Свои кастомные типы необходимо нумеровать с 1000
|
||||
*/
|
||||
const TYPE_IMAGE=1;
|
||||
const TYPE_VIDEO=2;
|
||||
|
||||
/**
|
||||
* Объект текущего пользователя
|
||||
*
|
||||
* @var ModuleUser_EntityUser|null
|
||||
*/
|
||||
protected $oUserCurrent;
|
||||
|
||||
protected $oMapper=null;
|
||||
|
||||
protected $aTargetTypes=array(
|
||||
'topic'=>array(),
|
||||
);
|
||||
|
||||
/**
|
||||
* Список доступных типов медиа
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $aMediaTypes=array(
|
||||
self::TYPE_IMAGE,self::TYPE_VIDEO
|
||||
);
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*
|
||||
*/
|
||||
public function Init() {
|
||||
parent::Init();
|
||||
$this->oMapper=Engine::GetMapper(__CLASS__);
|
||||
$this->oUserCurrent=$this->User_GetUserCurrent();
|
||||
}
|
||||
/**
|
||||
* Возвращает список типов объектов
|
||||
*
|
||||
* @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 $sTargetType
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetTargetTypeParams($sTargetType) {
|
||||
if ($this->IsAllowTargetType($sTargetType)) {
|
||||
return $this->aTargetTypes[$sTargetType];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Проверяет разрешен ли тип медиа
|
||||
*
|
||||
* @param string $sType
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowMediaType($sType) {
|
||||
return in_array($sType,$this->aMediaTypes);
|
||||
}
|
||||
/**
|
||||
* Проверка объекта target - владелец медиа
|
||||
*
|
||||
* @param string $sTargetType Тип
|
||||
* @param int $iTargetId ID владельца
|
||||
* @return bool
|
||||
*/
|
||||
public function CheckTarget($sTargetType,$iTargetId) {
|
||||
if (!$this->IsAllowTargetType($sTargetType)) {
|
||||
return false;
|
||||
}
|
||||
$sMethod = 'CheckTarget'.func_camelize($sTargetType);
|
||||
if (method_exists($this,$sMethod)) {
|
||||
return $this->$sMethod($iTargetId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function Upload($aFile,$sTargetType,$sTargetId,$sTargetTmp=null) {
|
||||
if (is_string($aFile)) {
|
||||
return $this->UploadUrl($aFile,$sTargetType,$sTargetId,$sTargetTmp);
|
||||
} else {
|
||||
return $this->UploadLocal($aFile,$sTargetType,$sTargetId,$sTargetTmp);
|
||||
}
|
||||
}
|
||||
|
||||
public function UploadLocal($aFile,$sTargetType,$sTargetId,$sTargetTmp=null) {
|
||||
if(!is_array($aFile) || !isset($aFile['tmp_name']) || !isset($aFile['name'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$aPathInfo=pathinfo($aFile['name']);
|
||||
$sExtension=isset($aPathInfo['extension']) ? $aPathInfo['extension'] : 'unknown';
|
||||
$sFileName = $aPathInfo['filename'].'.'.$sExtension;
|
||||
/**
|
||||
* Копируем загруженный файл
|
||||
*/
|
||||
$sDirTmp=Config::Get('path.tmp.server').'/media/';
|
||||
if (!is_dir($sDirTmp)) {
|
||||
@mkdir($sDirTmp,0777,true);
|
||||
}
|
||||
$sFileTmp=$sDirTmp.$sFileName;
|
||||
if (!move_uploaded_file($aFile['tmp_name'],$sFileTmp)) {
|
||||
return 'Не удалось загрузить файл';
|
||||
}
|
||||
/**
|
||||
* TODO: проверить на размер файла в байтах
|
||||
*/
|
||||
|
||||
return $this->ProcessingFile($sFileTmp,$sTargetType,$sTargetId,$sTargetTmp);
|
||||
}
|
||||
|
||||
public function UploadUrl($sFileUrl,$sTargetType,$sTargetId,$sTargetTmp=null) {
|
||||
/**
|
||||
* TODO: сделать загрузку по урлу
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
public function ProcessingFile($sFileTmp,$sTargetType,$sTargetId,$sTargetTmp=null) {
|
||||
/**
|
||||
* Определяем тип файла по расширенияю и запускаем обработку
|
||||
*/
|
||||
$aPathInfo=pathinfo($sFileTmp);
|
||||
$sExtension=strtolower($aPathInfo['extension']);
|
||||
if (in_array($sExtension,array('jpg','jpeg','gif','png'))) {
|
||||
return $this->ProcessingFileImage($sFileTmp,$sTargetType,$sTargetId,$sTargetTmp);
|
||||
}
|
||||
return 'Неверный тип файла';
|
||||
}
|
||||
|
||||
public function ProcessingFileImage($sFileTmp,$sTargetType,$sTargetId,$sTargetTmp=null) {
|
||||
$aPathInfo=pathinfo($sFileTmp);
|
||||
$aParams=$this->Image_BuildParams('media.'.$sTargetType);
|
||||
$oImage =$this->Image_CreateImageObject($sFileTmp);
|
||||
/**
|
||||
* Если объект изображения не создан, возвращаем ошибку
|
||||
*/
|
||||
if($sError=$oImage->get_last_error()) {
|
||||
@unlink($sFileTmp);
|
||||
return $sError;
|
||||
}
|
||||
/**
|
||||
* Превышает максимальные размеры из конфига
|
||||
*/
|
||||
if (($oImage->get_image_params('width')>Config::Get('module.media.image_max_width')) or ($oImage->get_image_params('height')>Config::Get('module.media.image_max_height'))) {
|
||||
@unlink($sFileTmp);
|
||||
return 'Превышен максимальный размер изображения';
|
||||
}
|
||||
$iWidth=$oImage->get_image_params('width');
|
||||
$iHeight=$oImage->get_image_params('height');
|
||||
$sPath=$this->GetSaveDir($sTargetType,$sTargetId);
|
||||
if (!is_dir(Config::Get('path.root.server').$sPath)) {
|
||||
@mkdir(Config::Get('path.root.server').$sPath,0777,true);
|
||||
}
|
||||
/**
|
||||
* Копируем файл в нужный каталог
|
||||
*/
|
||||
$sFileName=func_generator(20);
|
||||
$sFilePath=Config::Get('path.root.server').$sPath.$sFileName.'.'.$oImage->get_image_params('format');
|
||||
rename($sFileTmp,$sFilePath);
|
||||
|
||||
$aSizes=Config::Get("module.media.type.{$sTargetType}.image_sizes");
|
||||
if (!$aSizes) {
|
||||
$aSizes=Config::Get("module.media.image_sizes");
|
||||
}
|
||||
foreach ($aSizes as $aSize) {
|
||||
/**
|
||||
* Для каждого указанного в конфиге размера генерируем картинку
|
||||
*/
|
||||
$sNewFileName = $sFileName.'_'.$aSize['w'];
|
||||
$oImage = $this->Image_CreateImageObject($sFilePath);
|
||||
if ($aSize['crop']) {
|
||||
$this->Image_CropProportion($oImage, $aSize['w'], $aSize['h'], true);
|
||||
$sNewFileName .= 'crop';
|
||||
}
|
||||
$this->Image_Resize($sFilePath,$sPath,$sNewFileName,Config::Get('module.media.image_max_width'),Config::Get('module.media.image_max_height'),$aSize['w'],$aSize['h'],true,$aParams,$oImage);
|
||||
}
|
||||
/**
|
||||
* Сохраняем медиа
|
||||
*/
|
||||
$oMedia=Engine::GetEntity('ModuleMedia_EntityMedia');
|
||||
$oMedia->setUserId($this->oUserCurrent ? $this->oUserCurrent->getId() : null);
|
||||
$oMedia->setType(self::TYPE_IMAGE);
|
||||
$oMedia->setFilePath($this->Image_GetWebPath($sFilePath));
|
||||
$oMedia->setFileName($aPathInfo['filename']);
|
||||
$oMedia->setFileSize(filesize($sFilePath));
|
||||
$oMedia->setWidth($iWidth);
|
||||
$oMedia->setHeight($iHeight);
|
||||
$oMedia->setDataOne('image_sizes',$aSizes);
|
||||
if ($oMedia->Add()) {
|
||||
/**
|
||||
* Создаем связь с владельцем
|
||||
*/
|
||||
$oTarget=Engine::GetEntity('ModuleMedia_EntityTarget');
|
||||
$oTarget->setMediaId($oMedia->getId());
|
||||
$oTarget->setTargetType($sTargetType);
|
||||
$oTarget->setTargetId($sTargetId ? $sTargetId : null);
|
||||
$oTarget->setTargetTmp($sTargetTmp ? $sTargetTmp : null);
|
||||
if ($oTarget->Add()) {
|
||||
return $oMedia;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Возвращает каталог для сохранения контента медиа
|
||||
*
|
||||
* @param string $sTargetType
|
||||
* @param string|null $sTargetId Желательно для одного типа при формировании каталога для загрузки выбрать что-то одно - использовать $sTargetId или нет
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetSaveDir($sTargetType,$sTargetId=null) {
|
||||
return Config::Get('path.uploads.base')."/media/{$sTargetType}/".date('Y/m/d/H/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка владельца с типом "topic"
|
||||
* Название метода формируется автоматически
|
||||
*
|
||||
* @param int $iTargetId ID владельца
|
||||
* @return bool
|
||||
*/
|
||||
public function CheckTargetTopic($iTargetId) {
|
||||
if ($oTopic=$this->Topic_GetTopicById($iTargetId)) {
|
||||
/**
|
||||
* Проверяем права на редактирование топика
|
||||
*/
|
||||
if ($this->ACL_IsAllowEditTopic($oTopic,$this->oUserCurrent)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function BuildCodeForEditor($oMedia,$aParams) {
|
||||
$sCode='';
|
||||
if ($oMedia->getType()==self::TYPE_IMAGE) {
|
||||
$aSizes=(array)$oMedia->getDataOne('image_sizes');
|
||||
|
||||
$sSizeParam=isset($aParams['size']) ? (string)$aParams['size'] : '';
|
||||
$sSize='original';
|
||||
$bNeedHref=false;
|
||||
/**
|
||||
* Проверяем корректность размера
|
||||
*/
|
||||
foreach($aSizes as $aSizeAllow) {
|
||||
$sSizeKey=$aSizeAllow['w'].($aSizeAllow['crop'] ? 'crop' : '');
|
||||
if ($sSizeKey==$sSizeParam) {
|
||||
$sSize=$sSizeKey;
|
||||
/**
|
||||
* Необходимость лайтбокса
|
||||
*/
|
||||
if ($aSizeAllow['w']<$oMedia->getWidth()) {
|
||||
$bNeedHref=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$sPath=$oMedia->getFileWebPath($sSize=='original' ? null : $sSize);
|
||||
|
||||
$sCode='<img src="'.$sPath.'" ';
|
||||
if ($oMedia->getDataOne('title')) {
|
||||
$sCode.=' title="'.htmlspecialchars($oMedia->getDataOne('title')).'" ';
|
||||
$sCode.=' alt="'.htmlspecialchars($oMedia->getDataOne('title')).'" ';
|
||||
}
|
||||
if (isset($aParams['align']) and in_array($aParams['align'],array('left','right','center'))) {
|
||||
if ($aParams['align'] == 'center') {
|
||||
$sCode.=' class="image-center"';
|
||||
} else {
|
||||
$sCode.=' align="'.htmlspecialchars($aParams['align']).'" ';
|
||||
}
|
||||
}
|
||||
$sCode.=' />';
|
||||
if ($bNeedHref) {
|
||||
$sCode='<a href="'.$oMedia->getFileWebPath().'">'.$sCode.'</a>';
|
||||
}
|
||||
}
|
||||
|
||||
return $sCode;
|
||||
}
|
||||
|
||||
public function BuildHTML($sPath,$aParams) {
|
||||
$sText='<img src="'.$sPath.'" ';
|
||||
if (isset($aParams['title']) and $aParams['title']!='') {
|
||||
$sText.=' title="'.htmlspecialchars($aParams['title']).'" ';
|
||||
/**
|
||||
* Если не определен ALT заполняем его тайтлом
|
||||
*/
|
||||
if(!isset($aParams['alt'])) $aParams['alt']=$aParams['title'];
|
||||
}
|
||||
if (isset($aParams['align']) and in_array($aParams['align'],array('left','right','center'))) {
|
||||
if ($aParams['align'] == 'center') {
|
||||
$sText.=' class="image-center"';
|
||||
} else {
|
||||
$sText.=' align="'.htmlspecialchars($aParams['align']).'" ';
|
||||
}
|
||||
}
|
||||
$sAlt = isset($aParams['alt'])
|
||||
? ' alt="'.htmlspecialchars($aParams['alt']).'"'
|
||||
: ' alt=""';
|
||||
$sText.=$sAlt.' />';
|
||||
|
||||
return $sText;
|
||||
}
|
||||
|
||||
public function GetMediaByTarget($sTargetType,$iTargetId,$iUserId=null) {
|
||||
return $this->oMapper->GetMediaByTarget($sTargetType,$iTargetId,$iUserId);
|
||||
}
|
||||
|
||||
public function GetMediaByTargetTmp($sTargetTmp,$iUserId=null) {
|
||||
return $this->oMapper->GetMediaByTargetTmp($sTargetTmp,$iUserId);
|
||||
}
|
||||
|
||||
public function DeleteFile($oMedia) {
|
||||
/**
|
||||
* Сначала удаляем все файлы
|
||||
*/
|
||||
if ($oMedia->getType()==self::TYPE_IMAGE) {
|
||||
$aSizes=$oMedia->getDataOne('image_sizes');
|
||||
foreach($aSizes as $aSize) {
|
||||
$sSize = $aSize['w'];
|
||||
if ($aSize['crop']) {
|
||||
$sSize.='crop';
|
||||
}
|
||||
$this->Image_RemoveFile($this->Image_GetServerPath($oMedia->getFileWebPath($sSize)));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Удаляем все связи
|
||||
*/
|
||||
$aTargets=$oMedia->getTargets();
|
||||
foreach($aTargets as $oTarget) {
|
||||
$oTarget->Delete();
|
||||
}
|
||||
|
||||
return $oMedia->Delete();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
<?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 ModuleMedia_EntityMedia extends EntityORM {
|
||||
|
||||
protected $aValidateRules=array(
|
||||
|
||||
);
|
||||
|
||||
protected $aRelations=array(
|
||||
'targets' => array(self::RELATION_TYPE_HAS_MANY,'ModuleMedia_EntityTarget','media_id'),
|
||||
);
|
||||
|
||||
protected function beforeSave() {
|
||||
if ($this->_isNew()) {
|
||||
$this->setDateAdd(date("Y-m-d H:i:s"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getFileWebPath($sWidth = null) {
|
||||
if ($this->getFilePath()) {
|
||||
if ($sWidth) {
|
||||
$aPathInfo=pathinfo($this->getFilePath());
|
||||
return $aPathInfo['dirname'].'/'.$aPathInfo['filename'].'_'.$sWidth.'.'.$aPathInfo['extension'];
|
||||
} else {
|
||||
return $this->getFilePath();
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<?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 ModuleMedia_EntityTarget extends EntityORM {
|
||||
|
||||
protected $aValidateRules=array(
|
||||
|
||||
);
|
||||
|
||||
protected $aRelations=array(
|
||||
|
||||
);
|
||||
|
||||
protected function beforeSave() {
|
||||
if ($this->_isNew()) {
|
||||
$this->setDateAdd(date("Y-m-d H:i:s"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
<?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.media
|
||||
* @since 1.0
|
||||
*/
|
||||
class ModuleMedia_MapperMedia extends Mapper {
|
||||
|
||||
public function GetMediaByTarget($sTargetType,$iTargetId,$iUserId=null) {
|
||||
$sql = "SELECT
|
||||
m.*
|
||||
FROM ".Config::Get('db.table.media_target')." AS t
|
||||
JOIN ".Config::Get('db.table.media')." as m on ( m.id=t.media_id { and m.user_id = ?d } )
|
||||
WHERE
|
||||
t.target_id = ?d
|
||||
AND
|
||||
t.target_type = ?
|
||||
ORDER BY
|
||||
m.id desc
|
||||
limit 0,500";
|
||||
|
||||
$aResult = array();
|
||||
if ($aRows = $this->oDb->select($sql,$iUserId ? $iUserId : DBSIMPLE_SKIP,$iTargetId, $sTargetType)) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aResult[]=Engine::GetEntity('ModuleMedia_EntityMedia',$aRow);
|
||||
}
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
public function GetMediaByTargetTmp($sTargetTmp,$iUserId=null) {
|
||||
$sql = "SELECT
|
||||
m.*
|
||||
FROM ".Config::Get('db.table.media_target')." AS t
|
||||
JOIN ".Config::Get('db.table.media')." as m on ( m.id=t.media_id { and m.user_id = ?d } )
|
||||
WHERE
|
||||
t.target_tmp = ?
|
||||
ORDER BY
|
||||
m.id desc
|
||||
limit 0,500";
|
||||
|
||||
$aResult = array();
|
||||
if ($aRows = $this->oDb->select($sql,$iUserId ? $iUserId : DBSIMPLE_SKIP,$sTargetTmp)) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aResult[]=Engine::GetEntity('ModuleMedia_EntityMedia',$aRow);
|
||||
}
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
}
|
|
@ -228,6 +228,34 @@ $config['module']['topic']['photoset']['size'] = array( // спис
|
|||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Модуль Media
|
||||
*/
|
||||
$config['module']['media']['image_max_width'] = 5000; // Максимальный размер изображения по ширине
|
||||
$config['module']['media']['image_max_height'] = 5000; // Максимальный размер изображения по высоте
|
||||
$config['module']['media']['image_sizes'] = array( // список размеров, которые необходимо делать при загрузке изображения
|
||||
array(
|
||||
'w' => 1000,
|
||||
'h' => null,
|
||||
'crop' => false,
|
||||
),
|
||||
array(
|
||||
'w' => 500,
|
||||
'h' => null,
|
||||
'crop' => false,
|
||||
),
|
||||
array(
|
||||
'w' => 100,
|
||||
'h' => 100,
|
||||
'crop' => true,
|
||||
),
|
||||
array(
|
||||
'w' => 50,
|
||||
'h' => 50,
|
||||
'crop' => true,
|
||||
)
|
||||
);
|
||||
|
||||
// Какие модули должны быть загружены на старте
|
||||
$config['module']['autoLoad'] = array('Hook','Cache','Security','Session','Lang','Message','User');
|
||||
/**
|
||||
|
@ -288,6 +316,8 @@ $config['db']['table']['property_select'] = '___db.table.prefix___property_se
|
|||
$config['db']['table']['property_value'] = '___db.table.prefix___property_value';
|
||||
$config['db']['table']['property_value_tag'] = '___db.table.prefix___property_value_tag';
|
||||
$config['db']['table']['property_value_select'] = '___db.table.prefix___property_value_select';
|
||||
$config['db']['table']['media'] = '___db.table.prefix___media';
|
||||
$config['db']['table']['media_target'] = '___db.table.prefix___media_target';
|
||||
|
||||
$config['db']['tables']['engine'] = 'InnoDB'; // InnoDB или MyISAM
|
||||
|
||||
|
@ -441,6 +471,7 @@ $config['head']['default']['js'] = array(
|
|||
"___path.framework.frontend.web___/js/vendor/jquery.placeholder.min.js",
|
||||
"___path.framework.frontend.web___/js/vendor/jquery.charcount.js",
|
||||
"___path.framework.frontend.web___/js/vendor/jquery.imagesloaded.js",
|
||||
"___path.framework.frontend.web___/js/vendor/jquery.fileupload.js",
|
||||
"___path.framework.frontend.web___/js/vendor/notifier/jquery.notifier.js",
|
||||
"___path.framework.frontend.web___/js/vendor/prettify/prettify.js",
|
||||
"___path.framework.frontend.web___/js/vendor/prettyphoto/js/jquery.prettyphoto.js",
|
||||
|
@ -493,6 +524,7 @@ $config['head']['default']['js'] = array(
|
|||
"___path.application.web___/frontend/common/js/admin.js",
|
||||
"___path.application.web___/frontend/common/js/userfield.js",
|
||||
"___path.application.web___/frontend/common/js/captcha.js",
|
||||
"___path.application.web___/frontend/common/js/media.js",
|
||||
"___path.application.web___/frontend/common/js/init.js",
|
||||
|
||||
"http://yandex.st/share/share.js" => array('merge'=>false),
|
||||
|
|
321
application/frontend/common/js/media.js
Normal file
321
application/frontend/common/js/media.js
Normal file
|
@ -0,0 +1,321 @@
|
|||
/**
|
||||
* Фотосет
|
||||
*
|
||||
* @module ls/media
|
||||
*
|
||||
* @license GNU General Public License, version 2
|
||||
* @copyright 2013 OOO "ЛС-СОФТ" {@link http://livestreetcms.com}
|
||||
* @author Denis Shakhov <denis.shakhov@gmail.com>
|
||||
*/
|
||||
|
||||
var ls = ls || {};
|
||||
|
||||
ls.media =( function ($) {
|
||||
|
||||
var _defaultsFileupload = {
|
||||
url: aRouter['ajax']+"media/upload/",
|
||||
sequentialUploads: false,
|
||||
singleFileUploads: true,
|
||||
limitConcurrentUploads: 3
|
||||
};
|
||||
|
||||
var _defaults = {
|
||||
target_type: '',
|
||||
target_id: '',
|
||||
target_tmp: '',
|
||||
fileupload: _defaultsFileupload
|
||||
};
|
||||
|
||||
this.mode='insert';
|
||||
|
||||
this.setMode = function(mode) {
|
||||
this.mode=mode;
|
||||
this.showSettingsMode();
|
||||
};
|
||||
|
||||
this.showSettingsMode = function($item) {
|
||||
$('.js-media-settings-mode').hide();
|
||||
/**
|
||||
* Показываем только если есть выделенные элементы
|
||||
*/
|
||||
if (this.getSelected().length) {
|
||||
$('#media-settings-mode-'+this.mode).show();
|
||||
$item=$item || this.getCurrent();
|
||||
/**
|
||||
* Выставляем настройки по вставке медиа
|
||||
*/
|
||||
var $select=$('select[name=size]').html('');
|
||||
var sizes=$item.data('mediaImageSizes');
|
||||
$.each(sizes,function(k,v){
|
||||
/**
|
||||
* Расчитываем пропорциональную высоту изображения
|
||||
*/
|
||||
var height=v.h;
|
||||
if (!v.h) {
|
||||
height=parseInt(v.w*$item.data('mediaHeight')/$item.data('mediaWidth'));
|
||||
}
|
||||
$select.append('<option value="'+ v.w +(v.crop ? 'crop' : '')+'">'+v.w+' × '+height+'</option>');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.hideSettingsMode = function() {
|
||||
$('.js-media-settings-mode').hide();
|
||||
};
|
||||
|
||||
this.initUpload = function(options) {
|
||||
this.options = $.extend(true, {}, _defaults, options);
|
||||
|
||||
this.options.target_tmp=this.options.target_tmp ? this.options.target_tmp : $.cookie('media_target_tmp_'+this.options.target_type);
|
||||
if (!this.options.target_id && !this.options.target_tmp) {
|
||||
ls.media.generateTargetTmp(this.options.target_type);
|
||||
}
|
||||
|
||||
var params=this.options.fileupload;
|
||||
params.formData=$.extend({}, params.formData || {}, {
|
||||
security_ls_key: LIVESTREET_SECURITY_KEY,
|
||||
target_type: this.options.target_type,
|
||||
target_id: this.options.target_id,
|
||||
target_tmp: this.options.target_tmp
|
||||
});
|
||||
$.each(params.formData,function(k,v){
|
||||
if (v==null) {
|
||||
params.formData[k]='';
|
||||
}
|
||||
});
|
||||
$('.js-media-upload-file').fileupload(params);
|
||||
|
||||
|
||||
$('.js-media-upload-file').bind('fileuploadadd',function(e,data) {
|
||||
ls.media.addPreload(data);
|
||||
});
|
||||
$('.js-media-upload-file').bind('fileuploaddone',function(e,data) {
|
||||
if (data.result.bStateError) {
|
||||
ls.media.addFileError(data.context,data.result);
|
||||
} else {
|
||||
ls.media.addFile(data.context,data.result);
|
||||
}
|
||||
});
|
||||
$('.js-media-upload-file').bind('fileuploadprogress',function(e,data) {
|
||||
data.context.html(parseInt(data.loaded / data.total * 100, 10)+'%');
|
||||
});
|
||||
|
||||
this.loadGallery();
|
||||
this.bindFileEvents();
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*/
|
||||
this.init = function() {
|
||||
|
||||
};
|
||||
|
||||
this.removeCurrentFile = function() {
|
||||
var $item=this.getCurrent();
|
||||
if ($item.length) {
|
||||
return this.removeFile($item.data('mediaId'));
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.removeFile = function(id) {
|
||||
$this=this;
|
||||
ls.ajax.load(aRouter['ajax']+"media/remove-file/", { id: id }, function(result) {
|
||||
$('.js-media-upload-gallery-item[data-media-id='+id+']').fadeOut(500,function(){
|
||||
$(this).remove();
|
||||
|
||||
if ($itemNext=$this.searchNextSelected()) {
|
||||
$this.setCurrent($itemNext,true);
|
||||
} else {
|
||||
$this.hideDetail();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
this.loadGallery = function() {
|
||||
$('.js-media-upload-gallery-list').addClass('loader');
|
||||
ls.ajax.load(aRouter['ajax']+"media/load-gallery/", { target_type: this.options.target_type, target_id: this.options.target_id, target_tmp: this.options.target_tmp }, function(result) {
|
||||
$('.js-media-upload-gallery-list').removeClass('loader');
|
||||
$('.js-media-upload-gallery-list').html(result.sTemplate);
|
||||
});
|
||||
};
|
||||
|
||||
this.generateTargetTmp = function(type) {
|
||||
ls.ajax.load(aRouter['ajax']+"media/generate-target-tmp/", { type: type }, function(result) {
|
||||
if (result.sTmpKey) {
|
||||
this.options.target_tmp=result.sTmpKey;
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
this.addPreload = function(data) {
|
||||
data.context=$('<li class="modal-upload-image-gallery-list-item">' +
|
||||
'loader...' +
|
||||
'</li>');
|
||||
$('.js-media-upload-gallery-list').prepend(data.context);
|
||||
};
|
||||
|
||||
this.bindFileEvents = function() {
|
||||
$('.js-media-upload-gallery-list').on('click','.js-media-upload-gallery-item',function(e){
|
||||
var $item=$(e.currentTarget);
|
||||
var allowMany=(this.mode=='create-photoset' || e.ctrlKey || e.metaKey);
|
||||
if ($item.hasClass('active')) {
|
||||
/**
|
||||
* Снимаем выделение с текущего
|
||||
*/
|
||||
$item.removeClass('active').removeClass('is-selected');
|
||||
/**
|
||||
* Делаем активным другой выделенный элемент
|
||||
*/
|
||||
if ($itemNext=this.searchNextSelected($item)) {
|
||||
this.setCurrent($itemNext,true);
|
||||
} else {
|
||||
this.hideDetail();
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* Делаем текущим и показываем детальную информацию
|
||||
*/
|
||||
this.setCurrent($item,allowMany);
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
this.addFile = function(context,response) {
|
||||
/**
|
||||
* Завершение загрузки файла
|
||||
*/
|
||||
var $item=$(response.sTemplateFile);
|
||||
context.replaceWith($item);
|
||||
this.setSelected($item,true);
|
||||
};
|
||||
|
||||
this.addFileError = function(context,response) {
|
||||
/**
|
||||
* Помечаем файл как ошибочный (глюк при загрузке)
|
||||
*/
|
||||
ls.msg.error(response.sMsgTitle,response.sMsg);
|
||||
context.html('ERROR');
|
||||
};
|
||||
|
||||
this.searchNextSelected = function($itemOld) {
|
||||
var $item=$('.js-media-upload-gallery-item.is-selected:first');
|
||||
if ($item.length==0) {
|
||||
return false;
|
||||
}
|
||||
return $item;
|
||||
};
|
||||
|
||||
this.setCurrent = function($item,allowMany) {
|
||||
$('.js-media-upload-gallery-item.active').removeClass('active');
|
||||
$item.addClass('active');
|
||||
this.setSelected($item,allowMany);
|
||||
/**
|
||||
* Показываем детальную информацию
|
||||
*/
|
||||
this.showDetail($item);
|
||||
};
|
||||
|
||||
this.getCurrent = function() {
|
||||
return $('.js-media-upload-gallery-item.active');
|
||||
};
|
||||
|
||||
this.setSelected = function($item,allowMany) {
|
||||
if (!allowMany) {
|
||||
this.getSelected().removeClass('is-selected');
|
||||
}
|
||||
$item.addClass('is-selected');
|
||||
/**
|
||||
* Если нет еще нет активного элемента, то делаем активным текущий
|
||||
*/
|
||||
if (this.getCurrent().length==0) {
|
||||
this.setCurrent($item,allowMany);
|
||||
}
|
||||
};
|
||||
|
||||
this.getSelected = function() {
|
||||
return $('.js-media-upload-gallery-item.is-selected');
|
||||
};
|
||||
|
||||
this.showDetail = function($item) {
|
||||
$('.js-media-detail-preview').attr('src',$item.data('mediaPreview'));
|
||||
$('.js-media-detail-name').html($item.data('mediaFileName'));
|
||||
$('.js-media-detail-date').html($item.data('mediaDateAdd'));
|
||||
$('.js-media-detail-dimensions').html($item.data('mediaWidth')+' × '+$item.data('mediaHeight'));
|
||||
$('.js-media-detail-file-size').html(parseInt($item.data('mediaFileSize')/1024)+'kB');
|
||||
$('.js-media-detail-area').show();
|
||||
|
||||
this.showSettingsMode($item);
|
||||
};
|
||||
|
||||
this.hideDetail = function() {
|
||||
$('.js-media-detail-area').hide();
|
||||
this.hideSettingsMode();
|
||||
};
|
||||
|
||||
this.submitInsert = function() {
|
||||
var $aItems=this.getSelected();
|
||||
if (!$aItems.length) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Формируем список ID элементов
|
||||
*/
|
||||
var aIds=[];
|
||||
$aItems.each(function(k,v){
|
||||
var $item=$(v);
|
||||
aIds.push($item.data('mediaId'));
|
||||
});
|
||||
var params={
|
||||
ids: aIds,
|
||||
align: $('#media-settings-mode-insert').find('select[name=align]').val(),
|
||||
size: $('#media-settings-mode-insert').find('select[name=size]').val()
|
||||
}
|
||||
|
||||
ls.ajax.load(aRouter['ajax']+"media/submit-insert/", params, function(result) {
|
||||
if (result.bStateError) {
|
||||
ls.msg.error(result.sMsgTitle,result.sMsg);
|
||||
} else {
|
||||
$.markItUp({
|
||||
replaceWith: result.sTextResult
|
||||
});
|
||||
$('#modal-image-upload').modal('hide');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this.submitCreatePhotoset = function() {
|
||||
var $aItems=this.getSelected();
|
||||
if (!$aItems.length) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Формируем список ID элементов
|
||||
*/
|
||||
var aIds=[];
|
||||
$aItems.each(function(k,v){
|
||||
var $item=$(v);
|
||||
aIds.push($item.data('mediaId'));
|
||||
});
|
||||
var params={
|
||||
ids: aIds
|
||||
}
|
||||
|
||||
ls.ajax.load(aRouter['ajax']+"media/submit-create-photoset/", params, function(result) {
|
||||
if (result.bStateError) {
|
||||
ls.msg.error(result.sMsgTitle,result.sMsg);
|
||||
} else {
|
||||
$.markItUp({
|
||||
replaceWith: result.sTextResult
|
||||
});
|
||||
$('#modal-image-upload').modal('hide');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return this;
|
||||
}).call(ls.media || {},jQuery);
|
|
@ -26,4 +26,74 @@
|
|||
.write-list li.write-item-type-link .write-item-image { background-position: -200px 0; }
|
||||
.write-list li.write-item-type-photoset .write-item-image { background-position: -300px 0; }
|
||||
.write-list li.write-item-type-blog .write-item-image { background-position: -400px 0; }
|
||||
.write-list li.write-item-type-draft .write-item-image { background-position: -500px 0; }
|
||||
.write-list li.write-item-type-draft .write-item-image { background-position: -500px 0; }
|
||||
|
||||
|
||||
/**
|
||||
* Add media
|
||||
*
|
||||
* @template modals/modal.upload_image.tpl
|
||||
*/
|
||||
.modal-upload-image { max-width: 1200px; border: none; }
|
||||
|
||||
.modal-upload-image .grid-row { background: #222; }
|
||||
|
||||
/* Nav */
|
||||
.modal-upload-image-nav { float: left; width: 150px; padding-top: 15px; }
|
||||
.modal-upload-image-nav li a { display: block; padding: 10px 15px; color: #eee; }
|
||||
.modal-upload-image-nav li a:hover { background: #2a2a2a; }
|
||||
.modal-upload-image-nav li.active a { background: #333; }
|
||||
|
||||
/* Content */
|
||||
.modal-upload-image-content { min-height: 300px; margin-left: 150px; background: #fff; border-left: 1px solid #eee; }
|
||||
|
||||
/* Upload area */
|
||||
.form-input-file.form-input-file-media {
|
||||
display: block;
|
||||
border: 3px dashed #eee;
|
||||
color: #555;
|
||||
cursor: pointer;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Manager */
|
||||
.modal-upload-image-gallery { overflow: hidden; }
|
||||
.modal-upload-image-gallery-list { overflow: auto; width: 68%; margin-right: 2%; max-height: 354px; float: left; }
|
||||
.modal-upload-image-gallery-list-item {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
border: 3px solid transparent;
|
||||
padding: 1px;
|
||||
float: left;
|
||||
margin: 0 10px 10px 0;
|
||||
}
|
||||
.modal-upload-image-gallery-list-item img { vertical-align: top; width: 100px; height: 100px; }
|
||||
.modal-upload-image-gallery-list-item:hover { border-color: #eee; }
|
||||
|
||||
/* Selected */
|
||||
.modal-upload-image-gallery-list-item.is-selected { border-color: #D5CE3D; }
|
||||
|
||||
/* Active */
|
||||
.modal-upload-image-gallery-list-item.is-selected.active { border-color: #7979FC; }
|
||||
.modal-upload-image-gallery-list-item.is-selected.active .modal-upload-image-gallery-list-item-checkbox {background: #7979FC; }
|
||||
|
||||
/* Checkbox */
|
||||
.modal-upload-image-gallery-list-item input { display: none; }
|
||||
.modal-upload-image-gallery-list-item.is-selected .modal-upload-image-gallery-list-item-checkbox { position: absolute; right: 0; bottom: 0; width: 20px; height: 20px; background: #D5CE3D; cursor: pointer; }
|
||||
.modal-upload-image-gallery-list-item.is-selected input:checked + .modal-upload-image-gallery-list-item-checkbox { background: #000; }
|
||||
|
||||
/* Info */
|
||||
.modal-upload-image-gallery-info { width: 30%; float: left; padding: 20px; background: #fafafa; }
|
||||
.modal-upload-image-gallery-info ul li { margin-bottom: 5px; }
|
||||
|
||||
.modal-upload-image-gallery-list,
|
||||
.modal-upload-image-gallery-info {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Note */
|
||||
.modal-upload-image-note { margin-bottom: 20px; }
|
|
@ -24,7 +24,11 @@
|
|||
{block name='add_topic_options'}{/block}
|
||||
|
||||
{* Подключение редактора *}
|
||||
{include file='forms/editor.init.tpl'}
|
||||
{$sMediaTargetId=''}
|
||||
{if $oTopicEdit}
|
||||
{$sMediaTargetId=$oTopicEdit->getId()}
|
||||
{/if}
|
||||
{include file='forms/editor.init.tpl' sMediaTargetType='topic' sMediaTargetId=$sMediaTargetId}
|
||||
|
||||
|
||||
{hook run="add_topic_`$sTopicType`_begin"}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
{**
|
||||
* Добавление медиа-файла / Список изображений / Блок с изображением
|
||||
*
|
||||
* @styles css/modals.css
|
||||
*
|
||||
* TODO: Передавать сюда объект изображения вместо отдельных переменных
|
||||
*}
|
||||
<li class="js-media-upload-gallery-item modal-upload-image-gallery-list-item {if $bIsSelected}is-selected{/if} {if $bIsActive}active{/if}"
|
||||
data-media-id="{$oMediaItem->getId()}"
|
||||
data-media-type="{$oMediaItem->getType()}"
|
||||
data-media-date-add="{$oMediaItem->getDateAdd()}"
|
||||
data-media-data-title="{$oMediaItem->getDataOne('title')|escape:'html'}"
|
||||
data-media-file-name="{$oMediaItem->getFileName()|escape:'html'}"
|
||||
data-media-file-size="{$oMediaItem->getFileSize()}"
|
||||
data-media-width="{$oMediaItem->getWidth()}"
|
||||
data-media-height="{$oMediaItem->getHeight()}"
|
||||
data-media-preview="{$oMediaItem->getFileWebPath('100crop')}"
|
||||
data-media-image-sizes={json var=$oMediaItem->getDataOne('image_sizes')}
|
||||
>
|
||||
<img src="{$oMediaItem->getFileWebPath('100crop')}" alt="Image">
|
||||
|
||||
<input id="checkbox_02" type="checkbox">
|
||||
<label for="checkbox_02" class="modal-upload-image-gallery-list-item-checkbox" title="Убрать выделение"></label>
|
||||
</li>
|
68
application/frontend/skin/developer/modals/modal.upload_image.gallery.tpl
Executable file
68
application/frontend/skin/developer/modals/modal.upload_image.gallery.tpl
Executable file
|
@ -0,0 +1,68 @@
|
|||
{**
|
||||
* Добавление медиа-файла / Список изображений
|
||||
*
|
||||
* @styles css/modals.css
|
||||
*}
|
||||
|
||||
<div id="upload-gallery-image">
|
||||
|
||||
<label for="upload-file" class="form-input-file form-input-file-media js-media-upload-area">
|
||||
<span>Перетащите сюда файлы или кликните по этому тексту</span>
|
||||
<input type="file" name="filedata" class="js-media-upload-file" id="upload-file" multiple>
|
||||
</label>
|
||||
|
||||
<div class="modal-upload-image-gallery">
|
||||
|
||||
<ul class="modal-upload-image-gallery-list js-media-upload-gallery-list">
|
||||
|
||||
</ul>
|
||||
|
||||
<div class="modal-upload-image-gallery-info">
|
||||
<div class="js-media-detail-area" style="display: none;">
|
||||
<img src="" alt="" class="js-media-detail-preview">
|
||||
<ul class="mb-20">
|
||||
<li><strong class="js-media-detail-name"></strong></li>
|
||||
<li class="js-media-detail-date"></li>
|
||||
<li><span class="js-media-detail-dimensions"></span>, <span class="js-media-detail-file-size"></span></li>
|
||||
<li><a href="#" onclick="if (confirm('Удалить текущий файл?')) { ls.media.removeCurrentFile(); }; return false;">Удалить файл</a></li>
|
||||
</ul>
|
||||
|
||||
{* Title *}
|
||||
{include file='forms/form.field.text.tpl'
|
||||
sFieldName = 'title'
|
||||
sFieldLabel = $aLang.uploadimg_title}
|
||||
</div>
|
||||
|
||||
<div class="js-media-settings-mode" id="media-settings-mode-insert" style="display: none;">
|
||||
Опции вставки
|
||||
{* Align *}
|
||||
<p>
|
||||
<label>{$aLang.uploadimg_align}:</label>
|
||||
<select name="align" class="width-full">
|
||||
<option value="">{$aLang.uploadimg_align_no}</option>
|
||||
<option value="left">{$aLang.uploadimg_align_left}</option>
|
||||
<option value="right">{$aLang.uploadimg_align_right}</option>
|
||||
<option value="center" selected="selected">{$aLang.uploadimg_align_center}</option>
|
||||
</select>
|
||||
</p>
|
||||
<p>
|
||||
{$aImageSizes=Config::Get('module.media.image_sizes')}
|
||||
<label>Размер:</label>
|
||||
<select name="size" class="width-full">
|
||||
{foreach $aImageSizes as $aSize}
|
||||
<option value="{$aSize.w}{if $aSize.crop}crop{/if}">{$aSize.w} × {if $aSize.h}{$aSize.h}{else}*{/if}</option>
|
||||
{/foreach}
|
||||
<option value="original">Оригинал</option>
|
||||
</select>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="js-media-settings-mode" id="media-settings-mode-create-photoset" style="display: none;">
|
||||
Опции фотосета
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
192
application/frontend/skin/developer/modals/modal.upload_image.tpl
Normal file → Executable file
192
application/frontend/skin/developer/modals/modal.upload_image.tpl
Normal file → Executable file
|
@ -1,87 +1,107 @@
|
|||
{**
|
||||
* Загрузка изображения
|
||||
*
|
||||
* @styles css/modals.css
|
||||
*}
|
||||
|
||||
{extends file='modals/modal_base.tpl'}
|
||||
|
||||
{block name='modal_id'}modal-image-upload{/block}
|
||||
{block name='modal_class'}modal-image-upload js-modal-default{/block}
|
||||
{block name='modal_title'}{$aLang.uploadimg}{/block}
|
||||
|
||||
{block name='modal_header_after'}
|
||||
<ul class="nav nav-pills nav-pills-tabs" data-type="tabs">
|
||||
<li data-type="tab" data-tab-target="tab-upload-pc" class="active"><a href="#">{$aLang.uploadimg_from_pc}</a></li>
|
||||
<li data-type="tab" data-tab-target="tab-upload-link"><a href="#">{$aLang.uploadimg_from_link}</a></li>
|
||||
</ul>
|
||||
{/block}
|
||||
|
||||
{block name='modal_content_after'}
|
||||
<div data-type="tab-panes">
|
||||
{**
|
||||
* Загрузка
|
||||
*}
|
||||
<form method="POST" action="" enctype="multipart/form-data" id="tab-upload-pc" onsubmit="return false;" data-type="tab-pane" class="tab-pane" style="display: block">
|
||||
<div class="modal-content">
|
||||
<p><label for="img_file">{$aLang.uploadimg_file}:</label>
|
||||
<input type="file" name="img_file" id="img_file" value="" class="width-full" /></p>
|
||||
|
||||
{hook run="uploadimg_source"}
|
||||
|
||||
<p>
|
||||
<label for="form-image-align">{$aLang.uploadimg_align}:</label>
|
||||
<select name="align" id="form-image-align" class="width-full">
|
||||
<option value="">{$aLang.uploadimg_align_no}</option>
|
||||
<option value="left">{$aLang.uploadimg_align_left}</option>
|
||||
<option value="right">{$aLang.uploadimg_align_right}</option>
|
||||
<option value="center">{$aLang.uploadimg_align_center}</option>
|
||||
</select>
|
||||
</p>
|
||||
|
||||
<p><label for="form-image-title">{$aLang.uploadimg_title}:</label>
|
||||
<input type="text" name="title" id="form-image-title" value="" class="width-full" /></p>
|
||||
|
||||
{hook run="uploadimg_additional"}
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="button button-primary js-upload-image-button" data-form-id="tab-upload-pc">{$aLang.uploadimg_submit}</button>
|
||||
<button type="button" class="button" data-type="modal-close">{$aLang.uploadimg_cancel}</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{**
|
||||
* Ссылка
|
||||
*}
|
||||
<form method="POST" action="" enctype="multipart/form-data" id="tab-upload-link" onsubmit="return false;" data-type="tab-pane" class="tab-pane">
|
||||
<div class="modal-content">
|
||||
<p><label for="img_file">{$aLang.uploadimg_url}:</label>
|
||||
<input type="text" name="img_url" id="img_url" value="http://" class="width-full" /></p>
|
||||
|
||||
<p>
|
||||
<label for="form-image-url-align">{$aLang.uploadimg_align}:</label>
|
||||
<select name="align" id="form-image-url-align" class="width-full">
|
||||
<option value="">{$aLang.uploadimg_align_no}</option>
|
||||
<option value="left">{$aLang.uploadimg_align_left}</option>
|
||||
<option value="right">{$aLang.uploadimg_align_right}</option>
|
||||
<option value="center">{$aLang.uploadimg_align_center}</option>
|
||||
</select>
|
||||
</p>
|
||||
|
||||
<p><label for="form-image-url-title">{$aLang.uploadimg_title}:</label>
|
||||
<input type="text" name="title" id="form-image-url-title" value="" class="width-full" /></p>
|
||||
|
||||
{hook run="uploadimg_link_additional"}
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="button button-primary js-insert-image-button">{$aLang.uploadimg_link_submit_paste}</button>
|
||||
<button type="submit" class="button button-primary js-upload-image-button" data-form-id="tab-upload-link">{$aLang.uploadimg_link_submit_load}</button>
|
||||
<button type="button" class="button" data-type="modal-close">{$aLang.uploadimg_cancel}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{/block}
|
||||
|
||||
{**
|
||||
* Загрузка медиа-файлов
|
||||
*
|
||||
* @styles css/modals.css
|
||||
*}
|
||||
|
||||
{extends file='modals/modal_base.tpl'}
|
||||
|
||||
{block name='modal_id'}modal-image-upload{/block}
|
||||
{block name='modal_class'}modal-upload-image js-modal-default{/block}
|
||||
{block name='modal_title'}Добавить медиа-файл{/block}
|
||||
{block name='modal_attributes'}data-modal-center="false"{/block}
|
||||
|
||||
{block name='modal_content_after'}
|
||||
|
||||
<script type="text/javascript">
|
||||
jQuery(function($){
|
||||
$('.js-tab-show-gallery').on('tabbeforeactivate',function(event,tab){
|
||||
$('#upload-gallery-image').appendTo($('#'+tab.options.target).find('.modal-content'));
|
||||
ls.media.setMode($(event.target).data('mediaMode'));
|
||||
});
|
||||
|
||||
ls.media.setMode('insert');
|
||||
ls.media.initUpload({
|
||||
target_type: {json var=$sMediaTargetType},
|
||||
target_id: {json var=$sMediaTargetId},
|
||||
target_tmp: {json var=$sMediaTargetTmp},
|
||||
fileupload: {
|
||||
dropZone: $('.js-media-upload-area')
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="grid-row">
|
||||
{* Side navigation *}
|
||||
<ul class="modal-upload-image-nav" data-type="tabs">
|
||||
<li data-type="tab" data-tab-target="tab-media-insert" data-media-mode="insert" class="active js-tab-show-gallery"><a href="#">Вставить</a></li>
|
||||
<li data-type="tab" data-tab-target="tab-media-create-photoset" data-media-mode="create-photoset" class="js-tab-show-gallery"><a href="#">Создать фотосет</a></li>
|
||||
<!--<li data-type="tab" data-tab-target="tab-media-link"><a href="#">{$aLang.uploadimg_from_link}</a></li>-->
|
||||
</ul>
|
||||
|
||||
{* Side navigation content *}
|
||||
<div data-type="tab-panes" class="modal-upload-image-content">
|
||||
{**
|
||||
* Загрузка
|
||||
*}
|
||||
<div id="tab-media-insert" data-type="tab-pane" class="tab-pane modal-upload-image-pane" style="display: block">
|
||||
<div class="modal-content">
|
||||
{include file='modals/modal.upload_image.gallery.tpl'}
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="button button-primary" onclick="ls.media.submitInsert();">Вставить</button>
|
||||
<button type="button" class="button" data-type="modal-close">{$aLang.uploadimg_cancel}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{**
|
||||
* Ссылка
|
||||
*}
|
||||
<form method="POST" action="" enctype="multipart/form-data" id="tab-media-link" onsubmit="return false;" data-type="tab-pane" class="tab-pane modal-upload-image-pane">
|
||||
<div class="modal-content">
|
||||
<p><label for="img_url">{$aLang.uploadimg_url}:</label>
|
||||
<input type="text" name="img_url" id="img_url" value="http://" class="width-full" /></p>
|
||||
|
||||
<p>
|
||||
<label for="form-image-url-align">{$aLang.uploadimg_align}:</label>
|
||||
<select name="align" id="form-image-url-align" class="width-full">
|
||||
<option value="">{$aLang.uploadimg_align_no}</option>
|
||||
<option value="left">{$aLang.uploadimg_align_left}</option>
|
||||
<option value="right">{$aLang.uploadimg_align_right}</option>
|
||||
<option value="center">{$aLang.uploadimg_align_center}</option>
|
||||
</select>
|
||||
</p>
|
||||
|
||||
<p><label for="form-image-url-title">{$aLang.uploadimg_title}:</label>
|
||||
<input type="text" name="title" id="form-image-url-title" value="" class="width-full" /></p>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="button button-primary js-insert-image-button">Вставить</button>
|
||||
<button type="submit" class="button button-primary js-upload-image-button" data-form-id="tab-upload-link">{$aLang.uploadimg_link_submit_load}</button>
|
||||
<button type="button" class="button" data-type="modal-close">{$aLang.uploadimg_cancel}</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
{**
|
||||
* Фотосет
|
||||
*}
|
||||
<div id="tab-media-create-photoset" data-type="tab-pane" class="tab-pane modal-upload-image-pane">
|
||||
<div class="modal-content">
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="button button-primary" onclick="ls.media.submitCreatePhotoset();">Создать фотосет</button>
|
||||
<button type="button" class="button" data-type="modal-close">{$aLang.uploadimg_cancel}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
|
||||
{block name='modal_footer'}{/block}
|
|
@ -139,4 +139,57 @@ CREATE TABLE IF NOT EXISTS `prefix_property_value_select` (
|
|||
KEY `target_id` (`target_id`),
|
||||
KEY `property_id` (`property_id`),
|
||||
KEY `select_id` (`select_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `prefix_media` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`user_id` int(11) DEFAULT NULL,
|
||||
`type` int(11) NOT NULL,
|
||||
`file_path` varchar(500) NOT NULL,
|
||||
`file_name` varchar(500) NOT NULL,
|
||||
`file_size` int(11) NOT NULL,
|
||||
`width` int(11) NOT NULL,
|
||||
`height` int(11) NOT NULL,
|
||||
`date_add` datetime NOT NULL,
|
||||
`data` text NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `user_id` (`user_id`),
|
||||
KEY `type` (`type`),
|
||||
KEY `file_size` (`file_size`),
|
||||
KEY `width` (`width`),
|
||||
KEY `height` (`height`),
|
||||
KEY `date_add` (`date_add`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Структура таблицы `prefix_media_target`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `prefix_media_target` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`media_id` int(11) NOT NULL,
|
||||
`target_id` int(11) DEFAULT NULL,
|
||||
`target_type` varchar(50) NOT NULL,
|
||||
`target_tmp` varchar(50) DEFAULT NULL,
|
||||
`date_add` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `media_id` (`media_id`),
|
||||
KEY `target_id` (`target_id`),
|
||||
KEY `target_type` (`target_type`),
|
||||
KEY `target_tmp` (`target_tmp`),
|
||||
KEY `date_add` (`date_add`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Ограничения внешнего ключа сохраненных таблиц
|
||||
--
|
||||
|
||||
--
|
||||
-- Ограничения внешнего ключа таблицы `prefix_media_target`
|
||||
--
|
||||
ALTER TABLE `prefix_media_target`
|
||||
ADD CONSTRAINT `prefix_media_target_ibfk_1` FOREIGN KEY (`media_id`) REFERENCES `prefix_media` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
|
Loading…
Reference in a new issue