PageRenderTime 51ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/app/protected/modules/import/utils/sanitizers/RelatedModelNameOrIdValueTypeSanitizerUtil.php

https://bitbucket.org/andreustimm/zurmo
PHP | 286 lines | 205 code | 11 blank | 70 comment | 33 complexity | 0d5a870be8782fc6e719df1671db43f2 MD5 | raw file
Possible License(s): 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. /**
  37. * Sanitizer to handle attribute values that are possible a model name not just a model id.
  38. *
  39. * Override to accomodate a value type of 'ZURMO_MODEL_NAME'. This would represent a model 'name' attribute value
  40. * that can be used as a unique identifier to map to existing models. An example is when importing a contact, and
  41. * the account name is provided. If the name is found, then the contact will be connected to the existing account
  42. * otherwise a new account is created with the name provided.
  43. *
  44. */
  45. class RelatedModelNameOrIdValueTypeSanitizerUtil extends IdValueTypeSanitizerUtil
  46. {
  47. protected $maxNameLength;
  48. public static function getLinkedMappingRuleType()
  49. {
  50. return 'RelatedModelValueType';
  51. }
  52. /**
  53. * If a model id value is invalid, then continue importing the row
  54. */
  55. public static function shouldNotSaveModelOnSanitizingValueFailure()
  56. {
  57. return false;
  58. }
  59. /**
  60. * @param RedBean_OODBBean $rowBean
  61. * @throws NotSupportedException
  62. */
  63. public function analyzeByRow(RedBean_OODBBean $rowBean)
  64. {
  65. if ($rowBean->{$this->columnName} == null)
  66. {
  67. $found = false;
  68. }
  69. elseif ($this->mappingRuleData["type"] == RelatedModelValueTypeMappingRuleForm::ZURMO_MODEL_ID)
  70. {
  71. $found = $this->resolveFoundIdByValue($rowBean->{$this->columnName});
  72. }
  73. elseif ($this->mappingRuleData["type"] == RelatedModelValueTypeMappingRuleForm::ZURMO_MODEL_NAME)
  74. {
  75. try
  76. {
  77. $found = $this->resolveFoundNameByValue($rowBean);
  78. }
  79. catch (NotFoundException $e)
  80. {
  81. $found = null;
  82. }
  83. if ($found === null)
  84. {
  85. return;
  86. }
  87. }
  88. else
  89. {
  90. $found = $this->resolveFoundExternalSystemIdByValue($rowBean->{$this->columnName});
  91. }
  92. $this->resolveFindingModelDuringAnalysis($found, $rowBean);
  93. $this->resolveExternalSystemIdValueIsTooLong($rowBean);
  94. }
  95. protected function resolveFoundNameByValue(RedBean_OODBBean $rowBean)
  96. {
  97. $modelClassName = $this->attributeModelClassName;
  98. if (!method_exists($modelClassName, 'getByName'))
  99. {
  100. throw new NotSupportedException();
  101. }
  102. $modelsFound = $modelClassName::getByName($rowBean->{$this->columnName});
  103. if (count($modelsFound) == 0)
  104. {
  105. $found = false;
  106. if (strlen($rowBean->{$this->columnName}) > $this->maxNameLength)
  107. {
  108. $label = Zurmo::t('ImportModule', 'Value is too long.');
  109. $this->shouldSkipRow = true;
  110. $this->analysisMessages[] = $label;
  111. return null;
  112. }
  113. }
  114. else
  115. {
  116. $found = true;
  117. }
  118. return $found;
  119. }
  120. /**
  121. * Given a value that is either a zurmo id or an external system id, resolve that the
  122. * value is valid. The value presented can also be a 'name' value. If the name is not found as a model
  123. * in the system, then a new related model will be created using this name.
  124. * NOTE - If the related model has other required attributes that have no default values,
  125. * then there will be a problem saving this new model. This is too be resolved at some point.
  126. * If the value is not valid then an InvalidValueToSanitizeException is thrown.
  127. * @param mixed $value
  128. * @return sanitized value
  129. * @throws InvalidValueToSanitizeException
  130. * @throws NotFoundException
  131. * @throws NotSupportedException
  132. */
  133. public function sanitizeValue($value)
  134. {
  135. assert('is_string($this->attributeName) && $this->attributeName != "id"');
  136. if ($value == null)
  137. {
  138. return $value;
  139. }
  140. $modelClassName = $this->modelClassName;
  141. $relationModelClassName = $modelClassName::getRelationModelClassName($this->attributeName);
  142. if ($this->mappingRuleData["type"] == RelatedModelValueTypeMappingRuleForm::ZURMO_MODEL_ID)
  143. {
  144. try
  145. {
  146. if ((int)$value <= 0)
  147. {
  148. throw new NotFoundException();
  149. }
  150. return $relationModelClassName::getById((int)$value);
  151. }
  152. catch (NotFoundException $e)
  153. {
  154. throw new InvalidValueToSanitizeException(Zurmo::t('ImportModule', 'ID specified did not match any existing records.'));
  155. }
  156. }
  157. elseif ($this->mappingRuleData["type"] == RelatedModelValueTypeMappingRuleForm::EXTERNAL_SYSTEM_ID)
  158. {
  159. try
  160. {
  161. return static::getModelByExternalSystemIdAndModelClassName($value, $relationModelClassName);
  162. }
  163. catch (NotFoundException $e)
  164. {
  165. throw new InvalidValueToSanitizeException(Zurmo::t('ImportModule', 'Other ID specified did not match any existing records.'));
  166. }
  167. }
  168. else
  169. {
  170. if (!method_exists($relationModelClassName, 'getByName'))
  171. {
  172. throw new NotSupportedException();
  173. }
  174. try
  175. {
  176. $modelsFound = $relationModelClassName::getByName($value);
  177. if (!is_array($modelsFound))
  178. {
  179. $modelsFound = array($modelsFound);
  180. }
  181. }
  182. catch (NotFoundException $e)
  183. {
  184. $modelsFound = array();
  185. }
  186. if (count($modelsFound) == 0)
  187. {
  188. $newRelatedModel = new $relationModelClassName();
  189. $newRelatedModel->name = $value;
  190. $saved = $newRelatedModel->save();
  191. //Todo: need to handle this more gracefully. The use case where a related model is needed to be made
  192. //but there are some required attributes that do not have defaults. As a result, since those extra
  193. //defaults cannot be specified at this time, an error must be thrown.
  194. if (!$saved)
  195. {
  196. throw new InvalidValueToSanitizeException(Zurmo::t('ImportModule',
  197. 'A new related model could not be created because there are unspecified required attributes on that related model.'));
  198. }
  199. else
  200. {
  201. $this->importSanitizeResultsUtil->addRelatedModelMessage(
  202. Zurmo::t('ImportModule', '{modelLabel} saved correctly: {linkToModel}',
  203. array('{modelLabel}' => $newRelatedModel->getModelLabelByTypeAndLanguage('Singular'),
  204. '{linkToModel}' => ImportUtil::resolveLinkMessageToModel($newRelatedModel))));
  205. }
  206. return $newRelatedModel;
  207. }
  208. else
  209. {
  210. return $modelsFound[0];
  211. }
  212. }
  213. }
  214. /**
  215. * Ensure the type is an accepted type.
  216. * @param unknown_type integer
  217. */
  218. protected function ensureTypeValueIsValid($type)
  219. {
  220. assert('$type == RelatedModelValueTypeMappingRuleForm::ZURMO_MODEL_ID ||
  221. $type == RelatedModelValueTypeMappingRuleForm::EXTERNAL_SYSTEM_ID ||
  222. $type == RelatedModelValueTypeMappingRuleForm::ZURMO_MODEL_NAME');
  223. }
  224. protected function assertMappingRuleDataIsValid()
  225. {
  226. assert('$this->mappingRuleData["type"] == RelatedModelValueTypeMappingRuleForm::ZURMO_MODEL_ID ||
  227. $this->mappingRuleData["type"] == RelatedModelValueTypeMappingRuleForm::EXTERNAL_SYSTEM_ID ||
  228. $this->mappingRuleData["type"] == RelatedModelValueTypeMappingRuleForm::ZURMO_MODEL_NAME');
  229. }
  230. protected function init()
  231. {
  232. parent::init();
  233. $attributeModelClassName = $this->attributeModelClassName;
  234. $model = new $attributeModelClassName(false);
  235. if ($this->mappingRuleData["type"] == RelatedModelValueTypeMappingRuleForm::ZURMO_MODEL_NAME &&
  236. !$model->isAttribute("name"))
  237. {
  238. throw new NotSupportedException();
  239. }
  240. if ($this->mappingRuleData["type"] == RelatedModelValueTypeMappingRuleForm::ZURMO_MODEL_NAME)
  241. {
  242. $this->maxNameLength = StringValidatorHelper::getMaxLengthByModelAndAttributeName($model, 'name');
  243. }
  244. }
  245. protected function resolveForFoundModel()
  246. {
  247. if ($this->mappingRuleData["type"] == RelatedModelValueTypeMappingRuleForm::ZURMO_MODEL_NAME)
  248. {
  249. $label = Zurmo::t('ImportModule', 'Is an existing record and will be linked.');
  250. $this->analysisMessages[] = $label;
  251. }
  252. }
  253. protected function resolveForUnfoundModel(RedBean_OODBBean $rowBean)
  254. {
  255. if ($this->mappingRuleData["type"] == RelatedModelValueTypeMappingRuleForm::ZURMO_MODEL_ID ||
  256. $this->mappingRuleData["type"] == RelatedModelValueTypeMappingRuleForm::EXTERNAL_SYSTEM_ID)
  257. {
  258. if ($rowBean->{$this->columnName} != null)
  259. {
  260. $label = Zurmo::t('ImportModule', 'Was not found and this row will be skipped during import.');
  261. $this->shouldSkipRow = true;
  262. $this->analysisMessages[] = $label;
  263. }
  264. }
  265. else
  266. {
  267. if ($rowBean->{$this->columnName} != null)
  268. {
  269. $label = Zurmo::t('ImportModule', 'Was not found and will create a new record during import.');
  270. $this->analysisMessages[] = $label;
  271. }
  272. }
  273. }
  274. }
  275. ?>