%PDF- %PDF-
| Direktori : /home/bitrix/www/bitrix/modules/landing/lib/ |
| Current File : //home/bitrix/www/bitrix/modules/landing/lib/landing.php |
<?php
namespace Bitrix\Landing;
use \Bitrix\Main\Event;
use \Bitrix\Main\EventResult;
use \Bitrix\Main\Page\Asset;
use \Bitrix\Main\Localization\Loc;
use \Bitrix\Main\ModuleManager;
Loc::loadMessages(__FILE__);
class Landing extends \Bitrix\Landing\Internals\BaseTable
{
/**
* Internal class.
* @var string
*/
public static $internalClass = 'LandingTable';
/**
* Enabled updated or not.
* @var bool
*/
protected static $enabledUpdate = true;
/**
* Check deleted pages or not.
* @var bool
*/
protected static $checkDelete = true;
/**
* Current mode is edit.
* @var boolean
*/
protected static $editMode = false;
/**
* Current mode is preview.
* @var boolean
*/
protected static $previewMode = false;
/**
* External variables of Landing.
* @var array
*/
protected static $variables = array();
/**
* Set false if landing view as area.
* @var boolean
*/
protected $mainInstance = true;
/**
* Additional data of current landing.
* @var array
*/
protected $metaData = array();
/**
* All blocks of current landing.
* @var array
*/
protected $blocks = array();
/**
* Id of current landing.
* @var int
*/
protected $id = 0;
/**
* Title of current landing.
* @var string
*/
protected $title = '';
/**
* Code (part of URL) of current landing.
* @var string
*/
protected $code = '';
/**
* XMl Id of current landing.
* @var string
*/
protected $xmlId = '';
/**
* Site id of current landing.
* @var int
*/
protected $siteId = 0;
/**
* Folder id of current landing.
* @var int
*/
protected $folderId = 0;
/**
* Current template id.
* @var int
*/
protected $tplId = 0;
/**
* Current template type (site or landing).
* @var string
*/
protected $tplType = 'landing';
/**
* Active or not current landing.
* @var boolean
*/
protected $active = false;
/**
* Instance of Error.
* @var \Bitrix\Landing\Error
*/
protected $error = null;
/**
* Constructor.
* @param int $id Landing id.
* @param array $params Some params.
*/
protected function __construct($id, $params = array())
{
$this->error = new Error;
$filter = array(
'ID' => $id
);
if (
isset($params['force_deleted']) &&
$params['force_deleted'] === true
)
{
$filter['=DELETED'] = ['Y', 'N'];
$filter['=SITE.DELETED'] = ['Y', 'N'];
}
$landing = self::getList(array(
'select' => array(
'*',
'SITE_TPL_ID' => 'SITE.TPL_ID'
),
'filter' => $filter
))->fetch();
if ($landing)
{
/*
* $this->getEditMode()
* @todo return if no access
*/
// get base data
$this->title = $landing['TITLE'];
$this->code = $landing['CODE'];
$this->xmlId = $landing['XML_ID'];
$this->id = (int)$landing['ID'];
$this->siteId = (int)$landing['SITE_ID'];
$this->folderId = (int)$landing['FOLDER_ID'];
$this->active = $landing['ACTIVE'] == 'Y';
$this->tplId = $landing['TPL_ID'] > 0
? $landing['TPL_ID']
: (
$landing['SITE_TPL_ID'] > 0
? $landing['SITE_TPL_ID']
: 0
);
if (isset($params['is_area']) && $params['is_area'])
{
$this->mainInstance = false;
}
if ($landing['SITE_TPL_ID'] > 0 && !$landing['TPL_ID'])
{
$this->tplType = 'site';
}
// if edit mode - create copy for edit
if ($this->getEditMode())
{
if ($landing['PUBLIC'] == 'Y')
{
self::update($id, array(
'PUBLIC' => 'N',
'DATE_MODIFY' => false
));
Block::cloneForEdit($this);
}
}
// if landing is unactive
if (
false &&
!$this->active
)
{
//add error ?
//add title ? $this->title = Loc::getMessage('LANDING_TITLE_NOT_FOUND');
}
// get available blocks
else
{
Block::fillLanding(
$this,
isset($params['blocks_limit']) ? $params['blocks_limit'] : 0,
array(
'deleted' => isset($params['deleted']) && $params['deleted'] === true
)
);
}
// fill meta data
$keys = ['CREATED_BY_ID', 'MODIFIED_BY_ID', 'DATE_CREATE', 'DATE_MODIFY'];
foreach ($keys as $key)
{
if (isset($landing[$key]))
{
$this->metaData[$key] = $landing[$key];
}
}
}
// landing not found
else
{
$this->error->addError(
'LANDING_NOT_EXIST',
Loc::getMessage('LANDING_NOT_FOUND')
);
$this->title = Loc::getMessage('LANDING_TITLE_NOT_FOUND');
}
}
/**
* Set work mode to edit.
* @param boolean $mode Edit mode.
* @return void
*/
public static function setEditMode($mode = true)
{
self::$editMode = (boolean) $mode;
}
/**
* Get state of edit mode.
* @return boolean
*/
public static function getEditMode()
{
return self::$editMode;
}
/**
* Set work mode to preview.
* @param boolean $mode Preview mode.
* @return void
*/
public static function setPreviewMode($mode = true)
{
self::$previewMode = (boolean) $mode;
}
/**
* Get state of preview mode.
* @return boolean
*/
public static function getPreviewMode()
{
return self::$previewMode;
}
/**
* Check delete pages or not.
* @return bool
*/
public static function checkDeleted()
{
return self::$checkDelete;
}
/**
* Disable check delete.
* @return void
*/
public static function disableCheckDeleted()
{
self::$checkDelete = false;
}
/**
* Enable check delete.
* @return void
*/
public static function enableCheckDeleted()
{
self::$checkDelete = true;
}
/**
* Disable update.
* @return void
*/
public static function disableUpdate()
{
self::$enabledUpdate = false;
}
/**
* Enable update.
* @return void
*/
public static function enableUpdate()
{
self::$enabledUpdate = true;
}
/**
* Create current instance.
* @param int $id Landing id.
* @param array $params Additional params.
* @return Landing
*/
public static function createInstance($id, array $params = array())
{
return new self($id, $params);
}
/**
* Mark entity as deleted.
* @param int $id Entity id.
* @return \Bitrix\Main\Result
*/
public static function markDelete($id)
{
return parent::update($id, array(
'DELETED' => 'Y'
));
}
/**
* Mark entity as restored.
* @param int $id Entity id.
* @return \Bitrix\Main\Result
*/
public static function markUnDelete($id)
{
return parent::update($id, array(
'DELETED' => 'N'
));
}
/**
* Delete landing by id and its blocks.
* @param int $id Landing id.
* @param bool $forceDeleted Force delete throw an errors.
* @return \Bitrix\Main\Result
*/
public static function delete($id, $forceDeleted = false)
{
$result = new \Bitrix\Main\Entity\DeleteResult();
$params = [];
if ($forceDeleted)
{
$params['force_deleted'] = true;
}
// first check
foreach (array('draft', 'public') as $code)
{
self::setEditMode($code == 'draft');
$landing = self::createInstance($id, $params);
if ($landing->exist())
{
foreach ($landing->getBlocks() as $block)
{
if ($block->getAccess() < $block::ACCESS_X)
{
$result->addError(
new \Bitrix\Main\Error(
Loc::getMessage('LANDING_BLOCK_ACCESS_DENIED'),
'ACCESS_DENIED'
)
);
return $result;
}
}
}
else
{
$result->addError(
$landing->getError()->getErrors()[0]
);
return $result;
}
}
// delete blocks
foreach (array('draft', 'public') as $code)
{
self::setEditMode($code == 'draft');
$landing = self::createInstance($id, $params);
if ($landing->exist())
{
foreach ($landing->getBlocks() as $block)
{
if (!$block->unlink())
{
$result->addErrors($block->getError()->getErrors());
return $result;
}
}
File::deleteFromLanding($id);
}
}
return parent::delete($id);
}
/**
* Get hooks of Landing.
* @param int $id Landing id.
* @return array Array of Hook.
*/
public static function getHooks($id)
{
return Hook::getForLanding($id);
}
/**
* Get additional fields of Landing.
* @param int $id Landing id.
* @return array Array of Field.
*/
public static function getAdditionalFields($id)
{
$fields = array();
// now we can get additional fields only from hooks
foreach (self::getHooks($id) as $hook)
{
$fields += $hook->getPageFields();
}
return $fields;
}
/**
* Save additional fields for Landing.
* @param int $id Landing id.
* @param array $data Data array.
* @return void
*/
public static function saveAdditionalFields($id, array $data)
{
// now we can get additional fields only from hooks
Hook::saveForLanding($id, $data);
}
/**
* Set external variables of Landing.
* @param array $vars Additional vars.
* @return void
*/
public static function setVariables(array $vars)
{
foreach ($vars as $code => $val)
{
self::$variables[$code] = $val;
}
}
/**
* Get external variables of Landing.
* @return array
*/
public static function getVariables()
{
return self::$variables;
}
/**
* Get preview picture of the landing.
* Is the preview of first block.
* @return string
*/
public function getPreview()
{
if (
(
!defined('LANDING_DISABLE_CLOUD')
||
LANDING_DISABLE_CLOUD !== true
)
&&
Manager::isB24())
{
return $this->getPublicUrl() . 'preview.jpg';
}
static $hookPics = null;
if ($hookPics === null)
{
$hookPics = \Bitrix\Landing\Hook\Page\MetaOg::getAllImages();
}
if (isset($hookPics[$this->id]))
{
$pic = $hookPics[$this->id];
if (intval($pic) > 0)
{
$pic = \CFile::getPath($pic);
}
return $pic;
}
return '/bitrix/images/landing/nopreview.jpg';
}
/**
* Get full pubic URL for this landing.
* @param int|array $id Landing id (id array), optional.
* @param boolean $absolute Full url.
* @param bool $createPubPath Create pub path (checking and create).
* @return string
*/
public function getPublicUrl($id = false, $absolute = true, $createPubPath = false)
{
if ($id === false)
{
$id = $this->id;
}
$bitrix24 = Manager::isB24();
$disableCloud = defined('LANDING_DISABLE_CLOUD') &&
LANDING_DISABLE_CLOUD === true;
$domainDefault = null;
$data = array();
$res = Landing::getList(array(
'select' => array(
'ID',
'CODE',
'SITE_ID',
'SITE_ID_INDEX' => 'SITE.LANDING_ID_INDEX',
'SITE_PROTOCOL' => 'SITE.DOMAIN.PROTOCOL',
'SITE_DOMAIN' => 'SITE.DOMAIN.DOMAIN',
'SITE_CODE' => 'SITE.CODE',
'SITE_SMN_ID' => 'SITE.SMN_SITE_ID',
'FOLDER_CODE' => 'LF.CODE'
),
'filter' => array(
'ID' => $id,
'=DELETED' => ['Y', 'N']
),
'runtime' => array(
new \Bitrix\Main\Entity\ReferenceField(
'LF',
'\Bitrix\Landing\Internals\LandingTable',
array('=this.FOLDER_ID' => 'ref.ID')
)
)
));
while ($row = $res->fetch())
{
$domainReplace = false;
$row['SITE_ID_ORIG'] = $row['SITE_ID'];
// build site domain by default
if (!$row['SITE_DOMAIN'])
{
if (!$domainDefault)
{
$domainDefault = Domain::getList(array(
'filter' => array(
'ID' => Domain::getCurrentId()
)
))->fetch();
}
if (isset($domainDefault['PROTOCOL']))
{
$row['SITE_PROTOCOL'] = $domainDefault['PROTOCOL'];
}
if (isset($domainDefault['DOMAIN']))
{
$row['SITE_DOMAIN'] = $domainDefault['DOMAIN'];
}
$domainReplace = true;
}
// force https
if (Manager::isHttps())
{
$row['SITE_PROTOCOL'] = 'https';
}
if ($domainReplace || !$bitrix24 || $disableCloud)
{
$pubPath = Manager::getPublicationPath(
null,
$row['SITE_SMN_ID'] ? $row['SITE_SMN_ID'] : SITE_ID,
$createPubPath
);
$pubPath = rtrim($pubPath, '/');
}
// for create publication path
if (!ModuleManager::isModuleInstalled('bitrix24'))
{
Manager::getPublicationPath(
null,
$row['SITE_SMN_ID'] ? $row['SITE_SMN_ID'] : SITE_ID,
$createPubPath
);
}
if (isset($row['SITE_ID']))
{
$row['SITE_ID'] = '/' . $row['SITE_ID'] . '/';
}
if ($disableCloud)
{
$data[$row['ID']] = $pubPath .
$row['SITE_ID'] .
(self::$previewMode ? 'preview/' . Site::getPublicHash($row['SITE_ID_ORIG'], $row['SITE_DOMAIN']) . '/' : '') .
($row['FOLDER_CODE'] ? $row['FOLDER_CODE'] . '/' : '') .
(($row['ID'] == $row['SITE_ID_INDEX']) ? '' : $row['CODE'] . '/');
}
else
{
$data[$row['ID']] = (
$absolute
? (
$row['SITE_PROTOCOL'] . '://' .
$row['SITE_DOMAIN']
)
: ''
) .
(($domainReplace || !$bitrix24) ? $pubPath : '') .
((self::$previewMode && !$bitrix24) ? '/preview/' . Site::getPublicHash($row['SITE_ID_ORIG'], $row['SITE_DOMAIN']) : '') .
(($domainReplace && $bitrix24) ? $row['SITE_ID'] : '/') .
((self::$previewMode && $bitrix24) ? 'preview/' . Site::getPublicHash($row['SITE_ID_ORIG'], $row['SITE_DOMAIN']) . '/' : '') .
($row['FOLDER_CODE'] ? $row['FOLDER_CODE'] . '/' : '') .
(($row['ID'] == $row['SITE_ID_INDEX']) ? '' : $row['CODE'] . '/');
}
}
if (is_array($id))
{
return $data;
}
elseif (!empty($data))
{
return array_pop($data);
}
return false;
}
/**
* View landing in public or edit mode.
* @param array $params Some additional params.
* @return void
*/
public function view(array $params = array())
{
$blockEditMode = $this->getEditMode();
$editMode = $this->mainInstance && $blockEditMode;
if (!isset($params['parse_link']))
{
$params['parse_link'] = true;
}
if (!isset($params['apply_template']))
{
$params['apply_template'] = true;
}
// title
if ($this->mainInstance)
{
Manager::setPageTitle(
\htmlspecialcharsbx($this->title)
);
}
// add chain item if need
if ($this->mainInstance)
{
if ($this->folderId)
{
$res = self::getList(array(
'select' => array(
'ID', 'TITLE'
),
'filter' => array(
'ID' => $this->folderId
)
));
if ($row = $res->fetch())
{
Manager::getApplication()->addChainItem(
$row['TITLE'],
'#landing' . $row['ID']
);
}
}
else
{
Manager::getApplication()->addChainItem(
$this->title,
'#landing' . $this->id
);
}
}
// assets
if ($editMode)
{
$options = array(
'site_id' => $this->siteId,
'server_name' => $_SERVER['SERVER_NAME'],
'url' => $this->getPublicUrl(),
'xml_id' => $this->xmlId,
'blocks' => Block::getRepository(),
'style' => Block::getStyle()
);
// event for redefine $options
$event = new Event('landing', 'onLandingView', array(
'options' => $options
));
$event->send();
foreach ($event->getResults() as $result)
{
if ($result->getResultType() != EventResult::ERROR)
{
if (($modified = $result->getModified()))
{
if (isset($modified['options']))
{
$options = $modified['options'];
}
}
}
}
// output js
Asset::getInstance()->addString(
'<script type="text/javascript">' .
'BX.ready(function(){'
. 'if (typeof BX.Landing.Main !== "undefined")'
. '{'
. 'BX.Landing.Main.createInstance(' . $this->id . ', ' . \CUtil::phpToJSObject($options, false, false, true) . ');'
. '}'
. '});' .
'</script>'
);
}
$content = '';
// templates part - first
if ($params['apply_template'] && $this->mainInstance)
{
if (!TemplateRef::landingIsArea($this->id))
{
$content = $this->applyTemplate();
}
else
{
$content = '<div class="landing-main"' .
' data-site="' . $this->siteId . '"' .
' data-landing="' . $this->id . '">' .
'#CONTENT#' .
'</div>';
}
}
// then content
ob_start();
foreach ($this->blocks as $block)
{
$block->view($blockEditMode, $this);
}
if ($this->mainInstance)
{
$this->execHooks();
}
$contentMain = ob_get_contents();
ob_end_clean();
// implode content and templates parts
if ($content && strpos($content, '#CONTENT#') !== false)
{
$content = str_replace('#CONTENT#', $contentMain, $content);
}
else
{
$content = $contentMain;
}
// breadcrumb (see chain_template.php in tpl) and title
if (!$blockEditMode && $this->mainInstance)
{
ob_start();
echo Manager::getApplication()->getNavChain(
false, 0, false, true
);
$breadcrumb = ob_get_contents();
ob_end_clean();
$content = str_replace(
array(
'#breadcrumb#',
'#title#'
),
array(
$breadcrumb,
Manager::getApplication()->getTitle()
),
$content
);
}
// parse links between landings
if ($params['parse_link'] === true && !$blockEditMode)
{
echo $this->parseLocalUrl($content);
}
else
{
echo $content;
}
}
/**
* Get included areas of this page.
* @return array
*/
public function getAreas()
{
if ($this->tplType == 'site')
{
return TemplateRef::getForSite($this->siteId);
}
else
{
return TemplateRef::getForLanding($this->id);
}
}
/**
* Apply template for this landing.
* @param string $content Landing content.
* @return string
*/
protected function applyTemplate($content = null)
{
if ($this->tplId)
{
$template = Template::getList(array(
'filter' => array(
'ID' => $this->tplId
)
))->fetch();
if ($template)
{
$editMode = $this->getEditMode();
if ($template['XML_ID'] == 'empty')
{
$template['CONTENT'] = '<div class="landing-main">' .
$template['CONTENT'] .
'</div>';
}
if ($editMode)
{
$replace = array(
'>#CONTENT#<' => ' data-site="' . $this->siteId .
'" data-landing="' . $this->id .
'">#CONTENT#<',
'#CONTENT#' => $content ? $content : '#CONTENT#'
);
}
else
{
$replace = array(
'#CONTENT#' => $content ? $content : '#CONTENT#'
);
}
// if areas exist, get landings
if ($template['AREA_COUNT'] > 0)
{
foreach ($this->getAreas() as $area => $lid)
{
ob_start();
$landing = self::createInstance($lid, array(
'is_area' => true
));
if ($landing->exist())
{
$landing->view();
}
if ($editMode)
{
$replace['>#AREA_' . $area . '#<'] = ' data-site="' . $landing->getSiteId() .
'" data-landing="' . $lid .
'">#AREA_' . $area . '#<';
}
$replace['#AREA_' . $area . '#'] = ob_get_contents();
ob_end_clean();
}
}
$content = str_replace(
array_keys($replace),
array_values($replace),
$template['CONTENT']
);
}
}
else if ($this->getEditMode())
{
if (!$content)
{
$content = '#CONTENT#';
}
$content = '<div class="landing-main" ' .
'data-site="' . $this->siteId . '" ' .
'data-landing="' . $this->id . '">' .
$content .
'</div>';
}
return $content;
}
/**
* Parse between-landings url in landing content.
* @param string $content Landing content.
* @return string
*/
protected function parseLocalUrl($content)
{
$pattern = '/([",\'\;]{1})#(landing|block)([\d]+)\@{0,1}([^\'"]*)([",\'\&]{1})/is';
// replace catalog links in preview mode
if (self::$previewMode)
{
$content = preg_replace_callback(
'/href\="#catalog(Element|Section)([\d]+)"/i',
function($href)
{
return 'href="' . PublicAction\Utils::getIblockURL(
$href[2],
strtolower($href[1])
) . '"';
},
$content);
}
// prepare system pages
$sysPages = array();
foreach (Syspage::get($this->siteId) as $syspage)
{
$sysPages['@#system_' . $syspage['TYPE'] . '@'] = '#landing' . $syspage['LANDING_ID'];
}
if (!empty($sysPages))
{
$content = preg_replace(
array_keys($sysPages),
array_values($sysPages),
$content
);
}
// replace in content
if (preg_match_all($pattern, $content, $matches))
{
$urls = array(
'LANDING' => array(),
'BLOCK' => array()
);
for ($i = 0, $c = count($matches[0]); $i < $c; $i++)
{
if (strtoupper($matches[2][$i]) == 'LANDING')
{
$urls['LANDING'][] = $matches[3][$i];
}
else
{
$urls['BLOCK'][] = $matches[3][$i];
}
}
// get parent landings for blocks
// and public version of blocks too
$anchorsId = array();
$anchorsPublicId = array();
if (!empty($urls['BLOCK']))
{
$urls['BLOCK'] = Block::getRowByBlockId(
$urls['BLOCK'],
array(
'ID', 'LID', 'PARENT_ID', 'ANCHOR'
)
);
foreach ($urls['BLOCK'] as $bid => &$bidRow)
{
if (
!self::$previewMode &&
$bidRow['PARENT_ID']
)
{
$anchorsPublicId[$bid] = $bidRow['PARENT_ID'];
}
else
{
$anchorsId[$bid] = $bidRow['ANCHOR']
? \htmlspecialcharsbx($bidRow['ANCHOR'])
: Block::getAnchor($bidRow['ID']);
}
$bidRow = $bidRow['LID'];
}
unset($bidRow);
$urls['LANDING'] = array_unique(array_merge(
$urls['LANDING'],
$urls['BLOCK']
));
}
// get anchors for public version
if ($anchorsPublicId)
{
$anchorsPublicIdTmp = Block::getRowByBlockId(
$anchorsPublicId,
array(
'ID', 'LID', 'PARENT_ID', 'ANCHOR'
)
);
foreach ($anchorsPublicId as $bid => $bidParent)
{
if (!isset($anchorsPublicIdTmp[$bidParent]))
{
continue;
}
$bidParent = $anchorsPublicIdTmp[$bidParent];
$anchorsPublicId[$bid] = $bidParent['ANCHOR']
? \htmlspecialcharsbx($bidParent['ANCHOR'])
: Block::getAnchor($bidParent['ID']);
}
}
$anchorsPublicId += $anchorsId;
// get landing and blocks urls
if (!empty($urls['LANDING']))
{
$urls['LANDING'] = $this->getPublicUrl($urls['LANDING']);
}
if (!empty($urls['BLOCK']))
{
foreach ($urls['BLOCK'] as $bid => $lid)
{
if (isset($urls['LANDING'][$lid]))
{
$urls['BLOCK'][$bid] = $urls['LANDING'][$lid] . '#' . $anchorsPublicId[$bid];
}
else
{
unset($urls['BLOCK'][$bid]);
}
}
}
// replace urls
if (!empty($urls['LANDING']))
{
krsort($urls['LANDING']);
$content = preg_replace_callback(
$pattern,
function($matches) use($urls)
{
$matches[2] = strtoupper($matches[2]);
if (isset($urls[$matches[2]][$matches[3]]))
{
return $matches[1] .
$urls[$matches[2]][$matches[3]] . $matches[4] .
$matches[5];
}
},
$content
);
$landingUrls = array();
foreach ($urls['LANDING'] as $lid => $url)
{
$landingUrls['@#landing' . $lid.'@'] = $url;
}
}
}
return $content;
}
/**
* Exec hooks for landing (site and landing).
* @return void
*/
protected function execHooks()
{
$hooksExec = array();
foreach (Hook::getForSite($this->siteId) as $hook)
{
if ($hook->enabled())
{
$hooksExec[$hook->getCode()] = $hook;
}
}
foreach (Hook::getForLanding($this->id) as $hook)
{
if ($hook->enabled())
{
$hooksExec[$hook->getCode()] = $hook;
}
}
foreach ($hooksExec as $hook)
{
if (
!$this->getEditMode() ||
$hook->enabledInEditMode()
)
{
$hook->exec();
}
}
}
/**
* Exist or not landing in current instance.
* @return boolean
*/
public function exist()
{
return $this->id > 0;
}
/**
* Active or not the landing.
* @return boolean
*/
public function isActive()
{
return $this->active;
}
/**
* Get id of current landing.
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Get xml id of current landing.
* @return int
*/
public function getXmlId()
{
return $this->xmlId;
}
/**
* Get title of current landing.
* @return int
*/
public function getTitle()
{
return $this->title;
}
/**
* Get metadata of current landing.
*/
public function getMeta()
{
return $this->metaData;
}
/**
* Get site id of current landing.
* @return int
*/
public function getSiteId()
{
return $this->siteId;
}
/**
* Get site id of main, if exist.
* @return string
*/
public function getSmnSiteId()
{
if ($this->siteId)
{
$res = Site::getList(array(
'select' => array(
'SMN_SITE_ID'
),
'filter' => array(
'ID' => $this->siteId
)
));
if ($row = $res->fetch())
{
return $row['SMN_SITE_ID']
? $row['SMN_SITE_ID']
: SITE_ID;
}
}
return SITE_ID;
}
/**
* Get all blocks of current landing.
* @return Block[]
*/
public function getBlocks()
{
return $this->blocks;
}
/**
* Add new Block to the current landing.
* @param \Bitrix\Landing\Block $block New block instance.
* @return void
*/
public function addBlockToCollection(\Bitrix\Landing\Block $block)
{
if ($block->exist())
{
$this->blocks[$block->getId()] = $block;
}
}
/**
* Get error collection
* @return \Bitrix\Landing\Error
*/
public function getError()
{
return $this->error;
}
/**
* Change modified user and date for current landing.
* @return void
*/
public function touch()
{
self::update($this->id);
}
/**
* Publication current landing.
* @return boolean
*/
public function publication()
{
return Mutator::landingPublication($this);
}
/**
* Cancel publication of landing.
* @return boolean
*/
public function unpublic()
{
$date = new \Bitrix\Main\Type\DateTime;
$res = parent::update($this->id, array(
'ACTIVE' => 'N',
'PUBLIC' => 'N',
'DATE_MODIFY' => false
));
if ($res->isSuccess())
{
if (Manager::isB24())
{
Site::update($this->siteId, array());
}
return true;
}
else
{
$this->error->addFromResult($res);
return false;
}
}
/**
* Add new block to the landing.
* @param string $code Code of block.
* @param array $data Data array of block.
* @return int|false Id of new block or false on failure.
*/
public function addBlock($code, $data = array())
{
$block = Block::createFromRepository($this, $code, $data);
if ($block)
{
$this->touch();
$this->addBlockToCollection($block);
return $block->getId();
}
return false;
}
/**
* Delete one block from current landing.
* @param int $id Block id.
* @return boolean
*/
public function deleteBlock($id)
{
if (isset($this->blocks[$id]))
{
$result = $this->blocks[$id]->unlink();
$this->error->copyError(
$this->blocks[$id]->getError()
);
if ($result)
{
unset($this->blocks[$id]);
}
$this->touch();
return $result;
}
else
{
$this->error->addError(
'BLOCK_NOT_FOUND',
Loc::getMessage('LANDING_BLOCK_NOT_FOUND')
);
return false;
}
}
/**
* Mark delete or not the block.
* @param int $id Block id.
* @param boolean $mark Mark.
* @return boolean
*/
public function markDeletedBlock($id, $mark)
{
if (!isset($this->blocks[$id]))
{
$this->blocks[$id] = new Block($id);
}
if (isset($this->blocks[$id]))
{
if ($this->blocks[$id]->getAccess() >= $this->blocks[$id]->ACCESS_X)
{
$this->blocks[$id]->markDeleted($mark);
if ($this->blocks[$id]->save())
{
if ($mark)
{
unset($this->blocks[$id]);
}
else
{
$this->addBlockToCollection(
$this->blocks[$id]
);
}
$this->touch();
return true;
}
else
{
$this->error->copyError(
$this->blocks[$id]->getError()
);
}
}
else
{
$this->error->addError(
'ACCESS_DENIED',
Loc::getMessage('LANDING_BLOCK_ACCESS_DENIED')
);
return false;
}
}
else
{
$this->error->addError(
'BLOCK_NOT_FOUND',
Loc::getMessage('LANDING_BLOCK_NOT_FOUND')
);
return false;
}
}
/**
* Transfer one block to another landing.
* @param int $id Block id.
* @param int $lid Landing id.
* @return boolean
*/
protected function transferBlock($id, $lid)
{
if (isset($this->blocks[$id]))
{
$result = $this->blocks[$id]->changeLanding($lid);
$this->error->copyError($this->blocks[$id]->getError());
if ($result)
{
unset($this->blocks[$id]);
}
return $result;
}
else
{
$this->error->addError(
'BLOCK_NOT_FOUND',
Loc::getMessage('LANDING_BLOCK_NOT_FOUND')
);
return false;
}
}
/**
* Resort current blocks.
* @return void
*/
public function resortBlocks()
{
uasort($this->blocks, function($a, $b)
{
if ($a->getSort() == $b->getSort())
{
return ($a->getId() < $b->getId()) ? -1 : 1;
}
return ($a->getSort() < $b->getSort()) ? -1 : 1;
});
$sort = 0;
foreach ($this->blocks as $id => $block)
{
$block->saveSort($sort);
$sort += 500;
}
}
/**
* Sort the block on the landing.
* @param int $id Block id.
* @param string $action Code: up or down.
* @return boolean
*/
protected function sortBlock($id, $action)
{
if (isset($this->blocks[$id]))
{
$blocks = array_keys($this->blocks);
for ($i = 0, $c = count($blocks); $i < $c; $i++)
{
if ($blocks[$i] == $id)
{
// change sort between two blocks
$targetKey = $i + ($action == 'up' ? -1 : 1);
if (isset($blocks[$targetKey]))
{
$thisBlock = $this->blocks[$id];
$targetBlock = $this->blocks[$blocks[$targetKey]];
$thisBlockSort = $thisBlock->getSort();
$targetBlockSort = $targetBlock->getSort();
$thisBlock->setSort($targetBlockSort);
$targetBlock->setSort($thisBlockSort);
$res1 = $thisBlock->save();
$res2 = $targetBlock->save();
$this->error->copyError($thisBlock->getError());
$this->error->copyError($targetBlock->getError());
if ($res1 || $res2)
{
$this->touch();
}
return $res1 && $res2;
}
else
{
$this->error->addError(
'BLOCK_WRONG_SORT',
Loc::getMessage('LANDING_BLOCK_WRONG_SORT')
);
return false;
}
}
}
}
else
{
$this->error->addError(
'BLOCK_NOT_FOUND',
Loc::getMessage('LANDING_BLOCK_NOT_FOUND')
);
}
return false;
}
/**
* Sort up the block on the landing.
* @param int $id Block id.
* @return boolean
*/
public function upBlock($id)
{
return $this->sortBlock($id, 'up');
}
/**
* Sort down the block on the landing.
* @param int $id Block id.
* @return boolean
*/
public function downBlock($id)
{
return $this->sortBlock($id, 'down');
}
/**
* Show/hide the block on the landing.
* @param int $id Block id.
* @param string $action Code: up or down.
* @return boolean
*/
protected function activateBlock($id, $action)
{
if (isset($this->blocks[$id]))
{
if ($this->blocks[$id]->setActive($action == 'show'))
{
if ($res = $this->blocks[$id]->save())
{
$this->touch();
}
}
$this->error->copyError($this->blocks[$id]->getError());
return $res;
}
else
{
$this->error->addError(
'BLOCK_NOT_FOUND',
Loc::getMessage('LANDING_BLOCK_NOT_FOUND')
);
return false;
}
}
/**
* Activate the block on the landing.
* @param int $id Block id.
* @return boolean
*/
public function showBlock($id)
{
return $this->activateBlock($id, 'show');
}
/**
* Dectivate the block on the landing.
* @param int $id Block id.
* @return boolean
*/
public function hideBlock($id)
{
return $this->activateBlock($id, 'hide');
}
/**
* Copy/move other block to this landing.
* @param int $block Block id.
* @param array $params Params array.
* @return int New Block id.
*/
protected function changeParentOfBlock($block, $params)
{
$move = isset($params['MOVE']) && $params['MOVE'];
$afterId = isset($params['AFTER_ID']) ? $params['AFTER_ID'] : 0;
$fromLandingId = Block::getLandingIdByBlockId($block);
$same = $this->id == $fromLandingId;
if ($same)
{
$fromLanding = clone $this;
}
else
{
$fromLanding = self::createInstance($fromLandingId);
}
// if landing exist and available, get it blocks
if ($this->exist() && $fromLanding->exist())
{
$fromLandingBlocks = $fromLanding->getBlocks();
// if move, just change landing id
if ($move)
{
$res = $fromLanding->transferBlock($block, $this->id);
$this->error->copyError($fromLanding->getError());
if ($res)
{
$newBlock = $fromLandingBlocks[$block];
}
}
// else create copy
else if (isset($fromLandingBlocks[$block]))
{
$srcBlock = $fromLandingBlocks[$block];
$newBlock = Block::createFromRepository(
$this,
$srcBlock->getCode(),
array(
'ACTIVE' => $srcBlock->isActive() ? 'Y' : 'N',
'ACCESS' => $srcBlock->getAccess(),
'SORT' => $srcBlock->getSort(),
'CONTENT' => $srcBlock->getContent(),
'PUBLIC' => 'N'
));
// copy files
if ($newBlock)
{
File::copyBlockFiles(
$srcBlock->getId(),
$newBlock->getId()
);
}
}
// add block to collection and resort
if (isset($newBlock) && $newBlock)
{
if ($afterId > 0 && isset($this->blocks[$afterId]))
{
$targetBlock = $this->blocks[$afterId];
}
else
{
$targetBlock = array_pop(array_values($this->blocks));
}
if ($targetBlock)
{
$newBlock->setSort($targetBlock->getSort() + 1);
}
$this->addBlockToCollection($newBlock);
$this->resortBlocks();
}
//change dates
if ($this->error->isEmpty())
{
$this->touch();
if ($move && !$same)
{
$fromLanding->touch();
}
}
}
$this->error->copyError($fromLanding->getError());
return isset($newBlock) ? $newBlock->getId() : null;
}
/**
* Copy other block to this landing.
* @param int $id Block id (from another landing).
* @param int $afterId Put after this block id (in this landing).
* @return int New Block id.
*/
public function copyBlock($id, $afterId)
{
return $this->changeParentOfBlock($id, array(
'MOVE' => false,
'AFTER_ID' => $afterId
));
}
/**
* Copy all blocks from another landing to this.
* @param int $lid Landing id.
* @return void
*/
public function copyAllBlocks($lid)
{
$landing = self::createInstance($lid);
if ($this->exist() && $landing->exist())
{
$oldNew = array();
// copy blocks
foreach ($landing->getBlocks() as $block)
{
$newBlock = Block::createFromRepository(
$this,
$block->getCode(),
array(
'ACTIVE' => $block->isActive() ? 'Y' : 'N',
'PUBLIC' => $block->isPublic() ? 'Y' : 'N',
'ACCESS' => $block->getAccess(),
'SORT' => $block->getSort(),
'CONTENT' => $block->getContent()
));
if ($newBlock)
{
$oldNew[$block->getId()] = $newBlock;
$this->addBlockToCollection($newBlock);
}
}
// replace old id of blocks to the new one and clone files
foreach ($this->getBlocks() as $block)
{
$content = $block->getContent();
foreach ($oldNew as $oldId => $newBlock)
{
// clone files
File::addToBlock(
$newBlock->getId(),
File::getFilesFromBlockContent($oldId, $content)
);
// replace ids
$content = str_replace(
'#block' . $oldId,
'#block' . $newBlock->getId(),
$content
);
$block->saveContent($content);
$block->save();
}
}
$this->touch();
}
$this->error->copyError($this->getError());
$this->error->copyError($landing->getError());
}
/**
* Move other block to this landing.
* @param int $id Block id (from another landing).
* @param int $afterId Put after this block id (in this landing).
* @return int New Block id.
*/
public function moveBlock($id, $afterId)
{
return $this->changeParentOfBlock($id, array(
'MOVE' => true,
'AFTER_ID' => $afterId
));
}
/**
* Update the landing.
* @param int $id Landing id.
* @param array $fields Fields.
* @return \Bitrix\Main\Result
*/
public static function update($id, $fields = array())
{
if (self::$enabledUpdate)
{
return parent::update($id, $fields);
}
else
{
return new \Bitrix\Main\Result;
}
}
}