PageRenderTime 24ms CodeModel.GetById 44ms RepoModel.GetById 13ms app.codeStats 0ms

/lib/Varien/Data/Form/Element/Editor.php

https://bitbucket.org/sevenly/magento-ce
PHP | 399 lines | 262 code | 32 blank | 105 comment | 29 complexity | 40e2585d72356d2b5e7d55fc2373c6ea MD5 | raw file
  1. <?php
  2. /**
  3. * Magento
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@magentocommerce.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade Magento to newer
  18. * versions in the future. If you wish to customize Magento for your
  19. * needs please refer to http://www.magentocommerce.com for more information.
  20. *
  21. * @category Varien
  22. * @package Varien_Data
  23. * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. */
  26. /**
  27. * Form editor element
  28. *
  29. * @category Varien
  30. * @package Varien_Data
  31. * @author Magento Core Team <core@magentocommerce.com>
  32. */
  33. class Varien_Data_Form_Element_Editor extends Varien_Data_Form_Element_Textarea
  34. {
  35. public function __construct($attributes=array())
  36. {
  37. parent::__construct($attributes);
  38. if($this->isEnabled()) {
  39. $this->setType('wysiwyg');
  40. $this->setExtType('wysiwyg');
  41. } else {
  42. $this->setType('textarea');
  43. $this->setExtType('textarea');
  44. }
  45. }
  46. public function getElementHtml()
  47. {
  48. $js = '
  49. <script type="text/javascript">
  50. //<![CDATA[
  51. openEditorPopup = function(url, name, specs, parent) {
  52. if ((typeof popups == "undefined") || popups[name] == undefined || popups[name].closed) {
  53. if (typeof popups == "undefined") {
  54. popups = new Array();
  55. }
  56. var opener = (parent != undefined ? parent : window);
  57. popups[name] = opener.open(url, name, specs);
  58. } else {
  59. popups[name].focus();
  60. }
  61. return popups[name];
  62. }
  63. closeEditorPopup = function(name) {
  64. if ((typeof popups != "undefined") && popups[name] != undefined && !popups[name].closed) {
  65. popups[name].close();
  66. }
  67. }
  68. //]]>
  69. </script>';
  70. if($this->isEnabled())
  71. {
  72. // add Firebug notice translations
  73. $warn = 'Firebug is known to make the WYSIWYG editor slow unless it is turned off or configured properly.';
  74. $this->getConfig()->addData(array(
  75. 'firebug_warning_title' => $this->translate('Warning'),
  76. 'firebug_warning_text' => $this->translate($warn),
  77. 'firebug_warning_anchor' => $this->translate('Hide'),
  78. ));
  79. $translatedString = array(
  80. 'Insert Image...' => $this->translate('Insert Image...'),
  81. 'Insert Media...' => $this->translate('Insert Media...'),
  82. 'Insert File...' => $this->translate('Insert File...')
  83. );
  84. $jsSetupObject = 'wysiwyg' . $this->getHtmlId();
  85. $forceLoad = '';
  86. if (!$this->isHidden()) {
  87. if ($this->getForceLoad()) {
  88. $forceLoad = $jsSetupObject . '.setup("exact");';
  89. } else {
  90. $forceLoad = 'Event.observe(window, "load", '
  91. . $jsSetupObject . '.setup.bind(' . $jsSetupObject . ', "exact"));';
  92. }
  93. }
  94. $html = $this->_getButtonsHtml()
  95. . '<textarea name="' . $this->getName() . '" title="' . $this->getTitle()
  96. . '" id="' . $this->getHtmlId() . '"'
  97. . ' class="textarea ' . $this->getClass() . '" '
  98. . $this->serialize($this->getHtmlAttributes()) . ' >' . $this->getEscapedValue() . '</textarea>'
  99. . $js . '
  100. <script type="text/javascript">
  101. //<![CDATA[
  102. if ("undefined" != typeof(Translator)) {
  103. Translator.add(' . Zend_Json::encode($translatedString) . ');
  104. }'
  105. . $jsSetupObject . ' = new tinyMceWysiwygSetup("' . $this->getHtmlId() . '", '
  106. . Zend_Json::encode($this->getConfig()).');'
  107. . $forceLoad.'
  108. editorFormValidationHandler = ' . $jsSetupObject . '.onFormValidation.bind(' . $jsSetupObject . ');
  109. Event.observe("toggle' . $this->getHtmlId() . '", "click", '
  110. . $jsSetupObject . '.toggle.bind('.$jsSetupObject.'));
  111. varienGlobalEvents.attachEventHandler("formSubmit", editorFormValidationHandler);
  112. varienGlobalEvents.attachEventHandler("tinymceBeforeSetContent", '
  113. . $jsSetupObject . '.beforeSetContent.bind(' . $jsSetupObject . '));
  114. varienGlobalEvents.attachEventHandler("tinymceSaveContent", '
  115. . $jsSetupObject . '.saveContent.bind(' . $jsSetupObject . '));
  116. varienGlobalEvents.clearEventHandlers("open_browser_callback");
  117. varienGlobalEvents.attachEventHandler("open_browser_callback", '
  118. . $jsSetupObject . '.openFileBrowser.bind(' . $jsSetupObject . '));
  119. //]]>
  120. </script>';
  121. $html = $this->_wrapIntoContainer($html);
  122. $html .= $this->getAfterElementHtml();
  123. return $html;
  124. } else {
  125. // Display only buttons to additional features
  126. if ($this->getConfig('widget_window_url')) {
  127. $html = $this->_getButtonsHtml() . $js . parent::getElementHtml();
  128. $html = $this->_wrapIntoContainer($html);
  129. return $html;
  130. }
  131. return parent::getElementHtml();
  132. }
  133. }
  134. public function getTheme()
  135. {
  136. if(!$this->hasData('theme')) {
  137. return 'simple';
  138. }
  139. return $this->_getData('theme');
  140. }
  141. /**
  142. * Return Editor top Buttons HTML
  143. *
  144. * @return string
  145. */
  146. protected function _getButtonsHtml()
  147. {
  148. $buttonsHtml = '<div id="buttons'.$this->getHtmlId().'" class="buttons-set">';
  149. if ($this->isEnabled()) {
  150. $buttonsHtml .= $this->_getToggleButtonHtml() . $this->_getPluginButtonsHtml($this->isHidden());
  151. } else {
  152. $buttonsHtml .= $this->_getPluginButtonsHtml(true);
  153. }
  154. $buttonsHtml .= '</div>';
  155. return $buttonsHtml;
  156. }
  157. /**
  158. * Return HTML button to toggling WYSIWYG
  159. *
  160. * @return string
  161. */
  162. protected function _getToggleButtonHtml($visible = true)
  163. {
  164. $html = $this->_getButtonHtml(array(
  165. 'title' => $this->translate('Show / Hide Editor'),
  166. 'class' => 'show-hide',
  167. 'style' => $visible ? '' : 'display:none',
  168. 'id' => 'toggle'.$this->getHtmlId(),
  169. ));
  170. return $html;
  171. }
  172. /**
  173. * Prepare Html buttons for additional WYSIWYG features
  174. *
  175. * @param bool $visible Display button or not
  176. * @return void
  177. */
  178. protected function _getPluginButtonsHtml($visible = true)
  179. {
  180. $buttonsHtml = '';
  181. // Button to widget insertion window
  182. if ($this->getConfig('add_widgets')) {
  183. $buttonsHtml .= $this->_getButtonHtml(array(
  184. 'title' => $this->translate('Insert Widget...'),
  185. 'onclick' => "widgetTools.openDialog('" . $this->getConfig('widget_window_url') . "widget_target_id/"
  186. . $this->getHtmlId() . "')",
  187. 'class' => 'add-widget plugin',
  188. 'style' => $visible ? '' : 'display:none',
  189. ));
  190. }
  191. // Button to media images insertion window
  192. if ($this->getConfig('add_images')) {
  193. $buttonsHtml .= $this->_getButtonHtml(array(
  194. 'title' => $this->translate('Insert Image...'),
  195. 'onclick' => "MediabrowserUtility.openDialog('" .
  196. $this->getConfig('files_browser_window_url') .
  197. "target_element_id/" . $this->getHtmlId() . "/" .
  198. ((null !== $this->getConfig('store_id'))
  199. ? ('store/' . $this->getConfig('store_id') . '/')
  200. : '')
  201. . "')",
  202. 'class' => 'add-image plugin',
  203. 'style' => $visible ? '' : 'display:none',
  204. ));
  205. }
  206. foreach ($this->getConfig('plugins') as $plugin) {
  207. if (isset($plugin['options']) && $this->_checkPluginButtonOptions($plugin['options'])) {
  208. $buttonOptions = $this->_prepareButtonOptions($plugin['options']);
  209. if (!$visible) {
  210. $configStyle = '';
  211. if (isset($buttonOptions['style'])) {
  212. $configStyle = $buttonOptions['style'];
  213. }
  214. $buttonOptions = array_merge($buttonOptions, array('style' => 'display:none;' . $configStyle));
  215. }
  216. $buttonsHtml .= $this->_getButtonHtml($buttonOptions);
  217. }
  218. }
  219. return $buttonsHtml;
  220. }
  221. /**
  222. * Prepare button options array to create button html
  223. *
  224. * @param array $options
  225. * @return array
  226. */
  227. protected function _prepareButtonOptions($options)
  228. {
  229. $buttonOptions = array();
  230. $buttonOptions['class'] = 'plugin';
  231. foreach ($options as $name => $value) {
  232. $buttonOptions[$name] = $value;
  233. }
  234. $buttonOptions = $this->_prepareOptions($buttonOptions);
  235. return $buttonOptions;
  236. }
  237. /**
  238. * Check if plugin button options have required values
  239. *
  240. * @param array $pluginOptions
  241. * @return boolean
  242. */
  243. protected function _checkPluginButtonOptions($pluginOptions)
  244. {
  245. if (!isset($pluginOptions['title'])) {
  246. return false;
  247. }
  248. return true;
  249. }
  250. /**
  251. * Convert options by replacing template constructions ( like {{var_name}} )
  252. * with data from this element object
  253. *
  254. * @param array $options
  255. * @return array
  256. */
  257. protected function _prepareOptions($options)
  258. {
  259. $preparedOptions = array();
  260. foreach ($options as $name => $value) {
  261. if (is_array($value) && isset($value['search']) && isset($value['subject'])) {
  262. $subject = $value['subject'];
  263. foreach ($value['search'] as $part) {
  264. $subject = str_replace('{{'.$part.'}}', $this->getDataUsingMethod($part), $subject);
  265. }
  266. $preparedOptions[$name] = $subject;
  267. } else {
  268. $preparedOptions[$name] = $value;
  269. }
  270. }
  271. return $preparedOptions;
  272. }
  273. /**
  274. * Return custom button HTML
  275. *
  276. * @param array $data Button params
  277. * @return string
  278. */
  279. protected function _getButtonHtml($data)
  280. {
  281. $html = '<button type="button"';
  282. $html.= ' class="scalable '.(isset($data['class']) ? $data['class'] : '').'"';
  283. $html.= isset($data['onclick']) ? ' onclick="'.$data['onclick'].'"' : '';
  284. $html.= isset($data['style']) ? ' style="'.$data['style'].'"' : '';
  285. $html.= isset($data['id']) ? ' id="'.$data['id'].'"' : '';
  286. $html.= '>';
  287. $html.= isset($data['title']) ? '<span><span><span>'.$data['title'].'</span></span></span>' : '';
  288. $html.= '</button>';
  289. return $html;
  290. }
  291. /**
  292. * Wraps Editor HTML into div if 'use_container' config option is set to true
  293. * If 'no_display' config option is set to true, the div will be invisible
  294. *
  295. * @param string $html HTML code to wrap
  296. * @return string
  297. */
  298. protected function _wrapIntoContainer($html)
  299. {
  300. if (!$this->getConfig('use_container')) {
  301. return $html;
  302. }
  303. $html = '<div id="editor'.$this->getHtmlId().'"'
  304. . ($this->getConfig('no_display') ? ' style="display:none;"' : '')
  305. . ($this->getConfig('container_class') ? ' class="' . $this->getConfig('container_class') . '"' : '')
  306. . '>'
  307. . $html
  308. . '</div>';
  309. return $html;
  310. }
  311. /**
  312. * Editor config retriever
  313. *
  314. * @param string $key Config var key
  315. * @return mixed
  316. */
  317. public function getConfig($key = null)
  318. {
  319. if ( !($this->_getData('config') instanceof Varien_Object) ) {
  320. $config = new Varien_Object();
  321. $this->setConfig($config);
  322. }
  323. if ($key !== null) {
  324. return $this->_getData('config')->getData($key);
  325. }
  326. return $this->_getData('config');
  327. }
  328. /**
  329. * Translate string using defined helper
  330. *
  331. * @param string $string String to be translated
  332. * @return string
  333. */
  334. public function translate($string)
  335. {
  336. $translator = $this->getConfig('translator');
  337. if (is_object($translator) && is_callable(array($translator, '__'))) {
  338. $result = $translator->__($string);
  339. if (is_string($result)) {
  340. return $result;
  341. }
  342. }
  343. return $string;
  344. }
  345. /**
  346. * Check whether Wysiwyg is enabled or not
  347. *
  348. * @return bool
  349. */
  350. public function isEnabled()
  351. {
  352. if ($this->hasData('wysiwyg')) {
  353. return $this->getWysiwyg();
  354. }
  355. return $this->getConfig('enabled');
  356. }
  357. /**
  358. * Check whether Wysiwyg is loaded on demand or not
  359. *
  360. * @return bool
  361. */
  362. public function isHidden()
  363. {
  364. return $this->getConfig('hidden');
  365. }
  366. }