de061a6e369f8cd3da107a0de91fa9b31f9ad216
[yaffs-website] / web / core / profiles / demo_umami / modules / demo_umami_content / src / InstallHelper.php
1 <?php
2
3 namespace Drupal\demo_umami_content;
4
5 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
6 use Drupal\Core\Entity\EntityTypeManagerInterface;
7 use Drupal\Core\Extension\ModuleHandlerInterface;
8 use Drupal\Core\Path\AliasManagerInterface;
9 use Drupal\Core\State\StateInterface;
10 use Symfony\Component\DependencyInjection\ContainerInterface;
11 use Drupal\Component\Utility\Html;
12
13 /**
14  * Defines a helper class for importing default content.
15  *
16  * @internal
17  *   This code is only for use by the Umami demo: Content module.
18  */
19 class InstallHelper implements ContainerInjectionInterface {
20
21   /**
22    * The path alias manager.
23    *
24    * @var \Drupal\Core\Path\AliasManagerInterface
25    */
26   protected $aliasManager;
27
28   /**
29    * Entity type manager.
30    *
31    * @var \Drupal\Core\Entity\EntityTypeManagerInterface
32    */
33   protected $entityTypeManager;
34
35   /**
36    * Module handler.
37    *
38    * @var \Drupal\Core\Extension\ModuleHandlerInterface
39    */
40   protected $moduleHandler;
41
42   /**
43    * State.
44    *
45    * @var \Drupal\Core\State\StateInterface
46    */
47   protected $state;
48
49   /**
50    * Constructs a new InstallHelper object.
51    *
52    * @param \Drupal\Core\Path\AliasManagerInterface $aliasManager
53    *   The path alias manager.
54    * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
55    *   Entity type manager.
56    * @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler
57    *   Module handler.
58    * @param \Drupal\Core\State\StateInterface $state
59    *   State service.
60    */
61   public function __construct(AliasManagerInterface $aliasManager, EntityTypeManagerInterface $entityTypeManager, ModuleHandlerInterface $moduleHandler, StateInterface $state) {
62     $this->aliasManager = $aliasManager;
63     $this->entityTypeManager = $entityTypeManager;
64     $this->moduleHandler = $moduleHandler;
65     $this->state = $state;
66   }
67
68   /**
69    * {@inheritdoc}
70    */
71   public static function create(ContainerInterface $container) {
72     return new static(
73       $container->get('path.alias_manager'),
74       $container->get('entity_type.manager'),
75       $container->get('module_handler'),
76       $container->get('state')
77     );
78   }
79
80   /**
81    * Imports default contents.
82    */
83   public function importContent() {
84     $this->importArticles()
85       ->importRecipes()
86       ->importPages()
87       ->importBlockContent();
88   }
89
90   /**
91    * Imports articles.
92    *
93    * @return $this
94    */
95   protected function importArticles() {
96     $module_path = $this->moduleHandler->getModule('demo_umami_content')
97       ->getPath();
98     if (($handle = fopen($module_path . '/default_content/articles.csv', "r")) !== FALSE) {
99       $uuids = [];
100       $header = fgetcsv($handle);
101       while (($data = fgetcsv($handle)) !== FALSE) {
102         $data = array_combine($header, $data);
103         // Prepare content.
104         $values = [
105           'type' => 'article',
106           'title' => $data['title'],
107         ];
108         // Fields mapping starts.
109         // Set Body Field.
110         if (!empty($data['body'])) {
111           $body_path = $module_path . '/default_content/article_body/' . $data['body'];
112           $body = file_get_contents($body_path);
113           if ($body !== FALSE) {
114             $values['body'] = [['value' => $body, 'format' => 'basic_html']];
115           }
116         }
117         // Set node alias if exists.
118         if (!empty($data['slug'])) {
119           $values['path'] = [['alias' => '/' . $data['slug']]];
120         }
121         // Set field_tags if exists.
122         if (!empty($data['tags'])) {
123           $values['field_tags'] = [];
124           $tags = explode(',', $data['tags']);
125           foreach ($tags as $term) {
126             $values['field_tags'][] = ['target_id' => $this->getTerm($term)];
127           }
128         }
129         // Set article author.
130         if (!empty($data['author'])) {
131           $values['uid'] = $this->getUser($data['author']);
132         }
133         // Set Image field.
134         if (!empty($data['image'])) {
135           $path = $module_path . '/default_content/images/' . $data['image'];
136           $values['field_image'] = [
137             'target_id' => $this->createFileEntity($path),
138             'alt' => $data['alt'],
139           ];
140         }
141
142         // Create Node.
143         $node = $this->entityTypeManager->getStorage('node')->create($values);
144         $node->save();
145         $uuids[$node->uuid()] = 'node';
146       }
147       $this->storeCreatedContentUuids($uuids);
148       fclose($handle);
149     }
150     return $this;
151   }
152
153   /**
154    * Imports recipes.
155    *
156    * @return $this
157    */
158   protected function importRecipes() {
159     $module_path = $this->moduleHandler->getModule('demo_umami_content')->getPath();
160
161     if (($handle = fopen($module_path . '/default_content/recipes.csv', "r")) !== FALSE) {
162       $header = fgetcsv($handle);
163       $uuids = [];
164       while (($data = fgetcsv($handle)) !== FALSE) {
165         $data = array_combine($header, $data);
166         $values = [
167           'type' => 'recipe',
168           // Title field.
169           'title' => $data['title'],
170         ];
171         // Set article author.
172         if (!empty($data['author'])) {
173           $values['uid'] = $this->getUser($data['author']);
174           $values['field_author'] = $values['uid'];
175         }
176         // Set node alias if exists.
177         if (!empty($data['slug'])) {
178           $values['path'] = [['alias' => '/' . $data['slug']]];
179         }
180         // Set field_image field.
181         if (!empty($data['image'])) {
182           $image_path = $module_path . '/default_content/images/' . $data['image'];
183           $values['field_image'] = [
184             'target_id' => $this->createFileEntity($image_path),
185             'alt' => $data['alt'],
186           ];
187         }
188         // Set field_summary Field.
189         if (!empty($data['summary'])) {
190           $values['field_summary'] = [['value' => $data['summary'], 'format' => 'basic_html']];
191         }
192         // Set field_recipe_category if exists.
193         if (!empty($data['recipe_category'])) {
194           $values['field_recipe_category'] = [];
195           $tags = array_filter(explode(',', $data['recipe_category']));
196           foreach ($tags as $term) {
197             $values['field_recipe_category'][] = ['target_id' => $this->getTerm($term, 'recipe_category')];
198           }
199         }
200         // Set field_preparation_time Field.
201         if (!empty($data['preparation_time'])) {
202           $values['field_preparation_time'] = [['value' => $data['preparation_time']]];
203         }
204         // Set field_cooking_time Field.
205         if (!empty($data['cooking_time'])) {
206           $values['field_cooking_time'] = [['value' => $data['cooking_time']]];
207         }
208         // Set field_difficulty Field.
209         if (!empty($data['difficulty'])) {
210           $values['field_difficulty'] = $data['difficulty'];
211         }
212         // Set field_number_of_servings Field.
213         if (!empty($data['number_of_servings'])) {
214           $values['field_number_of_servings'] = [['value' => $data['number_of_servings']]];
215         }
216         // Set field_ingredients Field.
217         if (!empty($data['ingredients'])) {
218           $ingredients = explode(',', $data['ingredients']);
219           $values['field_ingredients'] = [];
220           foreach ($ingredients as $ingredient) {
221             $values['field_ingredients'][] = ['value' => $ingredient];
222           }
223         }
224         // Set field_recipe_instruction Field.
225         if (!empty($data['recipe_instruction'])) {
226           $recipe_instruction_path = $module_path . '/default_content/recipe_instructions/' . $data['recipe_instruction'];
227           $recipe_instructions = file_get_contents($recipe_instruction_path);
228           if ($recipe_instructions !== FALSE) {
229             $values['field_recipe_instruction'] = [['value' => $recipe_instructions, 'format' => 'basic_html']];
230           }
231         }
232         // Set field_tags if exists.
233         if (!empty($data['tags'])) {
234           $values['field_tags'] = [];
235           $tags = array_filter(explode(',', $data['tags']));
236           foreach ($tags as $term) {
237             $values['field_tags'][] = ['target_id' => $this->getTerm($term)];
238           }
239         }
240
241         $node = $this->entityTypeManager->getStorage('node')->create($values);
242         $node->save();
243         $uuids[$node->uuid()] = 'node';
244       }
245       $this->storeCreatedContentUuids($uuids);
246       fclose($handle);
247     }
248     return $this;
249   }
250
251   /**
252    * Imports pages.
253    *
254    * @return $this
255    */
256   protected function importPages() {
257     if (($handle = fopen($this->moduleHandler->getModule('demo_umami_content')->getPath() . '/default_content/pages.csv', "r")) !== FALSE) {
258       $headers = fgetcsv($handle);
259       $uuids = [];
260       while (($data = fgetcsv($handle)) !== FALSE) {
261         $data = array_combine($headers, $data);
262
263         // Prepare content.
264         $values = [
265           'type' => 'page',
266           'title' => $data['title'],
267         ];
268         // Fields mapping starts.
269         // Set Body Field.
270         if (!empty($data['body'])) {
271           $values['body'] = [['value' => $data['body'], 'format' => 'basic_html']];
272         }
273         // Set node alias if exists.
274         if (!empty($data['slug'])) {
275           $values['path'] = [['alias' => '/' . $data['slug']]];
276         }
277         // Set article author.
278         if (!empty($data['author'])) {
279           $values['uid'] = $this->getUser($data['author']);
280         }
281
282         // Create Node.
283         $node = $this->entityTypeManager->getStorage('node')->create($values);
284         $node->save();
285         $uuids[$node->uuid()] = 'node';
286       }
287       $this->storeCreatedContentUuids($uuids);
288       fclose($handle);
289     }
290     return $this;
291   }
292
293   /**
294    * Imports block content entities.
295    *
296    * @return $this
297    */
298   protected function importBlockContent() {
299     $module_path = $this->moduleHandler->getModule('demo_umami_content')->getPath();
300     $block_content_entities = [
301       'umami_recipes_banner' => [
302         'uuid' => '4c7d58a3-a45d-412d-9068-259c57e40541',
303         'info' => 'Umami Recipes Banner',
304         'type' => 'banner_block',
305         'field_title' => [
306           'value' => 'Super easy vegetarian pasta bake',
307         ],
308         'field_content_link' => [
309           'uri' => 'internal:' . call_user_func(function () {
310             $nodes = $this->entityTypeManager->getStorage('node')->loadByProperties(['title' => 'Super easy vegetarian pasta bake']);
311             $node = reset($nodes);
312             return $this->aliasManager->getAliasByPath('/node/' . $node->id());
313           }),
314           'title' => 'Super easy vegetarian pasta bake',
315         ],
316         'field_summary' => [
317           'value' => 'A wholesome pasta bake is the ultimate comfort food. This delicious bake is super quick to prepare and an ideal midweek meal for all the family.',
318         ],
319         'field_banner_image' => [
320           'target_id' => $this->createFileEntity($module_path . '/default_content/images/veggie-pasta-bake-hero-umami.jpg'),
321           'alt' => 'Mouth watering vegetarian pasta bake with rich tomato sauce and cheese toppings',
322         ],
323       ],
324       'umami_disclaimer' => [
325         'uuid' => '9b4dcd67-99f3-48d0-93c9-2c46648b29de',
326         'info' => 'Umami disclaimer',
327         'type' => 'disclaimer_block',
328         'field_disclaimer' => [
329           'value' => '<strong>Umami Magazine & Umami Publications</strong> is a fictional magazine and publisher for illustrative purposes only.',
330           'format' => 'basic_html',
331         ],
332         'field_copyright' => [
333           'value' => '&copy; 2018 Terms & Conditions',
334           'format' => 'basic_html',
335         ],
336       ],
337       'umami_footer_promo' => [
338         'uuid' => '924ab293-8f5f-45a1-9c7f-2423ae61a241',
339         'info' => 'Umami footer promo',
340         'type' => 'footer_promo_block',
341         'field_title' => [
342           'value' => 'Umami Food Magazine',
343         ],
344         'field_summary' => [
345           'value' => 'Skills and know-how. Magazine exclusive articles, recipes and plenty of reasons to get your copy today.',
346         ],
347         'field_content_link' => [
348           'uri' => 'internal:' . call_user_func(function () {
349             $nodes = $this->entityTypeManager->getStorage('node')->loadByProperties(['title' => 'About Umami']);
350             $node = reset($nodes);
351             return $this->aliasManager->getAliasByPath('/node/' . $node->id());
352           }),
353           'title' => 'Find out more',
354         ],
355         'field_promo_image' => [
356           'target_id' => $this->createFileEntity($module_path . '/default_content/images/umami-bundle.png'),
357           'alt' => '3 issue bundle of the Umami food magazine',
358         ],
359       ],
360     ];
361
362     // Create block content.
363     foreach ($block_content_entities as $values) {
364       $block_content = $this->entityTypeManager->getStorage('block_content')->create($values);
365       $block_content->save();
366       $this->storeCreatedContentUuids([$block_content->uuid() => 'block_content']);
367     }
368     return $this;
369   }
370
371   /**
372    * Deletes any content imported by this module.
373    *
374    * @return $this
375    */
376   public function deleteImportedContent() {
377     $uuids = $this->state->get('demo_umami_content_uuids', []);
378     $by_entity_type = array_reduce(array_keys($uuids), function ($carry, $uuid) use ($uuids) {
379       $entity_type_id = $uuids[$uuid];
380       $carry[$entity_type_id][] = $uuid;
381       return $carry;
382     }, []);
383     foreach ($by_entity_type as $entity_type_id => $entity_uuids) {
384       $storage = $this->entityTypeManager->getStorage($entity_type_id);
385       $entities = $storage->loadByProperties(['uuid' => $entity_uuids]);
386       $storage->delete($entities);
387     }
388     return $this;
389   }
390
391   /**
392    * Looks up a user by name, if it is missing the user is created.
393    *
394    * @param string $name
395    *   Username.
396    *
397    * @return int
398    *   User ID.
399    */
400   protected function getUser($name) {
401     $user_storage = $this->entityTypeManager->getStorage('user');
402     $users = $user_storage->loadByProperties(['name' => $name]);;
403     if (empty($users)) {
404       // Creating user without any email/password.
405       $user = $user_storage->create([
406         'name' => $name,
407         'status' => 1,
408       ]);
409       $user->enforceIsNew();
410       $user->save();
411       $this->storeCreatedContentUuids([$user->uuid() => 'user']);
412       return $user->id();
413     }
414     $user = reset($users);
415     return $user->id();
416   }
417
418   /**
419    * Looks up a term by name, if it is missing the term is created.
420    *
421    * @param string $term_name
422    *   Term name.
423    * @param string $vocabulary_id
424    *   Vocabulary ID.
425    *
426    * @return int
427    *   Term ID.
428    */
429   protected function getTerm($term_name, $vocabulary_id = 'tags') {
430     $term_name = trim($term_name);
431     $term_storage = $this->entityTypeManager->getStorage('taxonomy_term');
432     $terms = $term_storage->loadByProperties([
433       'name' => $term_name,
434       'vid' => $vocabulary_id,
435     ]);
436     if (!$terms) {
437       $term = $term_storage->create([
438         'name' => $term_name,
439         'vid' => $vocabulary_id,
440         'path' => ['alias' => '/' . Html::getClass($vocabulary_id) . '/' . Html::getClass($term_name)],
441       ]);
442       $term->save();
443       $this->storeCreatedContentUuids([$term->uuid() => 'taxonomy_term']);
444       return $term->id();
445     }
446     $term = reset($terms);
447     return $term->id();
448   }
449
450   /**
451    * Creates a file entity based on an image path.
452    *
453    * @param string $path
454    *   Image path.
455    *
456    * @return int
457    *   File ID.
458    */
459   protected function createFileEntity($path) {
460     $uri = $this->fileUnmanagedCopy($path);
461     $file = $this->entityTypeManager->getStorage('file')->create([
462       'uri' => $uri,
463       'status' => 1,
464     ]);
465     $file->save();
466     $this->storeCreatedContentUuids([$file->uuid() => 'file']);
467     return $file->id();
468   }
469
470   /**
471    * Stores record of content entities created by this import.
472    *
473    * @param array $uuids
474    *   Array of UUIDs where the key is the UUID and the value is the entity
475    *   type.
476    */
477   protected function storeCreatedContentUuids(array $uuids) {
478     $uuids = $this->state->get('demo_umami_content_uuids', []) + $uuids;
479     $this->state->set('demo_umami_content_uuids', $uuids);
480   }
481
482   /**
483    * Wrapper around file_unmanaged_copy().
484    *
485    * @param string $path
486    *   Path to image.
487    *
488    * @return string|false
489    *   The path to the new file, or FALSE in the event of an error.
490    */
491   protected function fileUnmanagedCopy($path) {
492     $filename = basename($path);
493     return file_unmanaged_copy($path, 'public://' . $filename, FILE_EXISTS_REPLACE);
494   }
495
496 }