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->importEditors()
88 ->importBlockContent();
94 * Other users are created as their content is imported. However, editors
95 * don't have their own content so are created here instead.
99 protected function importEditors() {
100 $user_storage = $this->entityTypeManager->getStorage('user');
105 foreach ($editors as $name) {
106 $user = $user_storage->create([
109 'roles' => ['editor'],
110 'mail' => mb_strtolower(str_replace(' ', '.', $name)) . '@example.com',
112 $user->enforceIsNew();
114 $this->storeCreatedContentUuids([$user->uuid() => 'user']);
124 protected function importArticles() {
125 $module_path = $this->moduleHandler->getModule('demo_umami_content')
127 if (($handle = fopen($module_path . '/default_content/articles.csv', "r")) !== FALSE) {
129 $header = fgetcsv($handle);
130 while (($data = fgetcsv($handle)) !== FALSE) {
131 $data = array_combine($header, $data);
135 'title' => $data['title'],
136 'moderation_state' => 'published',
138 // Fields mapping starts.
140 if (!empty($data['body'])) {
141 $body_path = $module_path . '/default_content/article_body/' . $data['body'];
142 $body = file_get_contents($body_path);
143 if ($body !== FALSE) {
144 $values['body'] = [['value' => $body, 'format' => 'basic_html']];
147 // Set node alias if exists.
148 if (!empty($data['slug'])) {
149 $values['path'] = [['alias' => '/' . $data['slug']]];
151 // Set field_tags if exists.
152 if (!empty($data['tags'])) {
153 $values['field_tags'] = [];
154 $tags = explode(',', $data['tags']);
155 foreach ($tags as $term) {
156 $values['field_tags'][] = ['target_id' => $this->getTerm($term)];
159 // Set article author.
160 if (!empty($data['author'])) {
161 $values['uid'] = $this->getUser($data['author']);
164 if (!empty($data['image'])) {
165 $path = $module_path . '/default_content/images/' . $data['image'];
166 $values['field_image'] = [
167 'target_id' => $this->createFileEntity($path),
168 'alt' => $data['alt'],
173 $node = $this->entityTypeManager->getStorage('node')->create($values);
175 $uuids[$node->uuid()] = 'node';
177 $this->storeCreatedContentUuids($uuids);
188 protected function importRecipes() {
189 $module_path = $this->moduleHandler->getModule('demo_umami_content')->getPath();
191 if (($handle = fopen($module_path . '/default_content/recipes.csv', "r")) !== FALSE) {
192 $header = fgetcsv($handle);
194 while (($data = fgetcsv($handle)) !== FALSE) {
195 $data = array_combine($header, $data);
199 'title' => $data['title'],
200 'moderation_state' => 'published',
202 // Set article author.
203 if (!empty($data['author'])) {
204 $values['uid'] = $this->getUser($data['author']);
206 // Set node alias if exists.
207 if (!empty($data['slug'])) {
208 $values['path'] = [['alias' => '/' . $data['slug']]];
210 // Set field_image field.
211 if (!empty($data['image'])) {
212 $image_path = $module_path . '/default_content/images/' . $data['image'];
213 $values['field_image'] = [
214 'target_id' => $this->createFileEntity($image_path),
215 'alt' => $data['alt'],
218 // Set field_summary Field.
219 if (!empty($data['summary'])) {
220 $values['field_summary'] = [['value' => $data['summary'], 'format' => 'basic_html']];
222 // Set field_recipe_category if exists.
223 if (!empty($data['recipe_category'])) {
224 $values['field_recipe_category'] = [];
225 $tags = array_filter(explode(',', $data['recipe_category']));
226 foreach ($tags as $term) {
227 $values['field_recipe_category'][] = ['target_id' => $this->getTerm($term, 'recipe_category')];
230 // Set field_preparation_time Field.
231 if (!empty($data['preparation_time'])) {
232 $values['field_preparation_time'] = [['value' => $data['preparation_time']]];
234 // Set field_cooking_time Field.
235 if (!empty($data['cooking_time'])) {
236 $values['field_cooking_time'] = [['value' => $data['cooking_time']]];
238 // Set field_difficulty Field.
239 if (!empty($data['difficulty'])) {
240 $values['field_difficulty'] = $data['difficulty'];
242 // Set field_number_of_servings Field.
243 if (!empty($data['number_of_servings'])) {
244 $values['field_number_of_servings'] = [['value' => $data['number_of_servings']]];
246 // Set field_ingredients Field.
247 if (!empty($data['ingredients'])) {
248 $ingredients = explode(',', $data['ingredients']);
249 $values['field_ingredients'] = [];
250 foreach ($ingredients as $ingredient) {
251 $values['field_ingredients'][] = ['value' => $ingredient];
254 // Set field_recipe_instruction Field.
255 if (!empty($data['recipe_instruction'])) {
256 $recipe_instruction_path = $module_path . '/default_content/recipe_instructions/' . $data['recipe_instruction'];
257 $recipe_instructions = file_get_contents($recipe_instruction_path);
258 if ($recipe_instructions !== FALSE) {
259 $values['field_recipe_instruction'] = [['value' => $recipe_instructions, 'format' => 'basic_html']];
262 // Set field_tags if exists.
263 if (!empty($data['tags'])) {
264 $values['field_tags'] = [];
265 $tags = array_filter(explode(',', $data['tags']));
266 foreach ($tags as $term) {
267 $values['field_tags'][] = ['target_id' => $this->getTerm($term)];
271 $node = $this->entityTypeManager->getStorage('node')->create($values);
273 $uuids[$node->uuid()] = 'node';
275 $this->storeCreatedContentUuids($uuids);
286 protected function importPages() {
287 if (($handle = fopen($this->moduleHandler->getModule('demo_umami_content')->getPath() . '/default_content/pages.csv', "r")) !== FALSE) {
288 $headers = fgetcsv($handle);
290 while (($data = fgetcsv($handle)) !== FALSE) {
291 $data = array_combine($headers, $data);
296 'title' => $data['title'],
297 'moderation_state' => 'published',
299 // Fields mapping starts.
301 if (!empty($data['body'])) {
302 $values['body'] = [['value' => $data['body'], 'format' => 'basic_html']];
304 // Set node alias if exists.
305 if (!empty($data['slug'])) {
306 $values['path'] = [['alias' => '/' . $data['slug']]];
308 // Set article author.
309 if (!empty($data['author'])) {
310 $values['uid'] = $this->getUser($data['author']);
314 $node = $this->entityTypeManager->getStorage('node')->create($values);
316 $uuids[$node->uuid()] = 'node';
318 $this->storeCreatedContentUuids($uuids);
325 * Imports block content entities.
329 protected function importBlockContent() {
330 $module_path = $this->moduleHandler->getModule('demo_umami_content')->getPath();
331 $block_content_entities = [
332 'umami_recipes_banner' => [
333 'uuid' => '4c7d58a3-a45d-412d-9068-259c57e40541',
334 'info' => 'Umami Recipes Banner',
335 'type' => 'banner_block',
337 'value' => 'Super easy vegetarian pasta bake',
339 'field_content_link' => [
340 'uri' => 'internal:' . call_user_func(function () {
341 $nodes = $this->entityTypeManager->getStorage('node')->loadByProperties(['title' => 'Super easy vegetarian pasta bake']);
342 $node = reset($nodes);
343 return $this->aliasManager->getAliasByPath('/node/' . $node->id());
345 'title' => 'Super easy vegetarian pasta bake',
348 '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.',
350 'field_banner_image' => [
351 'target_id' => $this->createFileEntity($module_path . '/default_content/images/veggie-pasta-bake-hero-umami.jpg'),
352 'alt' => 'Mouth watering vegetarian pasta bake with rich tomato sauce and cheese toppings',
355 'umami_disclaimer' => [
356 'uuid' => '9b4dcd67-99f3-48d0-93c9-2c46648b29de',
357 'info' => 'Umami disclaimer',
358 'type' => 'disclaimer_block',
359 'field_disclaimer' => [
360 'value' => '<strong>Umami Magazine & Umami Publications</strong> is a fictional magazine and publisher for illustrative purposes only.',
361 'format' => 'basic_html',
363 'field_copyright' => [
364 'value' => '© 2018 Terms & Conditions',
365 'format' => 'basic_html',
368 'umami_footer_promo' => [
369 'uuid' => '924ab293-8f5f-45a1-9c7f-2423ae61a241',
370 'info' => 'Umami footer promo',
371 'type' => 'footer_promo_block',
373 'value' => 'Umami Food Magazine',
376 'value' => 'Skills and know-how. Magazine exclusive articles, recipes and plenty of reasons to get your copy today.',
378 'field_content_link' => [
379 'uri' => 'internal:' . call_user_func(function () {
380 $nodes = $this->entityTypeManager->getStorage('node')->loadByProperties(['title' => 'About Umami']);
381 $node = reset($nodes);
382 return $this->aliasManager->getAliasByPath('/node/' . $node->id());
384 'title' => 'Find out more',
386 'field_promo_image' => [
387 'target_id' => $this->createFileEntity($module_path . '/default_content/images/umami-bundle.png'),
388 'alt' => '3 issue bundle of the Umami food magazine',
393 // Create block content.
394 foreach ($block_content_entities as $values) {
395 $block_content = $this->entityTypeManager->getStorage('block_content')->create($values);
396 $block_content->save();
397 $this->storeCreatedContentUuids([$block_content->uuid() => 'block_content']);
403 * Deletes any content imported by this module.
407 public function deleteImportedContent() {
408 $uuids = $this->state->get('demo_umami_content_uuids', []);
409 $by_entity_type = array_reduce(array_keys($uuids), function ($carry, $uuid) use ($uuids) {
410 $entity_type_id = $uuids[$uuid];
411 $carry[$entity_type_id][] = $uuid;
414 foreach ($by_entity_type as $entity_type_id => $entity_uuids) {
415 $storage = $this->entityTypeManager->getStorage($entity_type_id);
416 $entities = $storage->loadByProperties(['uuid' => $entity_uuids]);
417 $storage->delete($entities);
423 * Looks up a user by name, if it is missing the user is created.
425 * @param string $name
431 protected function getUser($name) {
432 $user_storage = $this->entityTypeManager->getStorage('user');
433 $users = $user_storage->loadByProperties(['name' => $name]);;
435 // Creating user without any password.
436 $user = $user_storage->create([
439 'roles' => ['author'],
440 'mail' => mb_strtolower(str_replace(' ', '.', $name)) . '@example.com',
442 $user->enforceIsNew();
444 $this->storeCreatedContentUuids([$user->uuid() => 'user']);
447 $user = reset($users);
452 * Looks up a term by name, if it is missing the term is created.
454 * @param string $term_name
456 * @param string $vocabulary_id
462 protected function getTerm($term_name, $vocabulary_id = 'tags') {
463 $term_name = trim($term_name);
464 $term_storage = $this->entityTypeManager->getStorage('taxonomy_term');
465 $terms = $term_storage->loadByProperties([
466 'name' => $term_name,
467 'vid' => $vocabulary_id,
470 $term = $term_storage->create([
471 'name' => $term_name,
472 'vid' => $vocabulary_id,
473 'path' => ['alias' => '/' . Html::getClass($vocabulary_id) . '/' . Html::getClass($term_name)],
476 $this->storeCreatedContentUuids([$term->uuid() => 'taxonomy_term']);
479 $term = reset($terms);
484 * Creates a file entity based on an image path.
486 * @param string $path
492 protected function createFileEntity($path) {
493 $uri = $this->fileUnmanagedCopy($path);
494 $file = $this->entityTypeManager->getStorage('file')->create([
499 $this->storeCreatedContentUuids([$file->uuid() => 'file']);
504 * Stores record of content entities created by this import.
506 * @param array $uuids
507 * Array of UUIDs where the key is the UUID and the value is the entity
510 protected function storeCreatedContentUuids(array $uuids) {
511 $uuids = $this->state->get('demo_umami_content_uuids', []) + $uuids;
512 $this->state->set('demo_umami_content_uuids', $uuids);
516 * Wrapper around file_unmanaged_copy().
518 * @param string $path
521 * @return string|false
522 * The path to the new file, or FALSE in the event of an error.
524 protected function fileUnmanagedCopy($path) {
525 $filename = basename($path);
526 return file_unmanaged_copy($path, 'public://' . $filename, FILE_EXISTS_REPLACE);