PageRenderTime 39ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/app/protected/modules/zurmo/models/Item.php

https://bitbucket.org/zurmo/zurmo/
PHP | 350 lines | 244 code | 30 blank | 76 comment | 32 complexity | 28196b448174a110355365ac6c9fb88a MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, GPL-2.0, LGPL-3.0, LGPL-2.1, BSD-2-Clause
  1. <?php
  2. /*********************************************************************************
  3. * Zurmo is a customer relationship management program developed by
  4. * Zurmo, Inc. Copyright (C) 2015 Zurmo Inc.
  5. *
  6. * Zurmo is free software; you can redistribute it and/or modify it under
  7. * the terms of the GNU Affero General Public License version 3 as published by the
  8. * Free Software Foundation with the addition of the following permission added
  9. * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
  10. * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
  11. * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
  12. *
  13. * Zurmo is distributed in the hope that it will be useful, but WITHOUT
  14. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  15. * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public License along with
  19. * this program; if not, see http://www.gnu.org/licenses or write to the Free
  20. * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  21. * 02110-1301 USA.
  22. *
  23. * You can contact Zurmo, Inc. with a mailing address at 27 North Wacker Drive
  24. * Suite 370 Chicago, IL 60606. or at email address contact@zurmo.com.
  25. *
  26. * The interactive user interfaces in original and modified versions
  27. * of this program must display Appropriate Legal Notices, as required under
  28. * Section 5 of the GNU Affero General Public License version 3.
  29. *
  30. * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
  31. * these Appropriate Legal Notices must retain the display of the Zurmo
  32. * logo and Zurmo copyright notice. If the display of the logo is not reasonably
  33. * feasible for technical reasons, the Appropriate Legal Notices must display the words
  34. * "Copyright Zurmo Inc. 2015. All rights reserved".
  35. ********************************************************************************/
  36. class Item extends CustomFieldsModel
  37. {
  38. private $insideOnModified;
  39. protected $isSetting = false;
  40. // On changing a member value the original value
  41. // is saved (ie: on change it again the original
  42. // value is not overwritten) so that on save the
  43. // changes can be written to the audit log.
  44. public $originalAttributeValues = array();
  45. /**
  46. * Should the model be audited. Override and set to false if you do not need to audit the Item.
  47. * @var bool
  48. */
  49. protected $isAudited = true;
  50. private $_workflowsToProcessAfterSave = array();
  51. private $_processWorkflowOnSave = true;
  52. public function onCreated()
  53. {
  54. $this->unrestrictedSet('createdDateTime', DateTimeUtil::convertTimestampToDbFormatDateTime(time()));
  55. $this->unrestrictedSet('modifiedDateTime', DateTimeUtil::convertTimestampToDbFormatDateTime(time()));
  56. }
  57. public function onModified()
  58. {
  59. if (!$this->insideOnModified)
  60. {
  61. $this->insideOnModified = true;
  62. if (!($this->unrestrictedGet('id') < 0 &&
  63. $this->getScenario() == 'importModel' &&
  64. array_key_exists('modifiedDateTime', $this->originalAttributeValues)) &&
  65. $this->getScenario() != 'doNotSetModifiedDateTimeOrUser')
  66. {
  67. $this->unrestrictedSet('modifiedDateTime', DateTimeUtil::convertTimestampToDbFormatDateTime(time()));
  68. }
  69. if (Yii::app()->user->userModel != null && Yii::app()->user->userModel->id > 0)
  70. {
  71. if (!($this->unrestrictedGet('id') < 0 &&
  72. $this->getScenario() == 'importModel' &&
  73. array_key_exists('modifiedByUser', $this->originalAttributeValues)) &&
  74. $this->getScenario() != 'doNotSetModifiedDateTimeOrUser')
  75. {
  76. $this->unrestrictedSet('modifiedByUser', Yii::app()->user->userModel);
  77. }
  78. }
  79. $this->insideOnModified = false;
  80. }
  81. }
  82. public function __set($attributeName, $value)
  83. {
  84. $this->isSetting = true;
  85. try
  86. {
  87. if (!$this->isSaving)
  88. {
  89. AuditUtil::saveOriginalAttributeValue($this, $attributeName, $value);
  90. }
  91. parent::__set($attributeName, $value);
  92. $this->isSetting = false;
  93. }
  94. catch (Exception $e)
  95. {
  96. $this->isSetting = false;
  97. throw $e;
  98. }
  99. }
  100. public function delete()
  101. {
  102. if ($this->isAudited)
  103. {
  104. AuditEvent::logAuditEvent('ZurmoModule', ZurmoModule::AUDIT_EVENT_ITEM_DELETED, strval($this), $this);
  105. }
  106. return parent::delete();
  107. }
  108. // Makes Item appear on the stack so that auditing can ensure
  109. // that things owned by Item are only saved by Item and not directly.
  110. public function save($runValidation = true, array $attributeNames = null)
  111. {
  112. return parent::save($runValidation, $attributeNames);
  113. }
  114. public function addWorkflowToProcessAfterSave(Workflow $workflow)
  115. {
  116. $this->_workflowsToProcessAfterSave[] = $workflow;
  117. }
  118. public function getWorkflowsToProcessAfterSave()
  119. {
  120. return $this->_workflowsToProcessAfterSave;
  121. }
  122. public function setDoNotProcessWorkflowOnSave()
  123. {
  124. $this->_processWorkflowOnSave = false;
  125. }
  126. public function setProcessWorkflowOnSave()
  127. {
  128. $this->_processWorkflowOnSave = true;
  129. }
  130. public function shouldProcessWorkflowOnSave()
  131. {
  132. return $this->_processWorkflowOnSave;
  133. }
  134. /**
  135. * @param string $attributeName
  136. * @param string $value
  137. * @return An
  138. */
  139. protected static function getByNameOrEquivalent($attributeName, $value)
  140. {
  141. assert('is_string($attributeName)');
  142. assert('is_string($value) && $value != ""');
  143. return static::getSubset(null, null, null, $attributeName . " = '" . DatabaseCompatibilityUtil::escape($value) . "'");
  144. }
  145. /**
  146. * Special handling of the import scenario. When you are importing a model, you can potentially set the
  147. * created/modified user/datetime which is normally not allowed since they are read-only attributes. This
  148. * logic helps to allow for this special use case.
  149. * @see RedBeanModel::beforeSave()
  150. */
  151. protected function beforeSave()
  152. {
  153. $this->isNewModel = $this->id < 0;
  154. if ($this->unrestrictedGet('id') < 0)
  155. {
  156. if ($this->getScenario() != 'importModel' ||
  157. ($this->getScenario() == 'importModel' && $this->createdByUser->id < 0))
  158. {
  159. if (Yii::app()->user->userModel != null && Yii::app()->user->userModel->id > 0)
  160. {
  161. $this->unrestrictedSet('createdByUser', Yii::app()->user->userModel);
  162. }
  163. }
  164. }
  165. if (parent::beforeSave())
  166. {
  167. if ($this->isModified())
  168. {
  169. $this->onModified();
  170. }
  171. return true;
  172. }
  173. else
  174. {
  175. return false;
  176. }
  177. }
  178. protected function afterSave()
  179. {
  180. parent::afterSave();
  181. if ($this->isAudited)
  182. {
  183. $this->logAuditEventsListForModified($this->isNewModel);
  184. AuditUtil::clearRelatedModelsOriginalAttributeValues($this);
  185. }
  186. $this->originalAttributeValues = array();
  187. $this->_workflowsToProcessAfterSave = array();
  188. $this->isNewModel = false; //reset.
  189. }
  190. protected function logAuditEventsListForModified($newModel)
  191. {
  192. if (!$newModel)
  193. {
  194. AuditUtil::logAuditEventsListForChangedAttributeValues($this);
  195. }
  196. }
  197. public function forgetOriginalAttributeValues()
  198. {
  199. $this->unrestrictedSet('originalAttributeValues', array());
  200. }
  201. public static function getDefaultMetadata()
  202. {
  203. $metadata = parent::getDefaultMetadata();
  204. $metadata[__CLASS__] = array(
  205. 'members' => array(
  206. 'createdDateTime',
  207. 'modifiedDateTime',
  208. ),
  209. 'relations' => array(
  210. 'createdByUser' => array(static::HAS_ONE, 'User', static::NOT_OWNED,
  211. static::LINK_TYPE_SPECIFIC, 'createdByUser'),
  212. 'modifiedByUser' => array(static::HAS_ONE, 'User', static::NOT_OWNED,
  213. static::LINK_TYPE_SPECIFIC, 'modifiedByUser'),
  214. ),
  215. 'rules' => array(
  216. array('createdDateTime', 'required'),
  217. array('createdDateTime', 'readOnly'),
  218. array('createdDateTime', 'type', 'type' => 'datetime'),
  219. array('createdByUser', 'readOnly'),
  220. array('modifiedDateTime', 'required'),
  221. array('modifiedDateTime', 'readOnly'),
  222. array('modifiedDateTime', 'type', 'type' => 'datetime'),
  223. array('modifiedByUser', 'readOnly'),
  224. ),
  225. 'elements' => array(
  226. 'createdDateTime' => 'DateTime',
  227. 'modifiedDateTime' => 'DateTime',
  228. ),
  229. );
  230. return $metadata;
  231. }
  232. public static function isTypeDeletable()
  233. {
  234. return false;
  235. }
  236. /**
  237. * Used for testing only. In scenarios where you need to test beforeDelete but can't because beforeDelete is
  238. * protected
  239. */
  240. public function testBeforeDelete()
  241. {
  242. $this->beforeDelete();
  243. }
  244. /**
  245. * See the yii documentation.
  246. */
  247. public function isAttributeAudited($attributeName)
  248. {
  249. assert("\$this->isAttribute('$attributeName')");
  250. assert('$attributeName != "id"');
  251. $attributeModelClassName = static::getAttributeModelClassName($attributeName);
  252. $metadata = static::getMetadata();
  253. if (isset($metadata[$attributeModelClassName]['noAudit']) &&
  254. in_array($attributeName, $metadata[$attributeModelClassName]['noAudit']))
  255. {
  256. return false;
  257. }
  258. return true;
  259. }
  260. /**
  261. * Override to handle the import scenario. During import you are allowed to externally set several read-only
  262. * attributes.
  263. * (non-PHPdoc)
  264. * @see RedBeanModel::isAllowedToSetReadOnlyAttribute()
  265. */
  266. public function isAllowedToSetReadOnlyAttribute($attributeName)
  267. {
  268. if ($this->getScenario() == 'importModel' || $this->getScenario() == 'searchModel')
  269. {
  270. if ($this->unrestrictedGet('id') > 0)
  271. {
  272. return false;
  273. }
  274. if ( in_array($attributeName, array('createdByUser', 'modifiedByUser', 'createdDateTime', 'modifiedDateTime')))
  275. {
  276. return true;
  277. }
  278. else
  279. {
  280. throw new NotSupportedException();
  281. }
  282. }
  283. return false;
  284. }
  285. /**
  286. * @return string of gamificationRulesType Override for a child class as needed.
  287. */
  288. public static function getGamificationRulesType()
  289. {
  290. return null;
  291. }
  292. protected static function translatedAttributeLabels($language)
  293. {
  294. return array_merge(parent::translatedAttributeLabels($language), array(
  295. 'createdByUser' => Zurmo::t('ZurmoModule', 'Created By User', array(), null, $language),
  296. 'createdDateTime' => Zurmo::t('ZurmoModule', 'Created Date Time', array(), null, $language),
  297. 'modifiedByUser' => Zurmo::t('ZurmoModule', 'Modified By User', array(), null, $language),
  298. 'modifiedDateTime' => Zurmo::t('ZurmoModule', 'Modified Date Time', array(), null, $language),
  299. ));
  300. }
  301. public static function getNonConfigurableAttributes()
  302. {
  303. $metadata = static::getDefaultMetadata();
  304. if (isset($metadata[get_called_class()]['nonConfigurableAttributes']))
  305. {
  306. return $metadata[get_called_class()]['nonConfigurableAttributes'];
  307. }
  308. return array();
  309. }
  310. /**
  311. * Gets by name
  312. * @param string $name
  313. * @return string
  314. */
  315. public static function getByName($name)
  316. {
  317. return self::getByNameOrEquivalent('name', $name);
  318. }
  319. }
  320. ?>