1 <?php
2 3 4 5 6 7 8
9
10 defined('JPATH_PLATFORM') or die;
11
12 13 14 15 16 17
18 class JControllerForm extends JControllerLegacy
19 {
20 21 22 23 24 25
26 protected $context;
27
28 29 30 31 32 33
34 protected $option;
35
36 37 38 39 40 41
42 protected $view_item;
43
44 45 46 47 48 49
50 protected $view_list;
51
52 53 54 55 56 57
58 protected $text_prefix;
59
60 61 62 63 64 65 66 67 68
69 public function __construct($config = array())
70 {
71 parent::__construct($config);
72
73
74 if (empty($this->option))
75 {
76 $this->option = 'com_' . strtolower($this->getName());
77 }
78
79
80 if (empty($this->text_prefix))
81 {
82 $this->text_prefix = strtoupper($this->option);
83 }
84
85
86 if (empty($this->context))
87 {
88 $r = null;
89
90 if (!preg_match('/(.*)Controller(.*)/i', get_class($this), $r))
91 {
92 throw new Exception(JText::_('JLIB_APPLICATION_ERROR_CONTROLLER_GET_NAME'), 500);
93 }
94
95 $this->context = strtolower($r[2]);
96 }
97
98
99 if (empty($this->view_item))
100 {
101 $this->view_item = $this->context;
102 }
103
104
105 if (empty($this->view_list))
106 {
107
108
109
110
111
112 $plural = array(
113 array('/(x|ch|ss|sh)$/i', "$1es"),
114 array('/([^aeiouy]|qu)y$/i', "$1ies"),
115 array('/([^aeiouy]|qu)ies$/i', "$1y"),
116 array('/(bu)s$/i', "$1ses"),
117 array('/s$/i', 's'),
118 array('/$/', 's'),
119 );
120
121
122 foreach ($plural as $pattern)
123 {
124 if (preg_match($pattern[0], $this->view_item))
125 {
126 $this->view_list = preg_replace($pattern[0], $pattern[1], $this->view_item);
127 break;
128 }
129 }
130 }
131
132
133 $this->registerTask('apply', 'save');
134 $this->registerTask('save2new', 'save');
135 $this->registerTask('save2copy', 'save');
136 }
137
138 139 140 141 142 143 144
145 public function add()
146 {
147 $context = "$this->option.edit.$this->context";
148
149
150 if (!$this->allowAdd())
151 {
152
153 $this->setError(JText::_('JLIB_APPLICATION_ERROR_CREATE_RECORD_NOT_PERMITTED'));
154 $this->setMessage($this->getError(), 'error');
155
156 $this->setRedirect(
157 JRoute::_(
158 'index.php?option=' . $this->option . '&view=' . $this->view_list
159 . $this->getRedirectToListAppend(), false
160 )
161 );
162
163 return false;
164 }
165
166
167 JFactory::getApplication()->setUserState($context . '.data', null);
168
169
170 $this->setRedirect(
171 JRoute::_(
172 'index.php?option=' . $this->option . '&view=' . $this->view_item
173 . $this->getRedirectToItemAppend(), false
174 )
175 );
176
177 return true;
178 }
179
180 181 182 183 184 185 186 187 188 189 190
191 protected function allowAdd($data = array())
192 {
193 $user = JFactory::getUser();
194
195 return $user->authorise('core.create', $this->option) || count($user->getAuthorisedCategories($this->option, 'core.create'));
196 }
197
198 199 200 201 202 203 204 205 206 207 208 209
210 protected function allowEdit($data = array(), $key = 'id')
211 {
212 return JFactory::getUser()->authorise('core.edit', $this->option);
213 }
214
215 216 217 218 219 220 221 222 223 224 225 226
227 protected function allowSave($data, $key = 'id')
228 {
229 $recordId = isset($data[$key]) ? $data[$key] : '0';
230
231 if ($recordId)
232 {
233 return $this->allowEdit($data, $key);
234 }
235 else
236 {
237 return $this->allowAdd($data);
238 }
239 }
240
241 242 243 244 245 246 247 248 249
250 public function batch($model)
251 {
252 $vars = $this->input->post->get('batch', array(), 'array');
253 $cid = $this->input->post->get('cid', array(), 'array');
254
255
256 $contexts = array();
257
258 $option = isset($this->extension) ? $this->extension : $this->option;
259
260 foreach ($cid as $id)
261 {
262
263 $contexts[$id] = $option . '.' . $this->context . '.' . $id;
264 }
265
266
267 if ($model->batch($vars, $cid, $contexts))
268 {
269 $this->setMessage(JText::_('JLIB_APPLICATION_SUCCESS_BATCH'));
270
271 return true;
272 }
273 else
274 {
275 $this->setMessage(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_FAILED', $model->getError()), 'warning');
276
277 return false;
278 }
279 }
280
281 282 283 284 285 286 287 288 289
290 public function cancel($key = null)
291 {
292 JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
293
294 $model = $this->getModel();
295 $table = $model->getTable();
296 $context = "$this->option.edit.$this->context";
297
298 if (empty($key))
299 {
300 $key = $table->getKeyName();
301 }
302
303 $recordId = $this->input->getInt($key);
304
305
306 if ($recordId)
307 {
308 if (property_exists($table, 'checked_out'))
309 {
310 if ($model->checkin($recordId) === false)
311 {
312
313 $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()));
314 $this->setMessage($this->getError(), 'error');
315
316 $this->setRedirect(
317 JRoute::_(
318 'index.php?option=' . $this->option . '&view=' . $this->view_item
319 . $this->getRedirectToItemAppend($recordId, $key), false
320 )
321 );
322
323 return false;
324 }
325 }
326 }
327
328
329 $this->releaseEditId($context, $recordId);
330 JFactory::getApplication()->setUserState($context . '.data', null);
331
332 $this->setRedirect(
333 JRoute::_(
334 'index.php?option=' . $this->option . '&view=' . $this->view_list
335 . $this->getRedirectToListAppend(), false
336 )
337 );
338
339 return true;
340 }
341
342 343 344 345 346 347 348 349 350 351 352
353 public function edit($key = null, $urlVar = null)
354 {
355
356 JFactory::getApplication()->allowCache(false);
357
358 $model = $this->getModel();
359 $table = $model->getTable();
360 $cid = $this->input->post->get('cid', array(), 'array');
361 $context = "$this->option.edit.$this->context";
362
363
364 if (empty($key))
365 {
366 $key = $table->getKeyName();
367 }
368
369
370 if (empty($urlVar))
371 {
372 $urlVar = $key;
373 }
374
375
376 $recordId = (int) (count($cid) ? $cid[0] : $this->input->getInt($urlVar));
377 $checkin = property_exists($table, $table->getColumnAlias('checked_out'));
378
379
380 if (!$this->allowEdit(array($key => $recordId), $key))
381 {
382 $this->setError(JText::_('JLIB_APPLICATION_ERROR_EDIT_NOT_PERMITTED'));
383 $this->setMessage($this->getError(), 'error');
384
385 $this->setRedirect(
386 JRoute::_(
387 'index.php?option=' . $this->option . '&view=' . $this->view_list
388 . $this->getRedirectToListAppend(), false
389 )
390 );
391
392 return false;
393 }
394
395
396 if ($checkin && !$model->checkout($recordId))
397 {
398
399 $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_CHECKOUT_FAILED', $model->getError()));
400 $this->setMessage($this->getError(), 'error');
401
402 $this->setRedirect(
403 JRoute::_(
404 'index.php?option=' . $this->option . '&view=' . $this->view_item
405 . $this->getRedirectToItemAppend($recordId, $urlVar), false
406 )
407 );
408
409 return false;
410 }
411 else
412 {
413
414 $this->holdEditId($context, $recordId);
415 JFactory::getApplication()->setUserState($context . '.data', null);
416
417 $this->setRedirect(
418 JRoute::_(
419 'index.php?option=' . $this->option . '&view=' . $this->view_item
420 . $this->getRedirectToItemAppend($recordId, $urlVar), false
421 )
422 );
423
424 return true;
425 }
426 }
427
428 429 430 431 432 433 434 435 436 437 438
439 public function getModel($name = '', $prefix = '', $config = array('ignore_request' => true))
440 {
441 if (empty($name))
442 {
443 $name = $this->context;
444 }
445
446 return parent::getModel($name, $prefix, $config);
447 }
448
449 450 451 452 453 454 455 456 457 458
459 protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id')
460 {
461 $append = '';
462
463
464 if ($tmpl = $this->input->get('tmpl', '', 'string'))
465 {
466 $append .= '&tmpl=' . $tmpl;
467 }
468
469 if ($layout = $this->input->get('layout', 'edit', 'string'))
470 {
471 $append .= '&layout=' . $layout;
472 }
473
474 if ($forcedLanguage = $this->input->get('forcedLanguage', '', 'cmd'))
475 {
476 $append .= '&forcedLanguage=' . $forcedLanguage;
477 }
478
479 if ($recordId)
480 {
481 $append .= '&' . $urlVar . '=' . $recordId;
482 }
483
484 $return = $this->input->get('return', null, 'base64');
485
486 if ($return)
487 {
488 $append .= '&return=' . $return;
489 }
490
491 return $append;
492 }
493
494 495 496 497 498 499 500
501 protected function getRedirectToListAppend()
502 {
503 $append = '';
504
505
506 if ($tmpl = $this->input->get('tmpl', '', 'string'))
507 {
508 $append .= '&tmpl=' . $tmpl;
509 }
510
511 if ($forcedLanguage = $this->input->get('forcedLanguage', '', 'cmd'))
512 {
513 $append .= '&forcedLanguage=' . $forcedLanguage;
514 }
515
516 return $append;
517 }
518
519 520 521 522 523 524 525 526 527 528 529
530 protected function postSaveHook(JModelLegacy $model, $validData = array())
531 {
532 }
533
534 535 536 537 538 539 540
541 public function loadhistory()
542 {
543 $model = $this->getModel();
544 $table = $model->getTable();
545 $historyId = $this->input->getInt('version_id', null);
546
547 if (!$model->loadhistory($historyId, $table))
548 {
549 $this->setMessage($model->getError(), 'error');
550
551 $this->setRedirect(
552 JRoute::_(
553 'index.php?option=' . $this->option . '&view=' . $this->view_list
554 . $this->getRedirectToListAppend(), false
555 )
556 );
557
558 return false;
559 }
560
561
562 if (empty($key))
563 {
564 $key = $table->getKeyName();
565 }
566
567 $recordId = $table->$key;
568
569
570 $urlVar = empty($this->urlVar) ? $key : $this->urlVar;
571
572
573 if (!$this->allowEdit(array($key => $recordId), $key))
574 {
575 $this->setError(JText::_('JLIB_APPLICATION_ERROR_EDIT_NOT_PERMITTED'));
576 $this->setMessage($this->getError(), 'error');
577
578 $this->setRedirect(
579 JRoute::_(
580 'index.php?option=' . $this->option . '&view=' . $this->view_list
581 . $this->getRedirectToListAppend(), false
582 )
583 );
584 $table->checkin();
585
586 return false;
587 }
588
589 $table->store();
590 $this->setRedirect(
591 JRoute::_(
592 'index.php?option=' . $this->option . '&view=' . $this->view_item
593 . $this->getRedirectToItemAppend($recordId, $urlVar), false
594 )
595 );
596
597 $this->setMessage(
598 JText::sprintf(
599 'JLIB_APPLICATION_SUCCESS_LOAD_HISTORY', $model->getState('save_date'), $model->getState('version_note')
600 )
601 );
602
603
604 $this->postSaveHook($model);
605
606 return true;
607 }
608
609 610 611 612 613 614 615 616 617 618
619 public function save($key = null, $urlVar = null)
620 {
621
622 JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
623
624 $app = JFactory::getApplication();
625 $model = $this->getModel();
626 $table = $model->getTable();
627 $data = $this->input->post->get('jform', array(), 'array');
628 $checkin = property_exists($table, $table->getColumnAlias('checked_out'));
629 $context = "$this->option.edit.$this->context";
630 $task = $this->getTask();
631
632
633 if (empty($key))
634 {
635 $key = $table->getKeyName();
636 }
637
638
639 if (empty($urlVar))
640 {
641 $urlVar = $key;
642 }
643
644 $recordId = $this->input->getInt($urlVar);
645
646
647 $data[$key] = $recordId;
648
649
650 if ($task == 'save2copy')
651 {
652
653 if ($checkin && $model->checkin($data[$key]) === false)
654 {
655
656 $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()));
657 $this->setMessage($this->getError(), 'error');
658
659 $this->setRedirect(
660 JRoute::_(
661 'index.php?option=' . $this->option . '&view=' . $this->view_item
662 . $this->getRedirectToItemAppend($recordId, $urlVar), false
663 )
664 );
665
666 return false;
667 }
668
669
670 $data[$key] = 0;
671 $data['associations'] = array();
672 $task = 'apply';
673 }
674
675
676 if (!$this->allowSave($data, $key))
677 {
678 $this->setError(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'));
679 $this->setMessage($this->getError(), 'error');
680
681 $this->setRedirect(
682 JRoute::_(
683 'index.php?option=' . $this->option . '&view=' . $this->view_list
684 . $this->getRedirectToListAppend(), false
685 )
686 );
687
688 return false;
689 }
690
691
692
693 $form = $model->getForm($data, false);
694
695 if (!$form)
696 {
697 $app->enqueueMessage($model->getError(), 'error');
698
699 return false;
700 }
701
702
703 $validData = $model->validate($form, $data);
704
705
706 if ($validData === false)
707 {
708
709 $errors = $model->getErrors();
710
711
712 for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++)
713 {
714 if ($errors[$i] instanceof Exception)
715 {
716 $app->enqueueMessage($errors[$i]->getMessage(), 'warning');
717 }
718 else
719 {
720 $app->enqueueMessage($errors[$i], 'warning');
721 }
722 }
723
724
725 $app->setUserState($context . '.data', $data);
726
727
728 $this->setRedirect(
729 JRoute::_(
730 'index.php?option=' . $this->option . '&view=' . $this->view_item
731 . $this->getRedirectToItemAppend($recordId, $urlVar), false
732 )
733 );
734
735 return false;
736 }
737
738 if (!isset($validData['tags']))
739 {
740 $validData['tags'] = null;
741 }
742
743
744 if (!$model->save($validData))
745 {
746
747 $app->setUserState($context . '.data', $validData);
748
749
750 $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError()));
751 $this->setMessage($this->getError(), 'error');
752
753 $this->setRedirect(
754 JRoute::_(
755 'index.php?option=' . $this->option . '&view=' . $this->view_item
756 . $this->getRedirectToItemAppend($recordId, $urlVar), false
757 )
758 );
759
760 return false;
761 }
762
763
764 if ($checkin && $model->checkin($validData[$key]) === false)
765 {
766
767 $app->setUserState($context . '.data', $validData);
768
769
770 $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()));
771 $this->setMessage($this->getError(), 'error');
772
773 $this->setRedirect(
774 JRoute::_(
775 'index.php?option=' . $this->option . '&view=' . $this->view_item
776 . $this->getRedirectToItemAppend($recordId, $urlVar), false
777 )
778 );
779
780 return false;
781 }
782
783 $langKey = $this->text_prefix . ($recordId == 0 && $app->isClient('site') ? '_SUBMIT' : '') . '_SAVE_SUCCESS';
784 $prefix = JFactory::getLanguage()->hasKey($langKey) ? $this->text_prefix : 'JLIB_APPLICATION';
785
786 $this->setMessage(JText::_($prefix . ($recordId == 0 && $app->isClient('site') ? '_SUBMIT' : '') . '_SAVE_SUCCESS'));
787
788
789 switch ($task)
790 {
791 case 'apply':
792
793 $recordId = $model->getState($this->context . '.id');
794 $this->holdEditId($context, $recordId);
795 $app->setUserState($context . '.data', null);
796 $model->checkout($recordId);
797
798
799 $this->setRedirect(
800 JRoute::_(
801 'index.php?option=' . $this->option . '&view=' . $this->view_item
802 . $this->getRedirectToItemAppend($recordId, $urlVar), false
803 )
804 );
805 break;
806
807 case 'save2new':
808
809 $this->releaseEditId($context, $recordId);
810 $app->setUserState($context . '.data', null);
811
812
813 $this->setRedirect(
814 JRoute::_(
815 'index.php?option=' . $this->option . '&view=' . $this->view_item
816 . $this->getRedirectToItemAppend(null, $urlVar), false
817 )
818 );
819 break;
820
821 default:
822
823 $this->releaseEditId($context, $recordId);
824 $app->setUserState($context . '.data', null);
825
826 $url = 'index.php?option=' . $this->option . '&view=' . $this->view_list
827 . $this->getRedirectToListAppend();
828
829
830 $return = $this->input->get('return', null, 'base64');
831
832 if (!is_null($return) && JUri::isInternal(base64_decode($return)))
833 {
834 $url = base64_decode($return);
835 }
836
837
838 $this->setRedirect(JRoute::_($url, false));
839 break;
840 }
841
842
843 $this->postSaveHook($model, $validData);
844
845 return true;
846 }
847 }
848