/migrationmanager/services/MigrationManager_SectionsService.php

https://github.com/Firstborn/Craft-CMS-Migration-Manager · PHP · 320 lines · 224 code · 49 blank · 47 comment · 36 complexity · 5215b22ca6eac39d3a7e958edd5a17d3 MD5 · raw file

  1. <?php
  2. namespace Craft;
  3. /**
  4. * Class MigrationManager_SectionsService
  5. */
  6. class MigrationManager_SectionsService extends MigrationManager_BaseMigrationService
  7. {
  8. /**
  9. * @var string
  10. */
  11. protected $source = 'section';
  12. /**
  13. * @var string
  14. */
  15. protected $destination = 'sections';
  16. /**
  17. * {@inheritdoc}
  18. */
  19. public function exportItem($id, $fullExport = false)
  20. {
  21. $section = craft()->sections->getSectionById($id);
  22. if (!$section) {
  23. return false;
  24. }
  25. $newSection = [
  26. 'name' => $section->attributes['name'],
  27. 'handle' => $section->attributes['handle'],
  28. 'type' => $section->attributes['type'],
  29. 'enableVersioning' => $section->attributes['enableVersioning'],
  30. 'hasUrls' => $section->attributes['hasUrls'],
  31. 'template' => $section->attributes['template'],
  32. 'maxLevels' => $section->attributes['maxLevels'],
  33. ];
  34. $this->addManifest($section->attributes['handle']);
  35. $locales = $section->getLocales();
  36. if ((bool)$section->attributes['hasUrls'] === false) {
  37. $newSection['locales'] = array();
  38. foreach ($locales as $localeId => $attributes) {
  39. $newSection['locales'][$localeId] = $attributes['enabledByDefault'];
  40. }
  41. } else {
  42. $newSection['locales'] = array();
  43. foreach ($locales as $localeId => $attributes) {
  44. $newSection['locales'][$localeId] = [
  45. 'locale' => $attributes->locale,
  46. 'urlFormat' => $attributes->urlFormat,
  47. 'nestedUrlFormat' => $attributes->nestedUrlFormat,
  48. 'enabledByDefault' => $attributes->enabledByDefault,
  49. ];
  50. }
  51. }
  52. $newSection['entrytypes'] = array();
  53. $sectionEntryTypes = $section->getEntryTypes();
  54. foreach ($sectionEntryTypes as $entryType) {
  55. $newEntryType = [
  56. 'sectionHandle' => $section->attributes['handle'],
  57. 'hasTitleField' => $entryType->attributes['hasTitleField'],
  58. 'titleLabel' => $entryType->attributes['titleLabel'],
  59. 'titleFormat' => $entryType->attributes['titleFormat'],
  60. 'name' => $entryType->attributes['name'],
  61. 'handle' => $entryType->attributes['handle'],
  62. 'fieldLayout' => array(),
  63. 'requiredFields' => array(),
  64. ];
  65. if ($newEntryType['titleFormat'] === null) {
  66. unset($newEntryType['titleFormat']);
  67. }
  68. $fieldLayout = $entryType->getFieldLayout();
  69. foreach ($fieldLayout->getTabs() as $tab) {
  70. $newEntryType['fieldLayout'][$tab->name] = array();
  71. foreach ($tab->getFields() as $tabField) {
  72. $newEntryType['fieldLayout'][$tab->name][] = craft()->fields->getFieldById($tabField->fieldId)->handle;
  73. if ($tabField->required) {
  74. $newEntryType['requiredFields'][] = craft()->fields->getFieldById($tabField->fieldId)->handle;
  75. }
  76. }
  77. }
  78. array_push($newSection['entrytypes'], $newEntryType);
  79. }
  80. // Fire an 'onExport' event
  81. $event = new Event($this, array(
  82. 'element' => $section,
  83. 'value' => $newSection
  84. ));
  85. if ($fullExport) {
  86. $this->onExport($event);
  87. }
  88. return $event->params['value'];
  89. }
  90. /**
  91. * {@inheritdoc}
  92. */
  93. public function importItem(array $data)
  94. {
  95. $result = true;
  96. $existing = craft()->sections->getSectionByHandle($data['handle']);
  97. if ($existing) {
  98. $this->mergeUpdates($data, $existing);
  99. }
  100. $section = $this->createModel($data);
  101. if ($section) {
  102. if (craft()->sections->saveSection($section)) {
  103. if (!$existing){
  104. //wipe out the default entry type
  105. $defaultEntryType = craft()->sections->getEntryTypesBySectionId($section->id);
  106. if ($defaultEntryType) {
  107. craft()->sections->deleteEntryTypeById($defaultEntryType[0]->id);
  108. }
  109. }
  110. //add entry types
  111. foreach ($data['entrytypes'] as $key => $newEntryType) {
  112. $existingType = $this->getSectionEntryTypeByHandle($newEntryType['handle'], $section->id);
  113. if ($existingType) {
  114. $this->mergeEntryType($newEntryType, $existingType);
  115. }
  116. $entryType = $this->createEntryType($newEntryType, $section);
  117. if (!craft()->sections->saveEntryType($entryType)) {
  118. $result = false;
  119. }
  120. }
  121. } else {
  122. $result = false;
  123. }
  124. } else {
  125. $result = false;
  126. }
  127. if ($result){
  128. // Fire an 'onImport' event
  129. $event = new Event($this, array(
  130. 'element' => $section,
  131. 'value' => $data
  132. ));
  133. $this->onImport($event);
  134. }
  135. return $result;
  136. }
  137. /**
  138. * {@inheritdoc}
  139. */
  140. public function createModel(array $data)
  141. {
  142. $section = new SectionModel();
  143. if (array_key_exists('id', $data)) {
  144. $section->id = $data['id'];
  145. }
  146. $section->name = $data['name'];
  147. $section->handle = $data['handle'];
  148. $section->type = $data['type'];
  149. $section->enableVersioning = $data['enableVersioning'];
  150. // Type-specific attributes
  151. if ($section->type == SectionType::Single) {
  152. $section->hasUrls = $data['hasUrls'] = true;
  153. } else {
  154. $section->hasUrls = $data['hasUrls'];
  155. }
  156. if ($section->hasUrls) {
  157. $section->template = $data['template'];
  158. } else {
  159. $section->template = $data['template'] = null;
  160. }
  161. if ($section->type == SectionType::Structure) {
  162. $section->maxLevels = $data['maxLevels'];
  163. }
  164. if (array_key_exists('locales', $data)) {
  165. $locales = array();
  166. foreach ($data['locales'] as $localeId => $localeAttributes) {
  167. //determine if locale exists
  168. if (in_array($localeId, craft()->i18n->getSiteLocaleIds())) {
  169. // depending if the migration had $section->hasUrls enabled,
  170. // then $localeAttributes will either hold an array of locale attributes
  171. // or will be a boolean indicating the locale default entry status
  172. if ($section->hasUrls) {
  173. $locales[$localeId] = new SectionLocaleModel(array(
  174. 'locale' => $localeId,
  175. 'enabledByDefault' => array_key_exists('enabledByDefault', $localeAttributes) ? $localeAttributes['enabledByDefault'] : true,
  176. 'urlFormat' => $localeAttributes['urlFormat'],
  177. 'nestedUrlFormat' => !empty($localeAttributes['nestedUrlFormat'])? $localeAttributes['nestedUrlFormat'] : '',
  178. ));
  179. } else {
  180. $locales[$localeId] = new SectionLocaleModel(array(
  181. 'locale' => $localeId,
  182. 'enabledByDefault' => $localeAttributes,
  183. ));
  184. }
  185. } else {
  186. $this->addError('missing locale: ' . $localeId . ' in section: ' . $section->handle . ', locale not defined in system');
  187. }
  188. }
  189. $section->setLocales($locales);
  190. }
  191. return $section;
  192. }
  193. /**
  194. * @param array $data
  195. * @param SectionModel $section
  196. *
  197. * @return EntryTypeModel
  198. */
  199. private function createEntryType($data, $section)
  200. {
  201. $entryType = new EntryTypeModel(array(
  202. 'sectionId' => $section->id,
  203. 'name' => $data['name'],
  204. 'handle' => $data['handle'],
  205. 'hasTitleField' => $data['hasTitleField'],
  206. 'titleLabel' => $data['titleLabel'],
  207. ));
  208. if (array_key_exists('titleFormat', $data)) {
  209. $entryType->titleFormat = $data['titleFormat'];
  210. }
  211. if (array_key_exists('id', $data)) {
  212. $entryType->id = $data['id'];
  213. }
  214. $requiredFields = array();
  215. if (array_key_exists('requiredFields', $data)) {
  216. foreach ($data['requiredFields'] as $handle) {
  217. $field = craft()->fields->getFieldByHandle($handle);
  218. if ($field) {
  219. $requiredFields[] = $field->id;
  220. }
  221. }
  222. }
  223. $layout = array();
  224. foreach ($data['fieldLayout'] as $key => $fields) {
  225. $fieldIds = array();
  226. foreach ($fields as $field) {
  227. $existingField = craft()->fields->getFieldByHandle($field);
  228. if ($existingField) {
  229. $fieldIds[] = $existingField->id;
  230. }
  231. }
  232. $layout[$key] = $fieldIds;
  233. }
  234. $fieldLayout = craft()->fields->assembleLayout($layout, $requiredFields);
  235. $fieldLayout->type = ElementType::Entry;
  236. $entryType->fieldLayout = $fieldLayout;
  237. return $entryType;
  238. }
  239. /**
  240. * @param array $newSection
  241. * @param SectionModel $section
  242. */
  243. private function mergeUpdates(&$newSection, $section)
  244. {
  245. $newSection['id'] = $section->id;
  246. }
  247. /**
  248. * @param array $newEntryType
  249. * @param EntryTypeModel $entryType
  250. */
  251. private function mergeEntryType(&$newEntryType, $entryType)
  252. {
  253. $newEntryType['id'] = $entryType->id;
  254. }
  255. /**
  256. * @param string $handle
  257. * @param int $sectionId
  258. *
  259. * @return bool
  260. */
  261. private function getSectionEntryTypeByHandle($handle, $sectionId)
  262. {
  263. $entryTypes = craft()->sections->getEntryTypesBySectionId($sectionId);
  264. foreach ($entryTypes as $entryType) {
  265. if ($entryType->handle == $handle) {
  266. return $entryType;
  267. }
  268. }
  269. return false;
  270. }
  271. }