3 namespace Drupal\demo_umami_content;
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;
14 * Defines a helper class for importing default content.
17 * This code is only for use by the Umami demo: Content module.
19 class InstallHelper implements ContainerInjectionInterface {
22 * The path alias manager.
24 * @var \Drupal\Core\Path\AliasManagerInterface
26 protected $aliasManager;
29 * Entity type manager.
31 * @var \Drupal\Core\Entity\EntityTypeManagerInterface
33 protected $entityTypeManager;
38 * @var \Drupal\Core\Extension\ModuleHandlerInterface
40 protected $moduleHandler;
45 * @var \Drupal\Core\State\StateInterface
50 * Constructs a new InstallHelper object.
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
58 * @param \Drupal\Core\State\StateInterface $state
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;
71 public static function create(ContainerInterface $container) {
73 $container->get('path.alias_manager'),
74 $container->get('entity_type.manager'),
75 $container->get('module_handler'),
76 $container->get('state')
81 * Imports default contents.
83 public function importContent() {
84 $this->importArticles()
87 ->importBlockContent();
95 protected function importArticles() {
96 $module_path = $this->moduleHandler->getModule('demo_umami_content')
98 if (($handle = fopen($module_path . '/default_content/articles.csv', "r")) !== FALSE) {
100 $header = fgetcsv($handle);
101 while (($data = fgetcsv($handle)) !== FALSE) {
102 $data = array_combine($header, $data);
106 'title' => $data['title'],
108 // Fields mapping starts.
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']];
117 // Set node alias if exists.
118 if (!empty($data['slug'])) {
119 $values['path'] = [['alias' => '/' . $data['slug']]];
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)];
129 // Set article author.
130 if (!empty($data['author'])) {
131 $values['uid'] = $this->getUser($data['author']);
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'],
143 $node = $this->entityTypeManager->getStorage('node')->create($values);
145 $uuids[$node->uuid()] = 'node';
147 $this->storeCreatedContentUuids($uuids);
158 protected function importRecipes() {
159 $module_path = $this->moduleHandler->getModule('demo_umami_content')->getPath();
161 if (($handle = fopen($module_path . '/default_content/recipes.csv', "r")) !== FALSE) {
162 $header = fgetcsv($handle);
164 while (($data = fgetcsv($handle)) !== FALSE) {
165 $data = array_combine($header, $data);
169 'title' => $data['title'],
171 // Set article author.
172 if (!empty($data['author'])) {
173 $values['uid'] = $this->getUser($data['author']);
174 $values['field_author'] = $values['uid'];
176 // Set node alias if exists.
177 if (!empty($data['slug'])) {
178 $values['path'] = [['alias' => '/' . $data['slug']]];
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'],
188 // Set field_summary Field.
189 if (!empty($data['summary'])) {
190 $values['field_summary'] = [['value' => $data['summary'], 'format' => 'basic_html']];
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')];
200 // Set field_preparation_time Field.
201 if (!empty($data['preparation_time'])) {
202 $values['field_preparation_time'] = [['value' => $data['preparation_time']]];
204 // Set field_cooking_time Field.
205 if (!empty($data['cooking_time'])) {
206 $values['field_cooking_time'] = [['value' => $data['cooking_time']]];
208 // Set field_difficulty Field.
209 if (!empty($data['difficulty'])) {
210 $values['field_difficulty'] = $data['difficulty'];
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']]];
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];
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']];
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)];
241 $node = $this->entityTypeManager->getStorage('node')->create($values);
243 $uuids[$node->uuid()] = 'node';
245 $this->storeCreatedContentUuids($uuids);
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);
260 while (($data = fgetcsv($handle)) !== FALSE) {
261 $data = array_combine($headers, $data);
266 'title' => $data['title'],
268 // Fields mapping starts.
270 if (!empty($data['body'])) {
271 $values['body'] = [['value' => $data['body'], 'format' => 'basic_html']];
273 // Set node alias if exists.
274 if (!empty($data['slug'])) {
275 $values['path'] = [['alias' => '/' . $data['slug']]];
277 // Set article author.
278 if (!empty($data['author'])) {
279 $values['uid'] = $this->getUser($data['author']);
283 $node = $this->entityTypeManager->getStorage('node')->create($values);
285 $uuids[$node->uuid()] = 'node';
287 $this->storeCreatedContentUuids($uuids);
294 * Imports block content entities.
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',
306 'value' => 'Super easy vegetarian pasta bake',
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());
314 'title' => 'Super easy vegetarian pasta bake',
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.',
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',
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',
332 'field_copyright' => [
333 'value' => '© 2018 Terms & Conditions',
334 'format' => 'basic_html',
337 'umami_footer_promo' => [
338 'uuid' => '924ab293-8f5f-45a1-9c7f-2423ae61a241',
339 'info' => 'Umami footer promo',
340 'type' => 'footer_promo_block',
342 'value' => 'Umami Food Magazine',
345 'value' => 'Skills and know-how. Magazine exclusive articles, recipes and plenty of reasons to get your copy today.',
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());
353 'title' => 'Find out more',
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',
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']);
372 * Deletes any content imported by this module.
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;
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);
392 * Looks up a user by name, if it is missing the user is created.
394 * @param string $name
400 protected function getUser($name) {
401 $user_storage = $this->entityTypeManager->getStorage('user');
402 $users = $user_storage->loadByProperties(['name' => $name]);;
404 // Creating user without any email/password.
405 $user = $user_storage->create([
409 $user->enforceIsNew();
411 $this->storeCreatedContentUuids([$user->uuid() => 'user']);
414 $user = reset($users);
419 * Looks up a term by name, if it is missing the term is created.
421 * @param string $term_name
423 * @param string $vocabulary_id
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,
437 $term = $term_storage->create([
438 'name' => $term_name,
439 'vid' => $vocabulary_id,
440 'path' => ['alias' => '/' . Html::getClass($vocabulary_id) . '/' . Html::getClass($term_name)],
443 $this->storeCreatedContentUuids([$term->uuid() => 'taxonomy_term']);
446 $term = reset($terms);
451 * Creates a file entity based on an image path.
453 * @param string $path
459 protected function createFileEntity($path) {
460 $uri = $this->fileUnmanagedCopy($path);
461 $file = $this->entityTypeManager->getStorage('file')->create([
466 $this->storeCreatedContentUuids([$file->uuid() => 'file']);
471 * Stores record of content entities created by this import.
473 * @param array $uuids
474 * Array of UUIDs where the key is the UUID and the value is the entity
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);
483 * Wrapper around file_unmanaged_copy().
485 * @param string $path
488 * @return string|false
489 * The path to the new file, or FALSE in the event of an error.
491 protected function fileUnmanagedCopy($path) {
492 $filename = basename($path);
493 return file_unmanaged_copy($path, 'public://' . $filename, FILE_EXISTS_REPLACE);