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

/framework/classes/orm/behaviour/twinnable.php

https://github.com/jay3/core
PHP | 761 lines | 505 code | 94 blank | 162 comment | 79 complexity | 73f30c2891d6c5c31395748d1b7a52b2 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /**
  3. * NOVIUS OS - Web OS for digital communication
  4. *
  5. * @copyright 2011 Novius
  6. * @license GNU Affero General Public License v3 or (at your option) any later version
  7. * http://www.gnu.org/licenses/agpl-3.0.html
  8. * @link http://www.novius-os.org
  9. */
  10. namespace Nos;
  11. class Orm_Behaviour_Twinnable extends Orm_Behaviour_Contextable
  12. {
  13. protected static $_shared_medias_context_cached = array();
  14. protected static $_shared_wysiwygs_context_cached = array();
  15. protected $_in_progress_check = array();
  16. public static function _init()
  17. {
  18. I18n::current_dictionary('nos::orm');
  19. }
  20. /**
  21. * common_id_property
  22. * is_main_property
  23. * common_fields
  24. */
  25. protected $_properties = array();
  26. public function __construct($class)
  27. {
  28. parent::__construct($class);
  29. if (!isset($this->_properties['common_fields'])) {
  30. $this->_properties['common_fields'] = array();
  31. }
  32. }
  33. /**
  34. * Add relations for linked media and wysiwyg shared with other context
  35. */
  36. public function buildRelations()
  37. {
  38. $class = $this->_class;
  39. $class::addRelation('has_many', 'linked_shared_wysiwygs_context', array(
  40. 'key_from' => $this->_properties['common_id_property'],
  41. 'model_to' => 'Nos\Model_Wysiwyg',
  42. 'key_to' => 'wysiwyg_foreign_context_common_id',
  43. 'cascade_save' => true,
  44. 'cascade_delete' => true,
  45. 'conditions' => array(
  46. 'where' => array(
  47. array('wysiwyg_join_table', '=', \DB::expr(\DB::quote($class::table()))),
  48. ),
  49. ),
  50. ));
  51. $class::addRelation('has_many', 'linked_shared_medias_context', array(
  52. 'key_from' => $this->_properties['common_id_property'],
  53. 'model_to' => 'Nos\Media\Model_Link',
  54. 'key_to' => 'medil_foreign_context_common_id',
  55. 'cascade_save' => true,
  56. 'cascade_delete' => true,
  57. 'conditions' => array(
  58. 'where' => array(
  59. array('medil_from_table', '=', \DB::expr(\DB::quote($class::table()))),
  60. ),
  61. ),
  62. ));
  63. }
  64. /**
  65. * Add linked wysiwygs shared by twin contexts in linked wysiwygs array
  66. *
  67. * @param \Nos\Orm\Model $item
  68. * @param array $linked_wysiwygs Array of linked wysiwygs, Passed by reference.
  69. */
  70. public function getLinkedWysiwygs(Orm\Model $item, &$linked_wysiwygs)
  71. {
  72. $linked_wysiwygs = $linked_wysiwygs + $item->linked_shared_wysiwygs_context;
  73. }
  74. /**
  75. * Add linked medias shared by twin contexts in linked medias array
  76. *
  77. * @param \Nos\Orm\Model $item
  78. * @param array $linked_medias Array of linked medias, Passed by reference.
  79. */
  80. public function getLinkedMedias(Orm\Model $item, &$linked_medias)
  81. {
  82. $linked_medias = $linked_medias + $item->linked_shared_medias_context;
  83. }
  84. /**
  85. * Add linked wysiwyg to the item if is shared by twin contexts
  86. *
  87. * @param \Nos\Orm\Model $item
  88. * @param bool $added Passed by reference. Set to true if the wysiwyg is a linked wysiwyg shared by context.
  89. * @param string $name Name of the linked wysiwyg,
  90. * @param string $value Content of the wysiwyg.
  91. */
  92. public function addLinkedWysiwyg(Orm\Model $item, &$added, $name, $value)
  93. {
  94. $class = $this->_class;
  95. if (in_array($name, static::sharedWysiwygsContext($class))) {
  96. $wysiwyg = new \Nos\Model_Wysiwyg();
  97. $wysiwyg->wysiwyg_text = $value;
  98. $wysiwyg->wysiwyg_join_table = $class::table();
  99. $wysiwyg->wysiwyg_key = $name;
  100. $wysiwyg->wysiwyg_foreign_context_common_id = $item->{$this->_properties['common_id_property']};
  101. // Don't save the link here, it's done with cascade_save = true
  102. //$wysiwyg->save();
  103. $this->linked_shared_wysiwygs_context[] = $wysiwyg;
  104. $added = true;
  105. }
  106. }
  107. /**
  108. * Add linked media to the item if is shared by twin contexts
  109. *
  110. * @param \Nos\Orm\Model $item
  111. * @param bool $added Passed by reference. Set to true if the media is a linked media shared by context.
  112. * @param string $name Name of the linked media,
  113. * @param int $value Id of the media.
  114. */
  115. public function addLinkedMedia(Orm\Model $item, &$added, $name, $value)
  116. {
  117. $class = $this->_class;
  118. if (in_array($name, static::sharedMediaContext($class))) {
  119. $medil = new \Nos\Media\Model_Link();
  120. $medil->medil_from_table = $class::table();
  121. $medil->medil_key = $name;
  122. $medil->medil_foreign_context_common_id = $item->{$this->_properties['common_id_property']};
  123. $medil->medil_media_id = $value;
  124. // Don't save the link here, it's done with cascade_save = true
  125. $item->linked_shared_medias_context[] = $medil;
  126. $added = true;
  127. }
  128. }
  129. /**
  130. * @return bool Return true if model has common fields (fields, linked medias or wysiwyg)
  131. */
  132. public function hasCommonFields()
  133. {
  134. $class = $this->_class;
  135. return count($this->_properties['common_fields']) > 0 ||
  136. static::sharedWysiwygsContext($class) > 0 ||
  137. static::sharedMediaContext($class) > 0;
  138. }
  139. /**
  140. * @param string $name Name of the field
  141. * @return bool Return true the field is common to contexts (fields, linked medias or wysiwyg)
  142. */
  143. public function isCommonField($name)
  144. {
  145. if (in_array($name, $this->_properties['common_fields'])) {
  146. return true;
  147. }
  148. $arr_name = explode('->', $name);
  149. if (count($arr_name) > 1) {
  150. $class = $this->_class;
  151. if ($arr_name[0] == 'wysiwygs' && in_array($arr_name[1], static::sharedWysiwygsContext($class))) {
  152. return true;
  153. }
  154. if ($arr_name[0] == 'medias' && in_array($arr_name[1], static::sharedMediaContext($class))) {
  155. return true;
  156. }
  157. }
  158. return false;
  159. }
  160. /**
  161. * @param $model Model name
  162. * @return array Array of wysiwyg keys which is common to all contexts
  163. */
  164. public static function sharedWysiwygsContext($model)
  165. {
  166. $init = array_key_exists($model, static::$_shared_wysiwygs_context_cached);
  167. if (!$init) {
  168. $shared_wysiwygs_context = array();
  169. if (property_exists($model, 'shared_wysiwygs_context')) {
  170. $shared_wysiwygs_context = $model::${'shared_wysiwygs_context'};
  171. }
  172. $config = $model::configModel();
  173. if (!empty($config) && !empty($config['shared_wysiwygs_context'])) {
  174. $shared_wysiwygs_context = array_merge($shared_wysiwygs_context, $config['shared_wysiwygs_context']);
  175. }
  176. static::$_shared_wysiwygs_context_cached[$model] = $shared_wysiwygs_context;
  177. }
  178. return static::$_shared_wysiwygs_context_cached[$model];
  179. }
  180. /**
  181. * @param $model Model name
  182. * @return array Array of media keys which is common to all contexts for the model
  183. */
  184. public static function sharedMediaContext($model)
  185. {
  186. $init = array_key_exists($model, static::$_shared_medias_context_cached);
  187. if (!$init) {
  188. $shared_medias_context = array();
  189. if (property_exists($model, 'shared_medias_context')) {
  190. $shared_medias_context = $model::${'shared_medias_context'};
  191. }
  192. $config = $model::configModel();
  193. if (!empty($config) && !empty($config['shared_medias_context'])) {
  194. $shared_medias_context = array_merge($shared_medias_context, $config['shared_medias_context']);
  195. }
  196. static::$_shared_medias_context_cached[$model] = $shared_medias_context;
  197. }
  198. return static::$_shared_medias_context_cached[$model];
  199. }
  200. /**
  201. * Fill in the context_common_id and context properties when creating the object
  202. *
  203. * @param \Nos\Orm\Model $item
  204. * @return void
  205. */
  206. public function before_insert(Orm\Model $item)
  207. {
  208. $common_id_property = $this->_properties['common_id_property'];
  209. if (empty($item->{$common_id_property})) {
  210. $item->set($common_id_property, 0);
  211. }
  212. }
  213. /**
  214. * Updates the context_common_id property
  215. *
  216. * @param \Nos\Orm\Model $item
  217. * @return void
  218. */
  219. public function after_insert(Orm\Model $item)
  220. {
  221. $common_id_property = $this->_properties['common_id_property'];
  222. $is_main_property = $this->_properties['is_main_property'];
  223. // It's a new main context
  224. if ($item->get($common_id_property) == 0) {
  225. // __get() magic method will retrieve $_primary_key[0]
  226. $item->set($common_id_property, $item->id);
  227. $item->set($is_main_property, true);
  228. $update = \DB::update($item->table())->set(array(
  229. $common_id_property => $item->id,
  230. $is_main_property => true,
  231. ));
  232. foreach ($item->primary_key() as $pk) {
  233. $update->where($pk, $item->get($pk));
  234. }
  235. $update->execute();
  236. // Database was updated using DB directly, because save() triggers all the observers, and we don't need that
  237. // $item->save();
  238. }
  239. }
  240. /**
  241. * Copies all common fields from the main context. Remove empty context linked wysiwygs and medias.
  242. *
  243. * @param \Nos\Orm\Model $item
  244. */
  245. public function before_save(Orm\Model $item)
  246. {
  247. $w_keys = array_keys($item->linked_shared_wysiwygs_context);
  248. foreach ($w_keys as $i) {
  249. // Remove empty wysiwyg
  250. if (empty($item->linked_shared_wysiwygs_context[$i]->wysiwyg_text)) {
  251. $this->linked_shared_wysiwygs_context[$i]->delete();
  252. unset($item->linked_shared_wysiwygs_context[$i]);
  253. }
  254. }
  255. $w_keys = array_keys($item->linked_shared_medias_context);
  256. foreach ($w_keys as $i) {
  257. // Remove empty medias
  258. if (empty($item->linked_shared_medias_context[$i]->medil_media_id)) {
  259. $item->linked_shared_medias_context[$i]->delete();
  260. unset($item->linked_shared_medias_context[$i]);
  261. }
  262. }
  263. $obj_main = $this->find_main_context($item);
  264. // No main context found => we just created a new main item :)
  265. if (empty($obj_main)) {
  266. $item->set($this->_properties['is_main_property'], true);
  267. }
  268. if (empty($this->_properties['common_fields'])) {
  269. return;
  270. }
  271. // Prevents looping in the observer
  272. if (!in_array($item->id, $this->_in_progress_check)) {
  273. $items = $this->find_other_context($item);
  274. $this->_in_progress_check = array_keys($items);
  275. foreach ($items as $it) {
  276. foreach ($this->_properties['common_fields'] as $common_field) {
  277. $it->set($common_field, $item->get($common_field));
  278. }
  279. }
  280. foreach ($items as $it) {
  281. $it->save();
  282. }
  283. $this->_in_progress_check = array();
  284. }
  285. }
  286. public function after_delete(Orm\Model $item)
  287. {
  288. if (!$this->is_main_context($item)) {
  289. return;
  290. }
  291. $available_contexts = $item->get_all_context();
  292. // Set the is_main property for one of the context
  293. foreach (Tools_Context::contexts() as $code => $name) {
  294. if (in_array($code, $available_contexts)) {
  295. $new_main_item = $this->find_context($item, $code);
  296. $new_main_item->set($this->_properties['is_main_property'], true);
  297. $new_main_item->save();
  298. break;
  299. }
  300. }
  301. }
  302. /**
  303. * Check if the parent exists in all the contexts of the child
  304. * @param \Nos\Orm\Model $item
  305. * @throws \Exception
  306. */
  307. public function change_parent(Orm\Model $item)
  308. {
  309. // This event has been sent from the tree behaviour, so we don't need to check the method exists
  310. $new_parent = $item->get_parent();
  311. if (!empty($new_parent)) {
  312. $contexts_parent = $new_parent->get_all_context();
  313. if ($item->is_new()) {
  314. $context_self = $item->get_context();
  315. if (!in_array($context_self, $contexts_parent)) {
  316. throw new \Exception(strtr(__('We’re afraid it cannot be added to {{context}} because its parent is not available in this context yet.'), array(
  317. '{{context}}' => \Nos\Tools_Context::contextLabel($context_self),
  318. )));
  319. }
  320. } else {
  321. $contexts_self = $this->get_all_context($item);
  322. $missing_contexts = array_diff($contexts_self, $contexts_parent);
  323. if (!empty($missing_contexts)) {
  324. throw new \Exception(strtr(__('We’re afraid it cannot be moved here because the parent is not available in the following contexts: {{contexts}}'), array(
  325. '{{contexts}}' => implode(', ', array_map(function ($context) {
  326. return \Nos\Tools_Context::contextLabel($context);
  327. }, $missing_contexts)),
  328. )));
  329. }
  330. }
  331. }
  332. $item->observe('check_change_parent');
  333. // Prevents looping in the observer
  334. if (!in_array($item->id, $this->_in_progress_check)) {
  335. $items = $this->find_other_context($item);
  336. $this->_in_progress_check = array_keys($items);
  337. foreach ($items as $it) {
  338. $parent = $new_parent === null ? null : $new_parent->find_context($it->get_context());
  339. $it->set_parent($parent);
  340. $it->observe('check_change_parent');
  341. }
  342. foreach ($items as $it) {
  343. $it->save();
  344. }
  345. $this->_in_progress_check = array();
  346. }
  347. }
  348. /**
  349. * Optimised operation for deleting all contexts
  350. *
  351. * @param \Nos\Orm\Model $item
  352. */
  353. public function delete_all_context(Orm\Model $item)
  354. {
  355. foreach ($item->find_context('all') as $item) {
  356. // This is to trick the is_main_context() method
  357. // This way, the 'after_delete' observer won't reassign is_main
  358. $item->set($this->_properties['is_main_property'], false);
  359. $item->delete();
  360. }
  361. }
  362. /**
  363. * Returns null if the Model is not twinnable. Returns true or false whether the object is in the main context.
  364. *
  365. * @param \Nos\Orm\Model $item
  366. * @return bool
  367. */
  368. public function is_main_context(Orm\Model $item)
  369. {
  370. // use !! for cast to boolean
  371. return !!$item->get($this->_properties['is_main_property']);
  372. }
  373. /**
  374. * Find the object in the main context
  375. *
  376. * @param \Nos\Orm\Model $item
  377. * @return \Nos\Orm\Model
  378. */
  379. public function find_main_context(Orm\Model $item)
  380. {
  381. if ($item->is_main_context()) {
  382. return $item;
  383. }
  384. return $item->find_context('main');
  385. }
  386. /**
  387. * Find the object in the specified context. Won't create it when it doesn't exists
  388. *
  389. * @param \Nos\Orm\Model $item
  390. * @param string | array $context Which locale to retrieve.
  391. * - 'main' will return the main context
  392. * - 'all' will return all the available objects
  393. * - any valid locale
  394. * - array if not empty, return only contexts specified
  395. * @return \Nos\Orm\Model | array(\Nos\Orm\Model)
  396. */
  397. public function find_context(Orm\Model $item, $context)
  398. {
  399. $common_id_property = $this->_properties['common_id_property'];
  400. $common_id = $item->get($common_id_property);
  401. if ($context == 'all' || is_array($context)) {
  402. $where = array(
  403. array($common_id_property, $common_id),
  404. );
  405. if (is_array($context) && !empty($context)) {
  406. $where[] = array($this->_properties['context_property'], 'IN', $context);
  407. }
  408. return $item->find('all', array('where' => $where));
  409. }
  410. if ($context === 'main' ? ($item->{$this->_properties['is_main_property']}) : ($item->{$this->_properties['context_property']} == $context)) {
  411. return $item->is_new() ? null : $item;
  412. } else {
  413. return $item->find('first', array(
  414. 'where' => array(
  415. array($common_id_property, $common_id),
  416. $context === 'main' ? array($this->_properties['is_main_property'], true) : array($this->_properties['context_property'], $context),
  417. )));
  418. }
  419. }
  420. /**
  421. * Find objects in other context that the item
  422. *
  423. * @param \Nos\Orm\Model $item
  424. * @param array $filter if not empty, return only contexts specified
  425. * @return array(\Nos\Orm\Model)
  426. */
  427. public function find_other_context(Orm\Model $item, array $filter = array())
  428. {
  429. $common_id_property = $this->_properties['common_id_property'];
  430. $common_id = $item->get($common_id_property);
  431. $where = array(
  432. array($common_id_property, $common_id),
  433. array($this->_properties['context_property'], '!=', $item->get_context()),
  434. );
  435. if (!empty($filter)) {
  436. $where[] = array($this->_properties['context_property'], 'IN', $filter);
  437. }
  438. return $item->find('all', array('where' => $where));
  439. }
  440. /**
  441. * Returns all available context for this object
  442. *
  443. * @param \Nos\Orm\Model $item
  444. * @param array $filter if not empty, return only contexts specified
  445. * @return array
  446. */
  447. public function get_all_context(Orm\Model $item, array $filter = array())
  448. {
  449. $all = array();
  450. foreach ($item->find_context($filter) as $item) {
  451. $context = $item->get($this->_properties['context_property']);
  452. $all[$item->id] = $context;
  453. }
  454. return $all;
  455. }
  456. /**
  457. * Returns all other available context for this object
  458. *
  459. * @param \Nos\Orm\Model $item
  460. * @param array $filter if not empty, return only contexts specified
  461. * @return array
  462. */
  463. public function get_other_context(Orm\Model $item, array $filter = array())
  464. {
  465. $other = array();
  466. foreach ($item->find_other_context($filter) as $item) {
  467. $context = $item->get($this->_properties['context_property']);
  468. $other[$item->id] = $context;
  469. }
  470. return $other;
  471. }
  472. /**
  473. * Returns all possible contexts for this object, depend of his parent.
  474. *
  475. * @param \Nos\Orm\Model $item
  476. * @return array
  477. */
  478. public function get_possible_context(Orm\Model $item)
  479. {
  480. $class = $this->_class;
  481. $tree = $class::behaviours('Nos\Orm_Behaviour_Tree');
  482. if (!$tree) {
  483. return array_keys(\Nos\Tools_Context::contexts());
  484. }
  485. // Return contexts from parent if available
  486. $parent = $item->get_parent();
  487. if (!empty($parent)) {
  488. return $parent->get_all_context();
  489. }
  490. return array_keys(\Nos\Tools_Context::contexts());
  491. }
  492. /**
  493. * Returns all available contexts for the requested items
  494. *
  495. * @param array $where
  496. * @return array List of available contexts for each is_main
  497. */
  498. public function contexts($where)
  499. {
  500. $common_id_property = $this->_properties['common_id_property'];
  501. $context_property = $this->_properties['context_property'];
  502. $properties = array(
  503. array($common_id_property, $common_id_property),
  504. array(\Db::expr('GROUP_CONCAT('.$context_property.')'), 'list_context'),
  505. );
  506. $query = call_user_func_array('\Db::select', $properties)
  507. ->from(call_user_func($this->_class . '::table'))
  508. ->group_by($common_id_property);
  509. foreach ($where as $field_name => $value) {
  510. if (!empty($value)) {
  511. if (is_array($value)) {
  512. $query->where($field_name, 'in', $value);
  513. } else {
  514. $query->where($field_name, '=', $value);
  515. }
  516. }
  517. }
  518. $data = array();
  519. foreach ($query->execute() as $row) {
  520. $data[$row[$common_id_property]] = $row['list_context'];
  521. }
  522. return $data;
  523. }
  524. public function findMainOrContext($context, array $options = array())
  525. {
  526. $class = $this->_class;
  527. $query = $class::query($options)
  528. ->and_where_open()
  529. ->where($this->_properties['context_property'], '=', $context)
  530. ->or_where($this->_properties['is_main_property'], '=', 1)
  531. ->and_where_close();
  532. $result = array();
  533. $result_context = array();
  534. foreach ($query->get() as $pk => $item) {
  535. if (isset($result_context[$item->{$this->_properties['common_id_property']}])) {
  536. if ($item->{$this->_properties['context_property']} !== $context) {
  537. continue;
  538. } else {
  539. unset($result[$result_context[$item->{$this->_properties['common_id_property']}]]);
  540. }
  541. }
  542. $result_context[$item->{$this->_properties['common_id_property']}] = $pk;
  543. $result[$pk] = $item;
  544. }
  545. return $result;
  546. }
  547. public function before_query(&$options)
  548. {
  549. if (array_key_exists('where', $options)) {
  550. $where = $options['where'];
  551. if (isset($where['context_main'])) {
  552. $where[$this->_properties['is_main_property']] = $where['context_main'];
  553. unset($where['context_main']);
  554. }
  555. foreach ($where as $k => $w) {
  556. if (is_int($k)) {
  557. $keys = array_keys($w);
  558. if (count($w) == 1 && $keys[0] == 'context_main') {
  559. $where[$k] = array($this->_properties['is_main_property'] => $w[$keys[0]]);
  560. }
  561. if (count($w) > 1 && $w[0] == 'context_main') {
  562. $w[0] = $this->_properties['is_main_property'];
  563. $where[$k] = $w;
  564. }
  565. }
  566. }
  567. $options['where'] = $where;
  568. }
  569. }
  570. public function gridAfter($config, $objects, &$items)
  571. {
  572. foreach ($objects as $object) {
  573. $common_id = $object->{$this->_properties['common_id_property']};
  574. $itemsKeys[] = $common_id;
  575. $commonIds[$this->_properties['common_id_property']][] = $common_id;
  576. }
  577. $class = $this->_class;
  578. $contexts = $class::contexts($commonIds);
  579. foreach ($contexts as $common_id => $list) {
  580. $contexts[$common_id] = explode(',', $list);
  581. }
  582. foreach ($itemsKeys as $key => $common_id) {
  583. $items[$key]['context'] = $contexts[$common_id];
  584. }
  585. $sites_count = count(\Nos\User\Permission::sites());
  586. $locales_count = count(\Nos\User\Permission::locales());
  587. $global_contexts = array_keys(\Nos\User\Permission::contexts());
  588. foreach ($items as &$item) {
  589. $flags = '';
  590. $contexts = $item['context'];
  591. $site = false;
  592. foreach ($global_contexts as $context) {
  593. if (is_array($config['context']) && !in_array($context, $config['context'])) {
  594. continue;
  595. }
  596. $site_params = Tools_Context::site($context);
  597. // When the site change
  598. if ($sites_count > 1 && $site !== $site_params['alias']) {
  599. $site = $site_params['alias'];
  600. $in = false;
  601. // Check if the any context of the item exists in the site
  602. foreach ($contexts as $temp_context) {
  603. if (Tools_Context::siteCode($temp_context) === $site_params['code']) {
  604. $in = true;
  605. break;
  606. }
  607. }
  608. $flags .= (empty($flags) ? '' : '&nbsp;&nbsp;&nbsp;').'<span style="'.(!$in ? 'visibility:hidden;' : '').'vertical-align:middle;" title="'.htmlspecialchars($site_params['title']).'">'.$site_params['alias'].'</span> ';
  609. }
  610. if ($locales_count > 1) {
  611. if (in_array($context, $contexts)) {
  612. $flags .= ' '.\Nos\Tools_Context::flag($context);
  613. } else {
  614. $flags .= ' <span style="display:inline-block; width:16px;"></span>';
  615. }
  616. }
  617. }
  618. $item['context'] = $flags;
  619. }
  620. }
  621. public function crudFields(&$fields, $crud)
  622. {
  623. parent::crudFields($fields, $crud);
  624. $fields = \Arr::merge(
  625. $fields,
  626. array(
  627. $this->_properties['common_id_property'] => array(
  628. 'form' => array(
  629. 'type' => 'hidden',
  630. 'value' => $crud->item->{$this->_properties['common_id_property']},
  631. ),
  632. ),
  633. )
  634. );
  635. if ($this->hasCommonFields() &&
  636. ((!$crud->is_new && count($contexts = $crud->item->get_other_context()) > 0) ||
  637. ($crud->is_new && !empty($crud->item->{$this->_properties['common_id_property']})))) {
  638. $crud->config['layout_insert']['common_fields'] = array('view' => 'nos::crud/context_common_fields');
  639. $crud->config['layout_update']['common_fields'] = array('view' => 'nos::crud/context_common_fields');
  640. if ($crud->is_new) {
  641. $contexts = $crud->item->get_all_context();
  642. if (empty($this->item_from)) {
  643. $from = $crud->item->find_main_context();
  644. }
  645. }
  646. $context_labels = array();
  647. foreach ($contexts as $context) {
  648. $context_labels[] = Tools_Context::contextLabel($context);
  649. }
  650. $context_labels = htmlspecialchars(\Format::forge($context_labels)->to_json());
  651. foreach ($fields as $key => $field) {
  652. if ($this->isCommonField($key)) {
  653. $fields[$key]['form']['disabled'] = true;
  654. $fields[$key]['form']['context_common_field'] = true;
  655. $fields[$key]['form']['data-other-contexts'] = $context_labels;
  656. if ($crud->is_new && !empty($from)) {
  657. $crud->item->{$key} = $from->{$key};
  658. }
  659. }
  660. }
  661. }
  662. }
  663. public function afterClone(Orm\Model $item)
  664. {
  665. $item->{$this->_properties['is_main_property']} = false;
  666. }
  667. }