PageRenderTime 26ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/app/bundles/FormBundle/Model/FormModel.php

https://gitlab.com/jankube/mautic
PHP | 465 lines | 299 code | 55 blank | 111 comment | 38 complexity | 864b481bd83b6635fe52037a7e80126a MD5 | raw file
  1. <?php
  2. /**
  3. * @package Mautic
  4. * @copyright 2014 Mautic Contributors. All rights reserved.
  5. * @author Mautic
  6. * @link http://mautic.org
  7. * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
  8. */
  9. namespace Mautic\FormBundle\Model;
  10. use Mautic\CoreBundle\Helper\InputHelper;
  11. use Mautic\CoreBundle\Model\FormModel as CommonFormModel;
  12. use Mautic\FormBundle\Entity\Action;
  13. use Mautic\FormBundle\Entity\Field;
  14. use Mautic\FormBundle\Entity\Form;
  15. use Mautic\FormBundle\Event\FormBuilderEvent;
  16. use Mautic\FormBundle\Event\FormEvent;
  17. use Mautic\FormBundle\FormEvents;
  18. use Symfony\Component\EventDispatcher\Event;
  19. use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
  20. /**
  21. * Class FormModel
  22. */
  23. class FormModel extends CommonFormModel
  24. {
  25. /**
  26. * {@inheritdoc}
  27. *
  28. * @return \Mautic\FormBundle\Entity\FormRepository
  29. */
  30. public function getRepository()
  31. {
  32. return $this->em->getRepository('MauticFormBundle:Form');
  33. }
  34. /**
  35. * {@inheritdoc}
  36. */
  37. public function getPermissionBase()
  38. {
  39. return 'form:forms';
  40. }
  41. /**
  42. * {@inheritdoc}
  43. */
  44. public function getNameGetter()
  45. {
  46. return "getName";
  47. }
  48. /**
  49. * {@inheritdoc}
  50. */
  51. public function createForm($entity, $formFactory, $action = null, $options = array())
  52. {
  53. if (!$entity instanceof Form) {
  54. throw new MethodNotAllowedHttpException(array('Form'));
  55. }
  56. $params = (!empty($action)) ? array('action' => $action) : array();
  57. return $formFactory->create('mauticform', $entity, $params);
  58. }
  59. /**
  60. * {@inheritdoc}
  61. */
  62. public function getEntity($id = null)
  63. {
  64. if ($id === null) {
  65. return new Form();
  66. }
  67. return parent::getEntity($id);
  68. }
  69. /**
  70. * {@inheritdoc}
  71. *
  72. * @return bool|FormEvent|void
  73. * @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
  74. */
  75. protected function dispatchEvent($action, &$entity, $isNew = false, Event $event = null)
  76. {
  77. if (!$entity instanceof Form) {
  78. throw new MethodNotAllowedHttpException(array('Form'));
  79. }
  80. switch ($action) {
  81. case "pre_save":
  82. $name = FormEvents::FORM_PRE_SAVE;
  83. break;
  84. case "post_save":
  85. $name = FormEvents::FORM_POST_SAVE;
  86. break;
  87. case "pre_delete":
  88. $name = FormEvents::FORM_PRE_DELETE;
  89. break;
  90. case "post_delete":
  91. $name = FormEvents::FORM_POST_DELETE;
  92. break;
  93. default:
  94. return null;
  95. }
  96. if ($this->dispatcher->hasListeners($name)) {
  97. if (empty($event)) {
  98. $event = new FormEvent($entity, $isNew);
  99. $event->setEntityManager($this->em);
  100. }
  101. $this->dispatcher->dispatch($name, $event);
  102. return $event;
  103. } else {
  104. return null;
  105. }
  106. }
  107. /**
  108. * @param Form $entity
  109. * @param $sessionFields
  110. */
  111. public function setFields(Form $entity, $sessionFields)
  112. {
  113. $order = 1;
  114. $existingFields = $entity->getFields();
  115. foreach ($sessionFields as $key => $properties) {
  116. $isNew = (!empty($properties['id']) && isset($existingFields[$properties['id']])) ? false : true;
  117. $field = !$isNew ? $existingFields[$properties['id']] : new Field();
  118. if (!$isNew) {
  119. if (empty($properties['alias'])) {
  120. $properties['alias'] = $field->getAlias();
  121. }
  122. if (empty($properties['label'])) {
  123. $properties['label'] = $field->getLabel();
  124. }
  125. }
  126. foreach ($properties as $f => $v) {
  127. if (in_array($f, array('id', 'order')))
  128. continue;
  129. $func = "set" . ucfirst($f);
  130. if (method_exists($field, $func)) {
  131. $field->$func($v);
  132. }
  133. }
  134. $field->setForm($entity);
  135. $field->setSessionId($key);
  136. $field->setOrder($order);
  137. $order++;
  138. $entity->addField($properties['id'], $field);
  139. }
  140. }
  141. /**
  142. * @param Form $entity
  143. * @param $sessionFields
  144. */
  145. public function deleteFields(Form $entity, $sessionFields)
  146. {
  147. if (empty($sessionFields)) {
  148. return;
  149. }
  150. $existingFields = $entity->getFields();
  151. foreach ($sessionFields as $fieldId) {
  152. if (isset($existingFields[$fieldId])) {
  153. $entity->removeField($fieldId, $existingFields[$fieldId]);
  154. }
  155. }
  156. }
  157. /**
  158. * @param Form $entity
  159. * @param $sessionActions
  160. */
  161. public function setActions(Form $entity, $sessionActions)
  162. {
  163. $order = 1;
  164. $existingActions = $entity->getActions();
  165. $savedFields = $entity->getFields();
  166. //match sessionId with field Id to update mapped fields
  167. $fieldIds = array();
  168. foreach ($savedFields as $id => $field) {
  169. $fieldIds[$field->getSessionId()] = $field->getId();
  170. }
  171. foreach ($sessionActions as $properties) {
  172. $isNew = (!empty($properties['id']) && isset($existingActions[$properties['id']])) ? false : true;
  173. $action = !$isNew ? $existingActions[$properties['id']] : new Action();
  174. foreach ($properties as $f => $v) {
  175. if (in_array($f, array('id', 'order')))
  176. continue;
  177. $func = "set" . ucfirst($f);
  178. if ($f == 'properties') {
  179. if (isset($v['mappedFields'])) {
  180. foreach ($v['mappedFields'] as $pk => $pv) {
  181. if (strpos($pv, 'new') !== false) {
  182. $v['mappedFields'][$pk] = $fieldIds[$pv];
  183. }
  184. }
  185. }
  186. }
  187. if (method_exists($action, $func)) {
  188. $action->$func($v);
  189. }
  190. }
  191. $action->setForm($entity);
  192. $action->setOrder($order);
  193. $order++;
  194. $entity->addAction($properties['id'], $action);
  195. }
  196. }
  197. /**
  198. * {@inheritdoc}
  199. */
  200. public function saveEntity($entity, $unlock = true)
  201. {
  202. $isNew = ($entity->getId()) ? false : true;
  203. if ($isNew) {
  204. $alias = substr(strtolower(InputHelper::alphanum($entity->getName())), 0, 10);
  205. $entity->setAlias($alias);
  206. }
  207. //save the form so that the ID is available for the form html
  208. parent::saveEntity($entity, $unlock);
  209. //now build the form table
  210. if ($entity->getId()) {
  211. $this->createTableSchema($entity, $isNew);
  212. }
  213. $this->generateHtml($entity);
  214. }
  215. /**
  216. * Obtains the cached HTML of a form and generates it if missing
  217. *
  218. * @param Form $form
  219. *
  220. * @return string
  221. */
  222. public function getContent(Form $form)
  223. {
  224. $cachedHtml = $form->getCachedHtml();
  225. if (empty($cachedHtml)) {
  226. $cachedHtml = $this->generateHtml($form);
  227. }
  228. return $cachedHtml;
  229. }
  230. /**
  231. * Generate the form's html
  232. *
  233. * @param Form $entity
  234. * @param bool $persist
  235. *
  236. * @return string
  237. */
  238. public function generateHtml(Form $entity, $persist = true)
  239. {
  240. //generate cached HTML
  241. $templating = $this->factory->getTemplating();
  242. $theme = $entity->getTemplate();
  243. if (!empty($theme)) {
  244. $theme .= '|';
  245. }
  246. $html = $templating->render(
  247. $theme.'MauticFormBundle:Builder:form.html.php',
  248. array(
  249. 'form' => $entity,
  250. 'theme' => $theme,
  251. )
  252. );
  253. $entity->setCachedHtml($html);
  254. if ($persist) {
  255. //bypass model function as events aren't needed for this
  256. $this->getRepository()->saveEntity($entity);
  257. }
  258. return $html;
  259. }
  260. /**
  261. * Creates the table structure for form results
  262. *
  263. * @param Form $entity
  264. * @param bool $isNew
  265. * @param bool $dropExisting
  266. */
  267. public function createTableSchema(Form $entity, $isNew = false, $dropExisting = false)
  268. {
  269. //create the field as its own column in the leads table
  270. $schemaHelper = $this->factory->getSchemaHelper('table');
  271. $name = "form_results_" . $entity->getId() . "_" . $entity->getAlias();
  272. $columns = $this->generateFieldColumns($entity);
  273. if ($isNew || (!$isNew && !$schemaHelper->checkTableExists($name))) {
  274. $schemaHelper->addTable(array(
  275. 'name' => $name,
  276. 'columns' => $columns,
  277. 'options' => array(
  278. 'primaryKey' => array('submission_id'),
  279. 'uniqueIndex' => array('submission_id', 'form_id')
  280. )
  281. ), true, $dropExisting);
  282. $schemaHelper->executeChanges();
  283. } else {
  284. //check to make sure columns exist
  285. $schemaHelper = $this->factory->getSchemaHelper('column', $name);
  286. foreach ($columns as $c) {
  287. if (!$schemaHelper->checkColumnExists($c['name'])) {
  288. $schemaHelper->addColumn($c, false);
  289. }
  290. }
  291. $schemaHelper->executeChanges();
  292. }
  293. }
  294. /**
  295. * {@inheritdoc}
  296. */
  297. public function deleteEntity($entity)
  298. {
  299. parent::deleteEntity($entity);
  300. if (!$entity->getId()) {
  301. //delete the associated results table
  302. $schemaHelper = $this->factory->getSchemaHelper('table');
  303. $schemaHelper->deleteTable("form_results_" . $entity->deletedId . "_" . $entity->getAlias());
  304. $schemaHelper->executeChanges();
  305. }
  306. }
  307. /**
  308. * {@inheritdoc}
  309. */
  310. public function deleteEntities($ids)
  311. {
  312. $entities = parent::deleteEntities($ids);
  313. $schemaHelper = $this->factory->getSchemaHelper('table');
  314. foreach ($entities as $id => $entity) {
  315. //delete the associated results table
  316. $schemaHelper->deleteTable("form_results_" . $id . "_" . $entity->getAlias());
  317. }
  318. $schemaHelper->executeChanges();
  319. return $entities;
  320. }
  321. /**
  322. * Generate an array of columns from fields
  323. *
  324. * @param Form $form
  325. *
  326. * @return array
  327. */
  328. public function generateFieldColumns(Form $form)
  329. {
  330. $fields = $form->getFields();
  331. $columns = array(
  332. array(
  333. 'name' => 'submission_id',
  334. 'type' => 'integer'
  335. ),
  336. array(
  337. 'name' => 'form_id',
  338. 'type' => 'integer'
  339. )
  340. );
  341. $ignoreTypes = array('button', 'freetext');
  342. foreach ($fields as $f) {
  343. if (!in_array($f->getType(), $ignoreTypes) && $f->getSaveResult() !== false) {
  344. $columns[] = array(
  345. 'name' => $f->getAlias(),
  346. 'type' => 'text',
  347. 'options' => array(
  348. 'notnull' => false
  349. )
  350. );
  351. }
  352. }
  353. return $columns;
  354. }
  355. /**
  356. * Gets array of custom fields and submit actions from bundles subscribed FormEvents::FORM_ON_BUILD
  357. * @return mixed
  358. */
  359. public function getCustomComponents()
  360. {
  361. static $customComponents;
  362. if (empty($customComponents)) {
  363. //build them
  364. $event = new FormBuilderEvent($this->translator);
  365. $this->dispatcher->dispatch(FormEvents::FORM_ON_BUILD, $event);
  366. $customComponents['fields'] = $event->getFormFields();
  367. $customComponents['actions'] = $event->getSubmitActions();
  368. $customComponents['choices'] = $event->getSubmitActionGroups();
  369. }
  370. return $customComponents;
  371. }
  372. /**
  373. * Get the document write javascript for the form
  374. *
  375. * @param Form $form
  376. * @return string
  377. */
  378. public function getAutomaticJavascript(Form $form)
  379. {
  380. $html = $this->getContent($form);
  381. //replace line breaks with literal symbol and escape quotations
  382. $search = array("\n", '"');
  383. $replace = array('\n', '\"');
  384. $html = str_replace($search, $replace, $html);
  385. return "document.write(\"".$html."\");";
  386. }
  387. /**
  388. * Writes in form values from get parameters
  389. *
  390. * @param $form
  391. * @param $formHtml
  392. */
  393. public function populateValuesWithGetParameters($form, &$formHtml)
  394. {
  395. $request = $this->factory->getRequest();
  396. $formName = strtolower(\Mautic\CoreBundle\Helper\InputHelper::alphanum($form->getName()));
  397. $fields = $form->getFields();
  398. foreach ($fields as $f) {
  399. $alias = $f->getAlias();
  400. if ($request->query->has($alias)) {
  401. preg_match('/<input id="mauticform_input_' . $formName . '_' . $alias . '"(.*?)value="(.*?)"(.*?)\/>/i', $formHtml, $match);
  402. if (!empty($match)) {
  403. //replace value with GET
  404. $replace = '<input id="mauticform_input_' . $formName . '_' . $alias . '"' . $match[1] . 'value="' . urldecode($request->query->get($alias)) . '"' . $match[3] . '/>';
  405. $formHtml = str_replace($match[0], $replace, $formHtml);
  406. }
  407. }
  408. }
  409. }
  410. }