PageRenderTime 44ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/include/SugarFields/Fields/Relatecollection/SugarFieldRelatecollection.php

https://bitbucket.org/hatim_alam/sugar-8
PHP | 269 lines | 109 code | 30 blank | 130 comment | 17 complexity | 5140243d4738cfaa0f15887470a87082 MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-3-Clause, Apache-2.0, MIT, BSD-2-Clause
  1. <?php
  2. /*
  3. * Your installation or use of this SugarCRM file is subject to the applicable
  4. * terms available at
  5. * http://support.sugarcrm.com/Resources/Master_Subscription_Agreements/.
  6. * If you do not agree to all of the applicable terms or do not have the
  7. * authority to bind the entity as an authorized representative, then do not
  8. * install or use this SugarCRM file.
  9. *
  10. * Copyright (C) SugarCRM Inc. All rights reserved.
  11. */
  12. /**
  13. *
  14. * Related collection field
  15. *
  16. * This field type can be used on record views to show related records for
  17. * the given bean context. Essentially a related collection field acts the
  18. * same as a subpanel, except that the records are shown directly in the
  19. * record view itself.
  20. *
  21. * There are already certain implementation which look alike, for example
  22. * email addresses and team sets. This sugar field type uses a generic
  23. * approach from which can be extended.
  24. *
  25. * Available vardef settings:
  26. *
  27. * array(
  28. * 'type' => 'relatedcollection'
  29. * 'link' => pointer to a vardef link field defining the relationship
  30. * Required parameter without a default
  31. * 'collection_fields' => array of fields to return from related object
  32. * Optional, defaults to id and name field
  33. * 'collection_limit' => maximum amount of related records to return
  34. * Optional, defaults to unlimited
  35. * 'collection_create' => ability to create new objects while linking
  36. * Optional, defaults to false
  37. * )
  38. *
  39. */
  40. class SugarFieldRelatecollection extends SugarFieldBase
  41. {
  42. /**
  43. *
  44. * Base fields for collection
  45. * @var array
  46. */
  47. protected static $baseFields = array(
  48. 'id',
  49. 'name',
  50. );
  51. /**
  52. *
  53. * Base collection limit
  54. * @var integer
  55. */
  56. protected static $baseLimit = -1;
  57. /**
  58. *
  59. * {@inheritdoc}
  60. */
  61. public function apiFormatField(array &$data, SugarBean $bean, array $args, $fieldName, $properties, array $fieldList = null, ServiceBase $service = null)
  62. {
  63. list ($relName, $fields, $limit) = $this->parseProperties($properties);
  64. $records = $this->getLinkedRecords($bean, $relName, $fields, $limit);
  65. $data[$fieldName] = array_values($records);
  66. }
  67. /**
  68. *
  69. * {@inheritdoc}
  70. */
  71. public function apiSave(SugarBean $bean, array $params, $field, $properties)
  72. {
  73. if (empty($params[$field]) || !is_array($params[$field])) {
  74. return;
  75. }
  76. // retrieve current linked objects
  77. list ($relName, $fields, $limit, $create) = $this->parseProperties($properties);
  78. $currentList = $this->getLinkedRecords($bean, $relName, $fields, $limit);
  79. /*
  80. * We do not require the client to send back the full list of related
  81. * items. Only explicit additions/removals are required. Already
  82. * present links are maintained if not explicitly defined during save.
  83. */
  84. foreach ($params[$field] as $record) {
  85. // validate required fields
  86. if (!$this->validateRequiredFields($record)) {
  87. continue;
  88. }
  89. // handle (new) related records
  90. if (empty($record['removed'])) {
  91. // create new bean first if supported when no id is provided
  92. if ($record['id'] === false && $create) {
  93. $new = $this->createNewBeanBeforeLink($bean, $relName, $record);
  94. if (!empty($new->id)) {
  95. $bean->$relName->add($new);
  96. }
  97. }
  98. // add new link if it doesn't exist yet
  99. if ($record['id'] && !isset($currentList[$record['id']])) {
  100. $bean->$relName->add($record['id']);
  101. }
  102. // handle related records flagged for removal
  103. } elseif (!empty($record['removed']) && !empty($record['id'])) {
  104. // just remove the link, Link2 will take care of the checks
  105. $bean->$relName->delete($bean->id, $record['id']);
  106. }
  107. }
  108. }
  109. /**
  110. *
  111. * Create a new bean before linking it to the parent
  112. * @param SugarBean $parent
  113. * @param string $relName Relationship name
  114. * @param array $record Data to use to create related bean
  115. * @return SugarBean
  116. */
  117. protected function createNewBeanBeforeLink(SugarBean $parent, $relName, array $record)
  118. {
  119. $relSeed = $this->getRelatedSeedBean($parent, $relName);
  120. $new = BeanFactory::newBean($relSeed->module_name);
  121. $new->fromArray($record);
  122. $new->save();
  123. return $new;
  124. }
  125. /**
  126. *
  127. * Check if required fields are present for given record (base fields).
  128. * @param array $record
  129. * @return boolean
  130. */
  131. protected function validateRequiredFields(array $record)
  132. {
  133. foreach (self::$baseFields as $field) {
  134. if (!isset($record[$field])) {
  135. return false;
  136. }
  137. }
  138. return true;
  139. }
  140. /**
  141. *
  142. * Return linked object data for given bean/relationship.
  143. * @param SugarBean $parent
  144. * @param string $relName
  145. * @param array $fields
  146. * @param integer $limit
  147. * @param string|array $orderBy field name or array of field name and direction to sort by
  148. * @return array
  149. */
  150. protected function getLinkedRecords(SugarBean $parent, $relName, array $fields, $limit, $orderBy = '')
  151. {
  152. if (! $relSeed = $this->getRelatedSeedBean($parent, $relName)) {
  153. return array();
  154. }
  155. // base query object for related module
  156. $sq = $this->getSugarQuery();
  157. $sq->select($fields);
  158. $sq->from($relSeed);
  159. if ($limit > 0) {
  160. $sq->limit($limit);
  161. }
  162. if (is_array($orderBy)) {
  163. $sq->orderBy($orderBy[0], $orderBy[1]);
  164. } elseif (is_string($orderBy)) {
  165. $sq->orderBy($orderBy);
  166. }
  167. // join against parent module
  168. $sq->joinSubpanel($parent, $relName);
  169. $result = array();
  170. foreach ($sq->execute() as $record) {
  171. $result[$record['id']] = $record;
  172. }
  173. return $result;
  174. }
  175. /**
  176. *
  177. * Parse field properties, return defaults if not set.
  178. * @param array $properties
  179. * @return array
  180. */
  181. protected function parseProperties(array $properties)
  182. {
  183. // link is required
  184. $link = empty($properties['link']) ? false : $properties['link'];
  185. // field list
  186. $fields = self::$baseFields;
  187. if (!empty($properties['collection_fields']) && is_array($properties['collection_fields'])) {
  188. $fields = array_unique(array_merge(self::$baseFields, $properties['collection_fields']));
  189. }
  190. // maximum related records
  191. $limit = (int) empty($properties['collection_limit']) ? self::$baseLimit : $properties['collection_limit'];
  192. // create linked object (disabled by default)
  193. $create = !empty($properties['collection_create']) ?: false;
  194. return array($link, $fields, $limit, $create);
  195. }
  196. /**
  197. *
  198. * Return a SugarBean for the other end of a given bean/relationship.
  199. * @param SugarBean $bean
  200. * @param string $rel Link name
  201. * @return mixed (SugarBean|null)
  202. */
  203. protected function getRelatedSeedBean(SugarBean $bean, $rel)
  204. {
  205. if ($bean->load_relationship($rel)) {
  206. return BeanFactory::newBean($bean->$rel->getRelatedModuleName());
  207. }
  208. }
  209. /**
  210. *
  211. * Return a new SugarQuery object.
  212. * @return SugarQuery
  213. */
  214. protected function getSugarQuery()
  215. {
  216. return new SugarQuery();
  217. }
  218. /**
  219. * Used during mass update process
  220. * @param SugarBean $bean
  221. * @param array $params
  222. * @param string $fieldName
  223. * @param array $properties
  224. * @return void
  225. */
  226. public function apiMassUpdate(SugarBean $bean, array $params, $fieldName, $properties)
  227. {
  228. return $this->apiSave($bean, $params, $fieldName, $properties);
  229. }
  230. /**
  231. * {@inheritDoc}
  232. *
  233. * We don't need to add relate collections to listview queries since we will grab those
  234. * records later on
  235. */
  236. public function addFieldToQuery($field, array &$fields)
  237. {
  238. }
  239. }