PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/backend/modules/extensions/actions/add_theme_template.php

http://github.com/forkcms/forkcms
PHP | 312 lines | 155 code | 54 blank | 103 comment | 25 complexity | e0b3e0860f2c5c704564848b13ef41f0 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, MIT, AGPL-3.0, LGPL-2.1, BSD-3-Clause
  1. <?php
  2. /*
  3. * This file is part of Fork CMS.
  4. *
  5. * For the full copyright and license information, please view the license
  6. * file that was distributed with this source code.
  7. */
  8. /**
  9. * This is the add-action, it will display a form to create a new item
  10. *
  11. * @author Matthias Mullie <matthias@mullie.eu>
  12. * @author Davy Hellemans <davy.hellemans@netlash.com>
  13. * @author Tijs Verkoyen <tijs@sumocoders.be>
  14. */
  15. class BackendExtensionsAddThemeTemplate extends BackendBaseActionAdd
  16. {
  17. /**
  18. * All available themes.
  19. *
  20. * @var array
  21. */
  22. private $availableThemes = array();
  23. /**
  24. * The position's default extras.
  25. *
  26. * @var array
  27. */
  28. private $extras = array();
  29. /**
  30. * The position's names.
  31. *
  32. * @var array
  33. */
  34. private $names = array();
  35. /**
  36. * The theme we are adding a template for.
  37. *
  38. * @var string
  39. */
  40. private $selectedTheme;
  41. /**
  42. * Execute the action
  43. */
  44. public function execute()
  45. {
  46. parent::execute();
  47. // load additional js
  48. $this->header->addJS('theme_template.js');
  49. // load data
  50. $this->loadData();
  51. $this->loadForm();
  52. $this->validateForm();
  53. $this->parse();
  54. $this->display();
  55. }
  56. /**
  57. * Load necessary data.
  58. */
  59. private function loadData()
  60. {
  61. // get data
  62. $this->selectedTheme = $this->getParameter('theme', 'string');
  63. // build available themes
  64. foreach(BackendExtensionsModel::getThemes() as $theme) $this->availableThemes[$theme['value']] = $theme['label'];
  65. // determine selected theme, based upon submitted form or default theme
  66. $this->selectedTheme = SpoonFilter::getValue($this->selectedTheme, array_keys($this->availableThemes), BackendModel::getModuleSetting('core', 'theme', 'core'));
  67. }
  68. /**
  69. * Load the form
  70. */
  71. private function loadForm()
  72. {
  73. // create form
  74. $this->frm = new BackendForm('add');
  75. // init var
  76. $maximumPositions = 30;
  77. // create elements
  78. $this->frm->addDropdown('theme', $this->availableThemes, $this->selectedTheme);
  79. $this->frm->addText('label');
  80. $this->frm->addText('file');
  81. $this->frm->addTextarea('format');
  82. $this->frm->addCheckbox('active', true);
  83. $this->frm->addCheckbox('default');
  84. // init vars
  85. $positions = array();
  86. $blocks = array();
  87. $widgets = array();
  88. $extras = BackendExtensionsModel::getExtras();
  89. // loop extras to populate the default extras
  90. foreach($extras as $item)
  91. {
  92. if($item['type'] == 'block')
  93. {
  94. $blocks[$item['id']] = SpoonFilter::ucfirst(BL::lbl($item['label']));
  95. if(isset($item['data']['extra_label'])) $blocks[$item['id']] = SpoonFilter::ucfirst($item['data']['extra_label']);
  96. }
  97. elseif($item['type'] == 'widget')
  98. {
  99. $widgets[$item['id']] = SpoonFilter::ucfirst(BL::lbl(SpoonFilter::toCamelCase($item['module']))) . ': ' . SpoonFilter::ucfirst(BL::lbl($item['label']));
  100. if(isset($item['data']['extra_label'])) $widgets[$item['id']] = SpoonFilter::ucfirst(BL::lbl(SpoonFilter::toCamelCase($item['module']))) . ': ' . $item['data']['extra_label'];
  101. }
  102. }
  103. // sort
  104. asort($blocks, SORT_STRING);
  105. asort($widgets, SORT_STRING);
  106. // create array
  107. $defaultExtras = array('' => array(0 => SpoonFilter::ucfirst(BL::lbl('Editor'))),
  108. SpoonFilter::ucfirst(BL::lbl('Widgets')) => $widgets);
  109. // create default position field
  110. $position = array();
  111. $position['i'] = 0;
  112. $position['formElements']['txtPosition'] = $this->frm->addText('position_' . $position['i'], null, 255, 'inputText positionName', 'inputTextError positionName');
  113. $position['blocks'][]['formElements']['ddmType'] = $this->frm->addDropdown('type_' . $position['i'] . '_' . 0, $defaultExtras, null, false, 'positionBlock', 'positionBlockError');
  114. $positions[] = $position;
  115. // content has been submitted: re-create submitted content rather than the db-fetched content
  116. if(isset($_POST['position_0']))
  117. {
  118. // init vars
  119. $this->names = array();
  120. $this->extras = array();
  121. $i = 1;
  122. $errors = array();
  123. // loop submitted positions
  124. while(isset($_POST['position_' . $i]))
  125. {
  126. // init vars
  127. $j = 0;
  128. $extras = array();
  129. // gather position names
  130. $name = $_POST['position_' . $i];
  131. // loop submitted blocks
  132. while(isset($_POST['type_' . $i . '_' . $j]))
  133. {
  134. // gather blocks id
  135. $extras[] = (int) $_POST['type_' . $i . '_' . $j];
  136. // increment counter; go fetch next block
  137. $j++;
  138. }
  139. // increment counter; go fetch next position
  140. $i++;
  141. // position already exists -> error
  142. if(in_array($name, $this->names)) $errors[] = sprintf(BL::getError('DuplicatePositionName'), $name);
  143. // position name == fallback -> error
  144. if($name == 'fallback') $errors[] = sprintf(BL::getError('ReservedPositionName'), $name);
  145. // not alphanumeric -> error
  146. if(!SpoonFilter::isValidAgainstRegexp('/^[a-z0-9]+$/i', $name)) $errors[] = sprintf(BL::getError('NoAlphaNumPositionName'), $name);
  147. // save positions
  148. $this->names[] = $name;
  149. $this->extras[$name] = $extras;
  150. }
  151. // add errors
  152. if($errors) $this->frm->addError(implode('<br />', array_unique($errors)));
  153. }
  154. // build blocks array
  155. foreach($this->names as $i => $name)
  156. {
  157. // create default position field
  158. $position = array();
  159. $position['i'] = $i + 1;
  160. $position['formElements']['txtPosition'] = $this->frm->addText('position_' . $position['i'], $name, 255, 'inputText positionName', 'inputTextError positionName');
  161. foreach($this->extras[$name] as $extra) $position['blocks'][]['formElements']['ddmType'] = $this->frm->addDropdown('type_' . $position['i'] . '_' . 0, $defaultExtras, $extra, false, 'positionBlock', 'positionBlockError');
  162. $positions[] = $position;
  163. }
  164. // assign
  165. $this->tpl->assign('positions', $positions);
  166. }
  167. /**
  168. * Parse the form
  169. */
  170. protected function parse()
  171. {
  172. parent::parse();
  173. // assign form errors
  174. $this->tpl->assign('formErrors', (string) $this->frm->getErrors());
  175. }
  176. /**
  177. * Validate the form
  178. */
  179. private function validateForm()
  180. {
  181. // is the form submitted?
  182. if($this->frm->isSubmitted())
  183. {
  184. // cleanup the submitted fields, ignore fields that were added by hackers
  185. $this->frm->cleanupFields();
  186. // required fields
  187. $this->frm->getField('file')->isFilled(BL::err('FieldIsRequired'));
  188. $this->frm->getField('label')->isFilled(BL::err('FieldIsRequired'));
  189. $this->frm->getField('format')->isFilled(BL::err('FieldIsRequired'));
  190. // validate syntax
  191. $syntax = trim(str_replace(array("\n", "\r", ' '), '', $this->frm->getField('format')->getValue()));
  192. // init var
  193. $table = BackendExtensionsModel::templateSyntaxToArray($syntax);
  194. // validate the syntax
  195. if($table === false) $this->frm->getField('format')->addError(BL::err('InvalidTemplateSyntax'));
  196. else
  197. {
  198. $html = BackendExtensionsModel::buildTemplateHTML($syntax);
  199. $cellCount = 0;
  200. $first = true;
  201. $errors = array();
  202. // loop rows
  203. foreach($table as $row)
  204. {
  205. // first row defines the cellcount
  206. if($first) $cellCount = count($row);
  207. // not same number of cells
  208. if(count($row) != $cellCount)
  209. {
  210. // add error
  211. $errors[] = BL::err('InvalidTemplateSyntax');
  212. // stop
  213. break;
  214. }
  215. // doublecheck position names
  216. foreach($row as $cell)
  217. {
  218. // ignore unavailable space
  219. if($cell != '/')
  220. {
  221. // not alphanumeric -> error
  222. if(!in_array($cell, $this->names)) $errors[] = sprintf(BL::getError('NonExistingPositionName'), $cell);
  223. // can't build proper html -> error
  224. elseif(substr_count($html, '"#position-' . $cell . '"') != 1) $errors[] = BL::err('InvalidTemplateSyntax');
  225. }
  226. }
  227. // reset
  228. $first = false;
  229. }
  230. // add errors
  231. if($errors) $this->frm->getField('format')->addError(implode('<br />', array_unique($errors)));
  232. }
  233. // no errors?
  234. if($this->frm->isCorrect())
  235. {
  236. // build array
  237. $item['theme'] = $this->frm->getField('theme')->getValue();
  238. $item['label'] = $this->frm->getField('label')->getValue();
  239. $item['path'] = 'core/layout/templates/' . $this->frm->getField('file')->getValue();
  240. $item['active'] = $this->frm->getField('active')->getChecked() ? 'Y' : 'N';
  241. $item['data']['format'] = trim(str_replace(array("\n", "\r", ' '), '', $this->frm->getField('format')->getValue()));
  242. $item['data']['names'] = $this->names;
  243. $item['data']['default_extras'] = $this->extras;
  244. $item['data']['default_extras_' . BackendLanguage::getWorkingLanguage()] = $this->extras;
  245. // serialize the data
  246. $item['data'] = serialize($item['data']);
  247. // insert the item
  248. $item['id'] = BackendExtensionsModel::insertTemplate($item);
  249. // trigger event
  250. BackendModel::triggerEvent($this->getModule(), 'after_add_template', array('item' => $item));
  251. // set default template
  252. if($this->frm->getField('default')->getChecked() && $item['theme'] == BackendModel::getModuleSetting('core', 'theme', 'core')) BackendModel::setModuleSetting($this->getModule(), 'default_template', $item['id']);
  253. // everything is saved, so redirect to the overview
  254. $this->redirect(BackendModel::createURLForAction('theme_templates') . '&theme=' . $item['theme'] . '&report=added-template&var=' . urlencode($item['label']) . '&highlight=row-' . $item['id']);
  255. }
  256. }
  257. }
  258. }