PageRenderTime 48ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/fileman/lib/block/editor.php

https://gitlab.com/alexprowars/bitrix
PHP | 1291 lines | 1010 code | 142 blank | 139 comment | 29 complexity | b4b47b48c153941e8d57e850896ab4b4 MD5 | raw file
  1. <?
  2. /**
  3. * Bitrix Framework
  4. * @package bitrix
  5. * @subpackage sender
  6. * @copyright 2001-2012 Bitrix
  7. */
  8. namespace Bitrix\Fileman\Block;
  9. use Bitrix\Main\Application;
  10. use Bitrix\Main\Loader;
  11. use Bitrix\Main\Web\DOM\Document;
  12. use Bitrix\Main\Localization\Loc;
  13. use Bitrix\Main\Web\DOM\CssParser;
  14. use Bitrix\Main\Text\HtmlFilter;
  15. Loc::loadMessages(__FILE__);
  16. class Editor
  17. {
  18. CONST SLICE_SECTION_ID = 'BX_BLOCK_EDITOR_EDITABLE_SECTION';
  19. CONST BLOCK_PLACE_ATTR = 'data-bx-block-editor-place';
  20. CONST BLOCK_PHP_ATTR = 'data-bx-editor-php-slice';
  21. CONST STYLIST_TAG_ATTR = 'data-bx-stylist-container';
  22. CONST BLOCK_PLACE_ATTR_DEF_VALUE = 'body';
  23. CONST BLOCK_COUNT_PER_PAGE = 14;
  24. public $id;
  25. protected $site;
  26. protected $url;
  27. protected $previewUrl;
  28. protected $saveFileUrl;
  29. protected $templateType;
  30. protected $templateId;
  31. protected $charset;
  32. protected $isTemplateMode;
  33. protected $isUserHavePhpAccess;
  34. protected $useLightTextEditor;
  35. protected $ownResultId;
  36. /*
  37. * block list
  38. */
  39. public $tools = array();
  40. /*
  41. * block list
  42. */
  43. public $blocks = array();
  44. protected $componentFilter = array();
  45. public $componentsAsBlocks = array();
  46. public $previewModes = array();
  47. public $tabs = array();
  48. public $uiPatterns = array(
  49. 'main' => <<<HTML
  50. #TEXTAREA#
  51. <div id="bx-block-editor-container-#id#" class="bx-block-editor-container">
  52. <div class="button-panel">
  53. #tabs#
  54. <span class="bx-editor-block-btn-close" title="#MESS_BTN_MIN#">#MESS_BTN_MIN#</span>
  55. <span class="bx-editor-block-btn-full" title="#MESS_BTN_MAX#">#MESS_BTN_MAX#</span>
  56. <span data-role="block-editor-tab-btn-get-html" class="bx-editor-block-btn-full bx-editor-block-btn-html-copy" title="#MESS_BTN_HTML_COPY#"></span>
  57. </div>
  58. #panels#
  59. </div>
  60. HTML
  61. ,
  62. 'block' => <<<HTML
  63. <li data-bx-block-editor-block-status="blank"
  64. data-bx-block-editor-block-type="#code#"
  65. class="bx-editor-typecode-#code_class# bx-editor-type-#type_class# bx-block-editor-i-block-list-item"
  66. title="#desc#"
  67. >
  68. <span class="bx-block-editor-i-block-list-item-icon"></span>
  69. <span class="bx-block-editor-i-block-list-item-name">#name#</span>
  70. </li>
  71. HTML
  72. ,
  73. 'block_page' => <<<HTML
  74. <ul class="bx-block-editor-i-block-list">
  75. #blocks#
  76. </ul>
  77. HTML
  78. ,
  79. 'tool' => <<<HTML
  80. <div class="bx-editor-block-tools" data-bx-editor-tool="#group#:#id#">
  81. <div class="caption">#name#:</div>
  82. <div class="item">#html#</div>
  83. </div>
  84. HTML
  85. ,
  86. 'device' => <<<HTML
  87. <div class="device #class#" data-bx-preview-device-class="#class#" data-bx-preview-device-width="#width#" data-bx-preview-device-height="#height#">
  88. <span>#MESS_NAME#</span>
  89. </div>
  90. HTML
  91. ,
  92. 'tab' => <<<HTML
  93. <span class="bx-editor-block-btn bx-editor-block-btn-#code# #tab_active#">#name#</span>
  94. HTML
  95. ,
  96. 'tab_active' => 'bx-editor-block-btn-active'
  97. ,
  98. 'panel' => <<<HTML
  99. <div class="bx-editor-block-panel #code#-panel" #panel_hidden#>#html#</div>
  100. HTML
  101. ,
  102. 'panel_hidden' => 'style="display: none;"'
  103. ,
  104. 'panel-edit' => <<<HTML
  105. <div class="visual-part">
  106. <div class="shadow">
  107. <div class="edit-text"></div>
  108. </div>
  109. <iframe id="bx-block-editor-iframe-#id#" src="" style="border: none;" width="100%" height="100%"></iframe>
  110. </div>
  111. <div class="dialog-part">
  112. <div style="overflow-x: hidden;">
  113. <div class="block-list-cont">
  114. <div class="block-list-tabs">
  115. <div class="bx-editor-block-tabs">
  116. <span class="tab-list">
  117. <span class="tab blocks active">#MESS_BLOCKS#</span>
  118. <span class="tab styles">#MESS_STYLES#</span>
  119. </span>
  120. </div>
  121. <div class="edit-panel-tabs-style">
  122. <ul class="bx-block-editor-i-place-list" data-bx-place-name="item"></ul>
  123. </div>
  124. <div style="clear: both;"></div>
  125. <div class="edit-panel-tabs-block">
  126. <div>#blocks#</div>
  127. <div style="clear: both;"></div>
  128. <div class="block-pager adm-nav-pages-block">
  129. <span class="adm-nav-page adm-nav-page-prev #nav-display#"></span>
  130. <span class="adm-nav-page adm-nav-page-next #nav-display#"></span>
  131. </div>
  132. </div>
  133. <div style="clear: both;"></div>
  134. </div>
  135. <div>
  136. </div>
  137. </div>
  138. </div>
  139. </div>
  140. <div class="block-edit-cont">
  141. <div class="bx-editor-block-form-head">
  142. <div class="bx-editor-block-form-head-btn">
  143. <a class="bx-editor-block-tools-btn bx-editor-block-tools-close" title="#MESS_TOOL_SAVE_TITLE#">#MESS_TOOL_SAVE#</a>
  144. <a class="bx-editor-block-tools-btn bx-editor-block-tools-cancel" title="#MESS_TOOL_CANCEL_TITLE#">#MESS_TOOL_CANCEL#</a>
  145. </div>
  146. <div class="block-edit-tabs">
  147. <div class="block-edit-tabs-inner">
  148. <span data-bx-block-editor-settings-tab="cont" class="bx-editor-block-tab active">#MESS_TOOL_CONTENT#</span>
  149. <span data-bx-block-editor-settings-tab="style" class="bx-editor-block-tab">#MESS_TOOL_STYLES#</span>
  150. <span data-bx-block-editor-settings-tab="prop" class="bx-editor-block-tab">#MESS_TOOL_SETTINGS#</span>
  151. </div>
  152. </div>
  153. </div>
  154. <div class="block-edit-form-empty">
  155. #MESS_TOOL_EMPTY#
  156. </div>
  157. <div class="block-edit-form">
  158. #tools#
  159. </div>
  160. </div>
  161. HTML
  162. ,
  163. 'panel-preview' => <<<HTML
  164. <div class="bx-block-editor-preview-container">
  165. <div class="shadow">
  166. <div class="edit-text"></div>
  167. <div class="error-text">#MESS_ACCESS_DENIED#</div>
  168. </div>
  169. <div class="devices">
  170. #devices#
  171. </div>
  172. <center>
  173. <div class="iframe-wrapper">
  174. <iframe sandbox="allow-same-origin allow-forms" class="preview-iframe" src=""></iframe>
  175. </div>
  176. </center>
  177. </div>
  178. <div style="clear:both;"></div>
  179. HTML
  180. ,
  181. 'panel-get-html' => <<<HTML
  182. <textarea style="width: 100%; height: 100%; min-height: 400px;" onfocus="this.select()"></textarea>
  183. HTML
  184. );
  185. /**
  186. * Return editor object
  187. *
  188. * @param array $params
  189. * @return Editor
  190. */
  191. public static function createInstance($params)
  192. {
  193. return new static($params);
  194. }
  195. /**
  196. * Create editor object.
  197. *
  198. * @param array $params
  199. */
  200. public function __construct($params)
  201. {
  202. $this->id = $params['id'];
  203. $this->url = $params['url'];
  204. $this->previewUrl = isset($params['previewUrl']) ? $params['previewUrl'] : '/bitrix/admin/fileman_block_editor.php?action=preview';
  205. $this->saveFileUrl = isset($params['saveFileUrl']) ? $params['saveFileUrl'] : '/bitrix/admin/fileman_block_editor.php?action=save_file';
  206. $this->templateType = $params['templateType'];
  207. $this->templateId = $params['templateId'];
  208. $this->site = $params['site'];
  209. $this->charset = $params['charset'];
  210. $this->isTemplateMode = isset($params['isTemplateMode']) ? (bool) $params['isTemplateMode'] : false;
  211. $this->useLightTextEditor = isset($params['useLightTextEditor']) ? (bool) $params['useLightTextEditor'] : false;
  212. $this->isUserHavePhpAccess = isset($params['isUserHavePhpAccess']) ? (bool) $params['isUserHavePhpAccess'] : false;
  213. $this->ownResultId = isset($params['own_result_id']) ? $params['own_result_id'] : true;
  214. $this->componentFilter = isset($params['componentFilter']) ? $params['componentFilter'] : array();
  215. $this->setToolList($this->getDefaultToolList());
  216. $this->previewModes = array(
  217. array('CLASS' => 'phone', 'NAME' => Loc::getMessage('BLOCK_EDITOR_PREVIEW_MODE_PHONE'), 'WIDTH' => 320, 'HEIGHT' => 480),
  218. array('CLASS' => 'tablet', 'NAME' => Loc::getMessage('BLOCK_EDITOR_PREVIEW_MODE_TABLET'), 'WIDTH' => 768, 'HEIGHT' => 1024),
  219. array('CLASS' => 'desktop', 'NAME' => Loc::getMessage('BLOCK_EDITOR_PREVIEW_MODE_DESKTOP'), 'WIDTH' => 1024, 'HEIGHT' => 768),
  220. );
  221. $this->tabs = array(
  222. 'edit' => array('NAME' => Loc::getMessage('BLOCK_EDITOR_TABS_EDIT'), 'ACTIVE' => true),
  223. 'preview' => array('NAME' => Loc::getMessage('BLOCK_EDITOR_TABS_PREVIEW'), 'ACTIVE' => false),
  224. //'get-html' => array('NAME' => Loc::getMessage('BLOCK_EDITOR_TABS_HTML'), 'ACTIVE' => false),
  225. );
  226. }
  227. /**
  228. * Set custom blocks
  229. *
  230. * @param array $blocks
  231. * @return void
  232. */
  233. public function setBlockList(array $blocks)
  234. {
  235. $this->blocks = $blocks;
  236. if(!is_array($this->blocks))
  237. {
  238. $this->blocks = array();
  239. }
  240. foreach($this->blocks as $key => $block)
  241. {
  242. if(!isset($block['TYPE']))
  243. {
  244. $block['TYPE'] = $block['CODE'];
  245. }
  246. $block['IS_COMPONENT'] = false;
  247. $block['CLASS'] = $block['CODE'];
  248. $this->blocks[$key] = $block;
  249. }
  250. $componentsNotAsBlocks = array();
  251. if (!$this->useLightTextEditor)
  252. {
  253. $componentList = $this->getComponentList();
  254. foreach($componentList as $component)
  255. {
  256. if(!isset($this->componentsAsBlocks[$component['NAME']]))
  257. {
  258. $componentsNotAsBlocks[] = array(
  259. 'TYPE' => 'component',
  260. 'IS_COMPONENT' => true,
  261. 'CODE' => $component['NAME'],
  262. 'NAME' => $component['TITLE'],
  263. 'DESC' => $component['TITLE'] . ".\n" . $component['DESCRIPTION'],
  264. 'HTML' => ''
  265. );
  266. }
  267. else
  268. {
  269. $interfaceName = $this->componentsAsBlocks[$component['NAME']]['NAME'];
  270. $this->blocks[] = array(
  271. 'TYPE' => 'component',
  272. 'IS_COMPONENT' => false,
  273. 'CODE' => $component['NAME'],
  274. 'NAME' => $interfaceName ? $interfaceName : $component['TITLE'],
  275. 'DESC' => $component['DESCRIPTION'],
  276. 'HTML' => ''
  277. );
  278. }
  279. }
  280. }
  281. $this->blocks = array_merge($this->blocks, $componentsNotAsBlocks);
  282. }
  283. /**
  284. * Set custom tools
  285. *
  286. * @param array $tools
  287. * @return void
  288. */
  289. public function setToolList(array $tools)
  290. {
  291. $this->tools = $tools;
  292. }
  293. /**
  294. * Return list of default blocks
  295. *
  296. * @return array
  297. */
  298. public function getDefaultBlockList()
  299. {
  300. return array(
  301. array(
  302. 'CODE' => 'text',
  303. 'NAME' => Loc::getMessage('BLOCK_EDITOR_BLOCK_TEXT_NAME'),
  304. 'DESC' => Loc::getMessage('BLOCK_EDITOR_BLOCK_TEXT_DESC'),
  305. 'HTML' => Loc::getMessage('BLOCK_EDITOR_BLOCK_TEXT_EXAMPLE')
  306. ),
  307. );
  308. }
  309. /**
  310. * Return true if can use Russian services.
  311. *
  312. * @return bool
  313. */
  314. public static function isAvailableRussian()
  315. {
  316. if (!Loader::includeModule('bitrix24'))
  317. {
  318. return true;
  319. }
  320. return in_array(\CBitrix24::getPortalZone(), array('ru', 'kz', 'by'));
  321. }
  322. /**
  323. * Return list of default tools, uses for block changing
  324. *
  325. * @return array
  326. */
  327. public function getDefaultToolList()
  328. {
  329. $isUserHavePhpAccess = $this->isUserHavePhpAccess;
  330. $useLightTextEditor = $this->useLightTextEditor;
  331. $resultList = array();
  332. $resultList[] = array(
  333. 'GROUP' => 'cont',
  334. 'ID' => 'html-raw',
  335. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_HTML_RAW'),
  336. 'HTML' => '<textarea style="width:600px; height: 400px;" data-bx-editor-tool-input="item"></textarea>',
  337. );
  338. $resultList[] = array(
  339. 'GROUP' => 'cont',
  340. 'ID' => 'src',
  341. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_SRC'),
  342. 'HTML' => '<input type="hidden" data-bx-editor-tool-input="item" value="">'
  343. . \Bitrix\Main\UI\FileInput::createInstance((array(
  344. "id" => "BX_BLOCK_EDITOR_SRC_" . $this->id,
  345. "name" => "NEW_FILE_EDITOR[n#IND#]",
  346. "upload" => true,
  347. "medialib" => true,
  348. "fileDialog" => true,
  349. "cloud" => true
  350. )))->show()
  351. );
  352. $resultList[] = array(
  353. 'GROUP' => 'cont',
  354. 'ID' => 'title',
  355. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_TITLE'),
  356. 'HTML' => Tools::getControlInput(),
  357. );
  358. $resultList[] = array(
  359. 'GROUP' => 'cont',
  360. 'ID' => 'href',
  361. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_HREF'),
  362. 'HTML' => Tools::getControlInput(),
  363. );
  364. \Bitrix\Main\Loader::includeModule('fileman');
  365. ob_start();
  366. ?>
  367. <div class="column" data-bx-editor-column="item">
  368. <?for ($columnNumber = 1; $columnNumber < 5; $columnNumber++):?>
  369. <span data-bx-editor-column-number="<?=$columnNumber?>"
  370. style="display: none;">
  371. <?=Loc::getMessage('BLOCK_EDITOR_TOOL_COLUMN')?> <?=$columnNumber?>
  372. </span>
  373. <?endfor;?>
  374. </div>
  375. <?
  376. if ($useLightTextEditor)
  377. {
  378. echo '<div style="color: #bfbfbf; font-size: 17px; padding: 0 0; position: relative;">';
  379. $editor = new \CHTMLEditor;
  380. $res = array_merge(
  381. array(
  382. 'height' => 400,
  383. 'minBodyWidth' => 350,
  384. 'normalBodyWidth' => 555,
  385. 'bAllowPhp' => false,
  386. 'limitPhpAccess' => false,
  387. 'showTaskbars' => false,
  388. 'showNodeNavi' => false,
  389. 'askBeforeUnloadPage' => true,
  390. 'useFileDialogs' => !IsModuleInstalled('intranet'),
  391. 'bbCode' => false,
  392. 'siteId' => SITE_ID,
  393. 'autoResize' => false,
  394. 'autoResizeOffset' => 40,
  395. 'saveOnBlur' => true,
  396. 'controlsMap' => array(
  397. array('id' => 'placeholder_selector', 'compact' => true, 'sort' => 60),
  398. array('id' => 'StyleSelector', 'compact' => true, 'sort' => 70),
  399. array('id' => 'Bold', 'compact' => true, 'sort' => 80),
  400. array('id' => 'Italic', 'compact' => true, 'sort' => 90),
  401. array('id' => 'Underline', 'compact' => true, 'sort' => 100),
  402. array('id' => 'Strikeout', 'compact' => true, 'sort' => 110),
  403. array('id' => 'RemoveFormat', 'compact' => true, 'sort' => 120),
  404. array('id' => 'Color', 'compact' => true, 'sort' => 130),
  405. array('id' => 'FontSelector', 'compact' => false, 'sort' => 135),
  406. array('id' => 'FontSize', 'compact' => false, 'sort' => 140),
  407. //array('separator' => true, 'compact' => false, 'sort' => 145),
  408. array('id' => 'OrderedList', 'compact' => true, 'sort' => 150),
  409. array('id' => 'UnorderedList', 'compact' => true, 'sort' => 160),
  410. array('id' => 'AlignList', 'compact' => false, 'sort' => 190),
  411. //array('separator' => true, 'compact' => false, 'sort' => 200),
  412. array('id' => 'InsertLink', 'compact' => true, 'sort' => 210),
  413. //array('id' => 'InsertImage', 'compact' => false, 'sort' => 220),
  414. //array('id' => 'InsertVideo', 'compact' => true, 'sort' => 230, 'wrap' => 'bx-b-video-'.$arParams["FORM_ID"]),
  415. //array('id' => 'InsertTable', 'compact' => false, 'sort' => 250),
  416. //array('id' => 'Code', 'compact' => true, 'sort' => 260),
  417. //array('id' => 'Quote', 'compact' => true, 'sort' => 270, 'wrap' => 'bx-b-quote-'.$arParams["FORM_ID"]),
  418. //array('id' => 'Smile', 'compact' => false, 'sort' => 280),
  419. //array('separator' => true, 'compact' => false, 'sort' => 290),
  420. array('id' => 'RemoveFormat', 'compact' => false, 'sort' => 310),
  421. array('id' => 'Fullscreen', 'compact' => false, 'sort' => 320),
  422. array('id' => 'BbCode', 'compact' => true, 'sort' => 340),
  423. array('id' => 'More', 'compact' => true, 'sort' => 400)
  424. )
  425. ),
  426. array(
  427. 'name' => 'BX_BLOCK_EDITOR_CONTENT_' . $this->id,
  428. 'id' => 'BX_BLOCK_EDITOR_CONTENT_' . $this->id,
  429. 'width' => '100%',
  430. 'arSmilesSet' => array(),
  431. 'arSmiles' => array(),
  432. 'content' => '',
  433. 'iframeCss' => 'body{font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; font-size: 13px;}'.
  434. '.bx-spoiler {border:1px solid #C0C0C0;background-color:#fff4ca;padding: 4px 4px 4px 24px;color:#373737;border-radius:2px;min-height:1em;margin: 0;}',
  435. )
  436. );
  437. $editor->Show($res);
  438. echo '</div>';
  439. }
  440. else
  441. {
  442. \CFileMan::AddHTMLEditorFrame(
  443. 'BX_BLOCK_EDITOR_CONTENT_' . $this->id,
  444. '',
  445. false,
  446. "html",
  447. array(
  448. 'height' => '200',
  449. 'width' => '100%'
  450. ),
  451. "N",
  452. 0,
  453. "",
  454. '',//'data-bx-editor-tool-input="content"',
  455. false,
  456. !$isUserHavePhpAccess,
  457. false,
  458. array(
  459. //'templateID' => $str_SITE_TEMPLATE_ID,
  460. 'componentFilter' => $this->componentFilter,
  461. 'limit_php_access' => !$isUserHavePhpAccess,
  462. 'hideTypeSelector' => true,
  463. 'minBodyWidth' => '420',
  464. 'normalBodyWidth' => '420',
  465. )
  466. );
  467. }
  468. $resultList[] = array(
  469. 'GROUP' => 'cont',
  470. 'ID' => 'content',
  471. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_CONTENT'),
  472. 'HTML' => '<input type="hidden" data-bx-editor-tool-input="item" value="">' . ob_get_clean()
  473. );
  474. ob_start();
  475. ?>
  476. <script type="text/template" id="template-social-item">
  477. <table style="background-color: #E9E9E9;">
  478. <tr>
  479. <td><?=Loc::getMessage('BLOCK_EDITOR_TOOL_SOCIAL_CONTENT_ADDRESS')?></td>
  480. <td>
  481. <input class="href" type="text" value="#href#">
  482. <select class="preset">
  483. <option value=""><?=Loc::getMessage('BLOCK_EDITOR_TOOL_SOCIAL_CONTENT_SELECT')?></option>
  484. <option value="http://#SERVER_NAME#/"><?=Loc::getMessage('BLOCK_EDITOR_TOOL_SOCIAL_CONTENT_OURSITE')?></option>
  485. <?if (self::isAvailableRussian()):?>
  486. <option value="http://vk.com/"><?=Loc::getMessage('BLOCK_EDITOR_TOOL_SOCIAL_CONTENT_VK')?></option>
  487. <option value="http://ok.ru/"><?=Loc::getMessage('BLOCK_EDITOR_TOOL_SOCIAL_CONTENT_OK')?></option>
  488. <?endif;?>
  489. <option value="http://facebook.com/"><?=Loc::getMessage('BLOCK_EDITOR_TOOL_SOCIAL_CONTENT_FACEBOOK')?></option>
  490. <option value="http://instagram.com/"><?=Loc::getMessage('BLOCK_EDITOR_TOOL_SOCIAL_CONTENT_INSTAGRAM')?></option>
  491. <option value="http://twitter.com/"><?=Loc::getMessage('BLOCK_EDITOR_TOOL_SOCIAL_CONTENT_TWITTER')?></option>
  492. <option value="http://"><?=Loc::getMessage('BLOCK_EDITOR_TOOL_SOCIAL_CONTENT_SITE')?></option>
  493. <option value="mailto:"><?=Loc::getMessage('BLOCK_EDITOR_TOOL_SOCIAL_CONTENT_EMAIL')?></option>
  494. </select>
  495. </td>
  496. </tr>
  497. <tr>
  498. <td><?=Loc::getMessage('BLOCK_EDITOR_TOOL_SOCIAL_CONTENT_NAME')?></td>
  499. <td>
  500. <input class="name" type="text" value="#name#">
  501. <input class="delete" type="button" value="<?=Loc::getMessage('BLOCK_EDITOR_TOOL_SOCIAL_CONTENT_BTN_DELETE')?>">
  502. </td>
  503. </tr>
  504. </table>
  505. <br/>
  506. </script>
  507. <div class="container"></div>
  508. <input class="add" type="button" value="<?=Loc::getMessage('BLOCK_EDITOR_TOOL_SOCIAL_CONTENT_BTN_ADD')?>">
  509. <?
  510. $resultList[] = array(
  511. 'GROUP' => 'cont',
  512. 'ID' => 'social_content',
  513. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_SOCIAL_CONTENT'),
  514. 'HTML' => '<input type="hidden" data-bx-editor-tool-input="item" value="">' . ob_get_clean()
  515. );
  516. $resultList[] = array(
  517. 'GROUP' => 'cont',
  518. 'ID' => 'button_caption',
  519. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_BUTTON_CAPTION'),
  520. 'HTML' => Tools::getControlInput(),
  521. );
  522. $resultList[] = array(
  523. 'GROUP' => 'style',
  524. 'ID' => 'font-size',
  525. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_FONT_SIZE'),
  526. 'HTML' => Tools::getControlFontSize(),
  527. );
  528. $resultList[] = array(
  529. 'GROUP' => 'style',
  530. 'ID' => 'text-align',
  531. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_TEXT_ALIGN'),
  532. 'HTML' => Tools::getControlTextAlign(),
  533. );
  534. $resultList[] = array(
  535. 'GROUP' => 'style',
  536. 'ID' => 'border',
  537. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_BORDER'),
  538. 'HTML' => '<input type="hidden" data-bx-editor-tool-input="item" id="block_editor_style_border">
  539. <select id="block_editor_style_border_style">
  540. <option value="">' . Loc::getMessage('BLOCK_EDITOR_COMMON_NO') . '</option>
  541. <option value="solid">' . Loc::getMessage('BLOCK_EDITOR_TOOL_BORDER_SOLID') . '</option>
  542. <option value="dashed">' . Loc::getMessage('BLOCK_EDITOR_TOOL_BORDER_DASHED') . '</option>
  543. <option value="dotted">' . Loc::getMessage('BLOCK_EDITOR_TOOL_BORDER_DOTTED') . '</option>
  544. </select>
  545. <select id="block_editor_style_border_width" style="width: 80px; min-width: 80px;">
  546. <option value="">' . Loc::getMessage('BLOCK_EDITOR_COMMON_NO') . '</option>
  547. <option value="1px">1px</option>
  548. <option value="2px">2px</option>
  549. <option value="3px">3px</option>
  550. <option value="4px">4px</option>
  551. <option value="5px">5px</option>
  552. <option value="6px">6px</option>
  553. <option value="7px">7px</option>
  554. </select>
  555. <input id="block_editor_style_border_color" type="hidden" class="bx-editor-color-picker">
  556. <span class="bx-editor-color-picker-view"></span>
  557. <span class="bx-editor-color-picker-text">' . Loc::getMessage('BLOCK_EDITOR_TOOLS_COLOR') .'</span>
  558. ',
  559. );
  560. $resultList[] = array(
  561. 'GROUP' => 'style',
  562. 'ID' => 'background-color',
  563. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_BACKGROUND_COLOR'),
  564. 'HTML' => Tools::getControlColor(),
  565. );
  566. $resultList[] = array(
  567. 'GROUP' => 'style',
  568. 'ID' => 'border-radius',
  569. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_BORDER_RADIUS'),
  570. 'HTML' => Tools::getControlBorderRadius(),
  571. );
  572. $resultList[] = array(
  573. 'GROUP' => 'style',
  574. 'ID' => 'color',
  575. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_COLOR'),
  576. 'HTML' => Tools::getControlColor(),
  577. );
  578. $resultList[] = array(
  579. 'GROUP' => 'style',
  580. 'ID' => 'font-family',
  581. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_FONT_FAMILY'),
  582. 'HTML' => Tools::getControlFontFamily(),
  583. );
  584. $resultList[] = array(
  585. 'GROUP' => 'prop',
  586. 'ID' => 'align',
  587. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_ALIGN'),
  588. 'HTML' => Tools::getControlTextAlign(),
  589. );
  590. $resultList[] = array(
  591. 'GROUP' => 'style',
  592. 'ID' => 'text-decoration',
  593. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_TEXT_DECORATION'),
  594. 'HTML' => Tools::getControlTextDecoration(),
  595. );
  596. $resultList[] = array(
  597. 'GROUP' => 'prop',
  598. 'ID' => 'align',
  599. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_ALIGN'),
  600. 'HTML' => Tools::getControlTextAlign(),
  601. );
  602. $resultList[] = array(
  603. 'GROUP' => 'prop',
  604. 'ID' => 'imagetextalign',
  605. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_IMAGETEXTALIGN'),
  606. 'HTML' => Tools::getControlSelect(array(
  607. 'left' => Loc::getMessage('BLOCK_EDITOR_CTRL_ALIGN_LEFT'),
  608. 'right' => Loc::getMessage('BLOCK_EDITOR_CTRL_ALIGN_RIGHT')
  609. ), false)
  610. );
  611. $resultList[] = array(
  612. 'GROUP' => 'prop',
  613. 'ID' => 'imagetextpart',
  614. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_IMAGETEXTPART'),
  615. 'HTML' => Tools::getControlSelect(
  616. array(
  617. '1/4' => Loc::getMessage('BLOCK_EDITOR_TOOL_IMAGETEXTPART14'),
  618. '1/3' => Loc::getMessage('BLOCK_EDITOR_TOOL_IMAGETEXTPART13'),
  619. '1/2' => Loc::getMessage('BLOCK_EDITOR_TOOL_IMAGETEXTPART12'),
  620. '2/3' => Loc::getMessage('BLOCK_EDITOR_TOOL_IMAGETEXTPART23')
  621. ),
  622. false)
  623. );
  624. $resultList[] = array(
  625. 'GROUP' => 'prop',
  626. 'ID' => 'height',
  627. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_HEIGHT'),
  628. 'HTML' => Tools::getControlInput(),
  629. );
  630. $resultList[] = array(
  631. 'GROUP' => 'prop',
  632. 'ID' => 'margin-top',
  633. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_MARGIN_TOP'),
  634. 'HTML' => Tools::getControlPaddingBottoms(),
  635. );
  636. $resultList[] = array(
  637. 'GROUP' => 'prop',
  638. 'ID' => 'margin-bottom',
  639. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_MARGIN_BOTTOM'),
  640. 'HTML' => Tools::getControlPaddingBottoms(),
  641. );
  642. $resultList[] = array(
  643. 'GROUP' => 'prop',
  644. 'ID' => 'groupimage-view',
  645. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_GROUPIMAGE_VIEW'),
  646. 'HTML' => Tools::getControlSelect(
  647. array(
  648. '' => Loc::getMessage('BLOCK_EDITOR_TOOL_GROUPIMAGE_VIEW_2COL'),
  649. '1' => Loc::getMessage('BLOCK_EDITOR_TOOL_GROUPIMAGE_VIEW_1COL')
  650. ),
  651. false
  652. ),
  653. );
  654. $resultList[] = array(
  655. 'GROUP' => 'prop',
  656. 'ID' => 'column-count',
  657. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_COLUMN_COUNT'),
  658. 'HTML' => Tools::getControlSelect(array('1' => '1', '2' => '2', '3' => '3'), false),
  659. );
  660. $resultList[] = array(
  661. 'GROUP' => 'prop',
  662. 'ID' => 'paddings',
  663. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_PADDINGS'),
  664. 'HTML' => Tools::getControlSelect(
  665. array(
  666. 'Y' => Loc::getMessage('BLOCK_EDITOR_TOOL_PADDINGS_STANDARD'),
  667. 'N' => Loc::getMessage('BLOCK_EDITOR_TOOL_PADDINGS_WITHOUT')
  668. ),
  669. false
  670. ),
  671. );
  672. $resultList[] = array(
  673. 'GROUP' => 'prop',
  674. 'ID' => 'wide',
  675. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_WIDE'),
  676. 'HTML' => Tools::getControlSelect(
  677. array(
  678. 'N' => Loc::getMessage('BLOCK_EDITOR_TOOL_WIDE_N'),
  679. 'Y' => Loc::getMessage('BLOCK_EDITOR_TOOL_WIDE_Y')
  680. )
  681. , false
  682. ),
  683. );
  684. $resultList[] = array(
  685. 'GROUP' => 'style',
  686. 'ID' => 'bx-stylist-bgcolor',
  687. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_BACKGROUND_COLOR'),
  688. 'HTML' => Tools::getControlColor(),
  689. );
  690. $resultList[] = array(
  691. 'GROUP' => 'style',
  692. 'ID' => 'bx-stylist-padding-top',
  693. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_MARGIN_TOP'),
  694. 'HTML' => Tools::getControlPaddingBottoms(),
  695. );
  696. $resultList[] = array(
  697. 'GROUP' => 'style',
  698. 'ID' => 'bx-stylist-padding-bottom',
  699. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_MARGIN_BOTTOM'),
  700. 'HTML' => Tools::getControlPaddingBottoms(),
  701. );
  702. $resultList[] = array(
  703. 'GROUP' => 'style',
  704. 'ID' => 'bx-stylist-text-color',
  705. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_STYLIST_TEXT') . ' ' . Loc::getMessage('BLOCK_EDITOR_TOOL_COLOR'),
  706. 'HTML' => Tools::getControlColor(),
  707. );
  708. $resultList[] = array(
  709. 'GROUP' => 'style',
  710. 'ID' => 'bx-stylist-text-font-family',
  711. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_STYLIST_TEXT') . ' ' . Loc::getMessage('BLOCK_EDITOR_TOOL_FONT_FAMILY'),
  712. 'HTML' => Tools::getControlFontFamily(),
  713. );
  714. $resultList[] = array(
  715. 'GROUP' => 'style',
  716. 'ID' => 'bx-stylist-text-font-size',
  717. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_STYLIST_TEXT') . ' ' . Loc::getMessage('BLOCK_EDITOR_TOOL_FONT_SIZE'),
  718. 'HTML' => Tools::getControlFontSize(),
  719. );
  720. $resultList[] = array(
  721. 'GROUP' => 'style',
  722. 'ID' => 'bx-stylist-text-font-weight',
  723. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_STYLIST_TEXT') . ' ' . Loc::getMessage('BLOCK_EDITOR_TOOL_FONT_WEIGHT'),
  724. 'HTML' => Tools::getControlFontWeight(),
  725. );
  726. $resultList[] = array(
  727. 'GROUP' => 'style',
  728. 'ID' => 'bx-stylist-text-line-height',
  729. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_STYLIST_TEXT') . ' ' . Loc::getMessage('BLOCK_EDITOR_TOOL_LINE_HEIGHT'),
  730. 'HTML' => Tools::getControlLineHeight(),
  731. );
  732. $resultList[] = array(
  733. 'GROUP' => 'style',
  734. 'ID' => 'bx-stylist-text-text-align',
  735. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_STYLIST_TEXT') . ' ' . Loc::getMessage('BLOCK_EDITOR_TOOL_TEXT_ALIGN'),
  736. 'HTML' => Tools::getControlTextAlign(),
  737. );
  738. $resultList[] = array(
  739. 'GROUP' => 'style',
  740. 'ID' => 'bx-stylist-a-color',
  741. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_STYLIST_LINK') . ' ' . Loc::getMessage('BLOCK_EDITOR_TOOL_COLOR'),
  742. 'HTML' => Tools::getControlColor(),
  743. );
  744. $resultList[] = array(
  745. 'GROUP' => 'style',
  746. 'ID' => 'bx-stylist-a-font-weight',
  747. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_STYLIST_LINK') . ' ' . Loc::getMessage('BLOCK_EDITOR_TOOL_FONT_WEIGHT'),
  748. 'HTML' => Tools::getControlFontWeight(),
  749. );
  750. $resultList[] = array(
  751. 'GROUP' => 'style',
  752. 'ID' => 'bx-stylist-a-text-decoration',
  753. 'NAME' => Loc::getMessage('BLOCK_EDITOR_TOOL_STYLIST_LINK') . ' ' . Loc::getMessage('BLOCK_EDITOR_TOOL_TEXT_DECORATION'),
  754. 'HTML' => Tools::getControlTextDecoration(),
  755. );
  756. for($i = 1; $i <= 4; $i++)
  757. {
  758. $resultList[] = array(
  759. 'GROUP' => 'style',
  760. 'ID' => 'bx-stylist-h' . $i . '-color',
  761. 'NAME' => 'H' . $i . ' ' . Loc::getMessage('BLOCK_EDITOR_TOOL_COLOR'),
  762. 'HTML' => Tools::getControlColor(),
  763. );
  764. $resultList[] = array(
  765. 'GROUP' => 'style',
  766. 'ID' => 'bx-stylist-h' . $i . '-font-size',
  767. 'NAME' => 'H' . $i . ' ' . Loc::getMessage('BLOCK_EDITOR_TOOL_FONT_SIZE'),
  768. 'HTML' => Tools::getControlFontSize(),
  769. );
  770. $resultList[] = array(
  771. 'GROUP' => 'style',
  772. 'ID' => 'bx-stylist-h' . $i . '-font-weight',
  773. 'NAME' => 'H' . $i . ' ' . Loc::getMessage('BLOCK_EDITOR_TOOL_FONT_WEIGHT'),
  774. 'HTML' => Tools::getControlFontWeight(),
  775. );
  776. $resultList[] = array(
  777. 'GROUP' => 'style',
  778. 'ID' => 'bx-stylist-h' . $i . '-line-height',
  779. 'NAME' => 'H' . $i . ' ' . Loc::getMessage('BLOCK_EDITOR_TOOL_LINE_HEIGHT'),
  780. 'HTML' => Tools::getControlLineHeight(),
  781. );
  782. $resultList[] = array(
  783. 'GROUP' => 'style',
  784. 'ID' => 'bx-stylist-h' . $i . '-text-align',
  785. 'NAME' => 'H' . $i . ' ' . Loc::getMessage('BLOCK_EDITOR_TOOL_TEXT_ALIGN'),
  786. 'HTML' => Tools::getControlTextAlign(),
  787. );
  788. }
  789. return $resultList;
  790. }
  791. /**
  792. * Return html of interface part.
  793. *
  794. * @param string $id
  795. * @param array $values
  796. * @return string
  797. */
  798. public function getUI($id, array $values)
  799. {
  800. if(!array_key_exists($id, $this->uiPatterns) || trim($this->uiPatterns[$id]) == '')
  801. {
  802. return '';
  803. }
  804. $placeholders = array_keys($values);
  805. $placeholders = '#' . implode('#,#', $placeholders) . '#';
  806. $placeholders = explode(',', $placeholders);
  807. return str_replace($placeholders, array_values($values), $this->uiPatterns[$id]);
  808. }
  809. /**
  810. * Return html of editor interface without resources.
  811. *
  812. * @return string
  813. */
  814. public function showEditor()
  815. {
  816. $textArea = '';
  817. $panels = '';
  818. $tabs = '';
  819. $blocks = '';
  820. $tools = '';
  821. $devices = '';
  822. foreach(array_chunk($this->blocks, static::BLOCK_COUNT_PER_PAGE) as $blocksPerPage)
  823. {
  824. $blocksForPage = '';
  825. foreach($blocksPerPage as $block)
  826. {
  827. $blocksForPage .= $this->getUI('block', array(
  828. 'type_class' => htmlspecialcharsbx($block['IS_COMPONENT'] ? 'component' : 'blockcomponent'),
  829. 'code_class' => htmlspecialcharsbx(str_replace(array(':', '.'), array('-', '-'), $block['CODE'])),
  830. 'type' => htmlspecialcharsbx($block['TYPE']),
  831. 'code' => htmlspecialcharsbx($block['CODE']),
  832. 'name' => htmlspecialcharsbx($block['NAME']),
  833. 'desc' => htmlspecialcharsbx($block['DESC']),
  834. ));
  835. }
  836. $blocks .= $this->getUI('block_page', array('blocks' => $blocksForPage));
  837. }
  838. foreach($this->tools as $tool)
  839. {
  840. $tools .= $this->getUI('tool', array(
  841. 'group' => htmlspecialcharsbx($tool['GROUP']),
  842. 'id' => htmlspecialcharsbx($tool['ID']),
  843. 'name' => htmlspecialcharsbx($tool['NAME']),
  844. 'html' => $tool['HTML'],
  845. ));
  846. }
  847. foreach($this->previewModes as $mode)
  848. {
  849. $devices .= $this->getUI('device', array(
  850. 'MESS_NAME' => mb_strtoupper(htmlspecialcharsbx($mode['NAME'])),
  851. 'class' => htmlspecialcharsbx($mode['CLASS']),
  852. 'width' => htmlspecialcharsbx($mode['WIDTH']),
  853. 'height' => htmlspecialcharsbx($mode['HEIGHT']),
  854. ));
  855. }
  856. if(!$this->ownResultId)
  857. {
  858. $this->ownResultId = 'bx-block-editor-result-' . htmlspecialcharsbx($this->id);
  859. $textArea = '<textarea name="' . htmlspecialcharsbx($this->id) . '" id="' . htmlspecialcharsbx($this->ownResultId)
  860. .'" style="width:800px;height:900px; display: none;"></textarea>';
  861. }
  862. foreach($this->tabs as $tabCode => $tab)
  863. {
  864. if(!isset($this->uiPatterns['panel-' . $tabCode]))
  865. {
  866. continue;
  867. }
  868. $tabs .= $this->getUI('tab', array(
  869. 'code' => htmlspecialcharsbx($tabCode),
  870. 'name' => htmlspecialcharsbx($tab['NAME']),
  871. 'tab_active' => ($tab['ACTIVE'] ? $this->getUI('tab_active', array()) : '')
  872. ));
  873. $panel = $this->getUI('panel-' . $tabCode, array(
  874. 'id' => htmlspecialcharsbx($this->id),
  875. 'blocks' => $blocks,
  876. 'tools' => $tools,
  877. 'devices' => $devices,
  878. 'nav-display' => count($this->blocks) <= static::BLOCK_COUNT_PER_PAGE ? 'bx-block-hide' : '',
  879. 'MESS_ACCESS_DENIED' => Loc::getMessage('ACCESS_DENIED'),
  880. 'MESS_STYLES' => Loc::getMessage('BLOCK_EDITOR_UI_STYLES'),
  881. 'MESS_BLOCKS' => Loc::getMessage('BLOCK_EDITOR_UI_BLOCKS'),
  882. 'MESS_TOOL_CONTENT' => Loc::getMessage('BLOCK_EDITOR_UI_TOOL_CONTENT'),
  883. 'MESS_TOOL_STYLES' => Loc::getMessage('BLOCK_EDITOR_UI_TOOL_STYLES'),
  884. 'MESS_TOOL_SETTINGS' => Loc::getMessage('BLOCK_EDITOR_UI_TOOL_SETTINGS'),
  885. 'MESS_TOOL_EMPTY' => Loc::getMessage('BLOCK_EDITOR_UI_TOOL_EMPTY'),
  886. 'MESS_TOOL_SAVE' => Loc::getMessage('BLOCK_EDITOR_UI_TOOL_SAVE'),
  887. 'MESS_TOOL_SAVE_TITLE' => Loc::getMessage('BLOCK_EDITOR_UI_TOOL_SAVE_TITLE'),
  888. 'MESS_TOOL_CANCEL' => Loc::getMessage('BLOCK_EDITOR_UI_TOOL_CANCEL'),
  889. 'MESS_TOOL_CANCEL_TITLE' => Loc::getMessage('BLOCK_EDITOR_UI_TOOL_CANCEL_TITLE'),
  890. ));
  891. $panels .= $this->getUI('panel', array(
  892. 'code' => htmlspecialcharsbx($tabCode),
  893. 'panel_hidden' => (!$tab['ACTIVE'] ? $this->getUI('panel_hidden', array()) : ''),
  894. 'html' => $panel
  895. ));
  896. }
  897. return $this->getUI('main', array(
  898. 'TEXTAREA' => $textArea,
  899. 'id' => htmlspecialcharsbx($this->id),
  900. 'tabs' => $tabs,
  901. 'panels' => $panels,
  902. 'MESS_BTN_MAX' => Loc::getMessage('BLOCK_EDITOR_UI_BTN_MAX'),
  903. 'MESS_BTN_MIN' => Loc::getMessage('BLOCK_EDITOR_UI_BTN_MIN'),
  904. 'MESS_BTN_HTML_COPY' => Loc::getMessage('BLOCK_EDITOR_UI_BTN_HTML_COPY'),
  905. ));
  906. }
  907. /**
  908. * Return html for showing editor and include all resources
  909. *
  910. * @return string
  911. */
  912. public function show()
  913. {
  914. \CJSCore::RegisterExt('block_editor', array(
  915. 'js' => array(
  916. '/bitrix/js/main/core/core_dragdrop.js',
  917. '/bitrix/js/fileman/block_editor/dialog.js',
  918. '/bitrix/js/fileman/block_editor/helper.js',
  919. '/bitrix/js/fileman/block_editor/editor.js',
  920. ),
  921. 'css' => '/bitrix/js/fileman/block_editor/dialog.css',
  922. 'lang' => '/bitrix/modules/fileman/lang/' . LANGUAGE_ID . '/js_block_editor.php',
  923. ));
  924. \CJSCore::Init(array("block_editor", "color_picker", "clipboard"));
  925. static $isBlockEditorManagerInited = false;
  926. $editorBlockTypeListByCode = array();
  927. if(!$isBlockEditorManagerInited)
  928. {
  929. foreach($this->blocks as $block)
  930. {
  931. $editorBlockTypeListByCode[$block['CODE']] = $block;
  932. }
  933. }
  934. $jsCreateParams = array(
  935. 'id' => $this->id,
  936. 'url' => $this->url,
  937. 'previewUrl' => $this->previewUrl,
  938. 'saveFileUrl' => $this->saveFileUrl,
  939. 'templateType' => $this->templateType,
  940. 'templateId' => $this->templateId,
  941. 'isTemplateMode' => $this->isTemplateMode,
  942. 'site' => $this->site,
  943. 'charset' => $this->charset
  944. );
  945. $result = '';
  946. if(!$isBlockEditorManagerInited)
  947. {
  948. $result .= 'BX.BlockEditorManager.setBlockList(' . \CUtil::PhpToJSObject($editorBlockTypeListByCode) . ");\n";
  949. }
  950. $result .= "var blockEditorParams = " . \CUtil::PhpToJSObject($jsCreateParams) . ";\n";
  951. $result .= "blockEditorParams['context'] = BX('bx-block-editor-container-" . htmlspecialcharsbx($this->id) . "');\n";
  952. $result .= "blockEditorParams['iframe'] = BX('bx-block-editor-iframe-" . htmlspecialcharsbx($this->id) . "');\n";
  953. $result .= "blockEditorParams['resultNode'] = BX('" . htmlspecialcharsbx($this->ownResultId) . "');\n";
  954. $result .= "BX.BlockEditorManager.create(blockEditorParams);\n";
  955. $result = "\n" . '<script type="text/javascript">BX.ready(function(){' . "\n" . $result . '})</script>' . "\n";
  956. $result = $this->showEditor() . $result;
  957. $isBlockEditorManagerInited = true;
  958. return $result;
  959. }
  960. /**
  961. * Return received string, that php changed in special format for block editor.
  962. *
  963. * @param string $html
  964. * @param string $charset
  965. * @return string $html
  966. */
  967. public static function getHtmlForEditor($html, $charset = null)
  968. {
  969. $phpList = \PHPParser::ParseFile($html);
  970. foreach($phpList as $php)
  971. {
  972. $phpFormatted = htmlspecialcharsbx(str_replace(["\r", "\n"], "", $php[2]));
  973. $id = 'bx_block_php_' . mt_rand();
  974. $surrogate = '<span id="' . $id . '" ' . self::BLOCK_PHP_ATTR . '="' . ($phpFormatted) . '" class="bxhtmled-surrogate" title=""></span>';
  975. $html = str_replace($php[2], $surrogate, $html);
  976. }
  977. if(!$charset)
  978. {
  979. $charset = Application::getInstance()->getContext()->getCulture()->getCharset();
  980. $charset = 'UTF-8';
  981. }
  982. $charsetPlaceholder = '#CHARSET#';
  983. $html = static::replaceCharset($html, $charsetPlaceholder);
  984. $html = str_replace($charsetPlaceholder, HtmlFilter::encode($charset), $html);
  985. $html = Sanitizer::clean($html);
  986. return $html;
  987. }
  988. /**
  989. * Replace charset in HTML string.
  990. *
  991. * @param string $html
  992. * @param string $charset
  993. * @param bool $add
  994. * @return string $html
  995. */
  996. public static function replaceCharset($html, $charset = '#CHARSET#', $add = false)
  997. {
  998. $html = preg_replace(
  999. '/(<meta .*?charset=["\']+?)([^"\']+?)(["\']+?.*?>)/i',
  1000. '$1' . $charset . '$3',
  1001. $html
  1002. );
  1003. $html = preg_replace(
  1004. '/(<meta .*?content=["\']+?[^;]+?;[ ]*?charset=)([^"\']*?)(["\']+?.*?>)/i',
  1005. '$1' . $charset . '$3', $html, 1, $replaceCount
  1006. );
  1007. if($replaceCount === 0 && $add)
  1008. {
  1009. $html = preg_replace(
  1010. '/(<head.*?>)/i',
  1011. '$1<meta http-equiv="Content-Type" content="text/html; charset=' . $charset . '">',
  1012. $html
  1013. );
  1014. }
  1015. return $html;
  1016. }
  1017. /**
  1018. * Fill template(as a HTML) by slice content.
  1019. * Result is string.
  1020. *
  1021. * @param string $template
  1022. * @param string $string Content string.
  1023. * @param string $encoding
  1024. * @return string
  1025. * @deprecated
  1026. * @see \Bitrix\Fileman\Block\Content\Engine::fillHtmlTemplate
  1027. */
  1028. public static function fillTemplateBySliceContent($template, $string, $encoding = null)
  1029. {
  1030. return Content\Engine::fillHtmlTemplate($template, $string, $encoding);
  1031. }
  1032. /**
  1033. * Fill template(as a DOM Document) by content.
  1034. *
  1035. * @param Document $document Document.
  1036. * @param string $string Content string.
  1037. * @param string $encoding
  1038. * @return boolean
  1039. * @deprecated
  1040. * @see \Bitrix\Fileman\Block\Content\Engine::fillHtmlTemplate
  1041. */
  1042. public static function fillDocumentBySliceContent(Document $document, $string, $encoding = null)
  1043. {
  1044. return Content\Engine::create($document)->setEncoding($encoding)->setContent($string)->fill();
  1045. }
  1046. /**
  1047. * Check string for the presence of tag attributes that indicates supporting of block editor
  1048. *
  1049. * @param string $content
  1050. * @return boolean
  1051. */
  1052. public static function isContentSupported($content)
  1053. {
  1054. if(!$content || mb_strpos($content, Content\Engine::BLOCK_PLACE_ATTR) === false)
  1055. {
  1056. return false;
  1057. }
  1058. else
  1059. {
  1060. return true;
  1061. }
  1062. }
  1063. /**
  1064. * Check string for the presence of html
  1065. *
  1066. * @param string $content
  1067. * @return bool
  1068. */
  1069. public static function isHtmlDocument($content)
  1070. {
  1071. $result = true;
  1072. $content = mb_strtoupper($content);
  1073. if(mb_strpos($content, '<HTML') === false)
  1074. {
  1075. $result = false;
  1076. }
  1077. if(mb_strpos($content, '</HTML') === false)
  1078. {
  1079. $result = false;
  1080. }
  1081. if(mb_strpos($content, '<BODY') === false)
  1082. {
  1083. $result = false;
  1084. }
  1085. return $result;
  1086. }
  1087. /**
  1088. * Set components filter
  1089. *
  1090. * @param array $componentFilter
  1091. * @return void
  1092. */
  1093. public function setComponentFilter(array $componentFilter = null)
  1094. {
  1095. $this->componentFilter = $componentFilter;
  1096. }
  1097. protected function getComponentList()
  1098. {
  1099. return static::getComponentListPlain(static::getComponentTree());
  1100. }
  1101. protected function getComponentTree()
  1102. {
  1103. $util = new \CComponentUtil;
  1104. return $util->GetComponentsTree(false, false, $this->componentFilter);
  1105. }
  1106. protected function getComponentListPlain($list)
  1107. {
  1108. $result = array();
  1109. $path = null;
  1110. if(!is_array($list))
  1111. {
  1112. return $result;
  1113. }
  1114. if(isset($list['@']))
  1115. {
  1116. $path = $list['@'];
  1117. }
  1118. if(isset($list['*']))
  1119. {
  1120. $componentList = array();
  1121. foreach($list['*'] as $componentName => $componentData)
  1122. {
  1123. $componentData['TREE_PATH'] = array($path);
  1124. $componentList[$componentName] = $componentData;
  1125. }
  1126. return $componentList;
  1127. }
  1128. if(isset($list['#']))
  1129. {
  1130. foreach($list['#'] as $key => $item)
  1131. {
  1132. $resultItem = static::getComponentListPlain($item);
  1133. if(is_array($resultItem) && is_array($path))
  1134. {
  1135. foreach($resultItem as $componentName => $componentData)
  1136. {
  1137. if(!isset($componentData['TREE_PATH']))
  1138. {
  1139. $componentData['TREE_PATH'] = array();
  1140. }
  1141. $resultItem[$componentName]['TREE_PATH'] = array_merge(array($path), $componentData['TREE_PATH']);
  1142. }
  1143. }
  1144. $result = array_merge($result, $resultItem);
  1145. }
  1146. }
  1147. return $result;
  1148. }
  1149. }