Browse Source

Step 7: complete the Blog CRUD.

Frederic G. MARAND 7 years ago
parent
commit
d52c75d0cd
8 changed files with 226 additions and 68 deletions
  1. 1 0
      README.md
  2. 85 0
      blog.drush.inc
  3. 61 0
      dr8_zth.module
  4. 2 2
      dr8_zth.routing.yml
  5. 8 8
      src/Controller/BlogController.php
  6. 8 2
      src/Entity/Blog.php
  7. 38 56
      src/Form/BlogForm.php
  8. 23 0
      templates/blog.html.twig

+ 1 - 0
README.md

@@ -30,3 +30,4 @@ the following:
 5. Complete the `BlogType` CRUD by implementing the `BlogTypeForm`.
 6. Complete the implementation of the `Blog` collection route to show id, title,
   author, and operations.
+7. Complete the `Blog` CRUD by implementing the `BlogForm`.

+ 85 - 0
blog.drush.inc

@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * @file
+ * Drush commands for the blog module.
+ */
+
+use Drupal\dr8_zth\Entity\Blog;
+
+/**
+ * Implements hook_drush_command().
+ */
+function blog_drush_command() {
+  $ret['blog-create'] = [
+    'description' => 'Create a blog entity',
+  ];
+
+  $ret['blog-create-values'] = [
+    'description' => 'Create a blog entity with values',
+  ];
+
+  $ret['blog-delete'] = [
+    'description' => 'Delete a blog entity by its id',
+  ];
+
+  $ret['blog-load'] = [
+    'description' => 'Load a blog entity by its id',
+  ];
+
+  return $ret;
+}
+
+/**
+ * Command callback for blog-create.
+ */
+function drush_blog_create() {
+  $blog = Blog::create();
+  $blog->save();
+}
+
+/**
+ * Command callback for blog-create-values.
+ */
+function drush_blog_create_values() {
+  $values = [
+    'title' => 'Drupal user group',
+    'date' => (new \DateTime())->format(DATETIME_DATETIME_STORAGE_FORMAT),
+    'description' => [
+      'value' => '<p>The monthly meeting of Drupalists is happening today!</p>',
+      'format' => 'restricted_html',
+    ],
+  ];
+  $blog = Blog::create($values);
+  $blog->save();
+}
+
+/**
+ * Command callback for blog-delete.
+ *
+ * @param int $id
+ *   The id of a blog to delete.
+ */
+function drush_blog_delete($id) {
+  $blog = Blog::load($id);
+  if (!$blog) {
+    return;
+  }
+  $blog->delete();
+}
+
+/**
+ * Command callback for blog-delete.
+ *
+ * @param int $id
+ *   The id of a blog to load and display.
+ */
+function drush_blog_load($id) {
+  $blog = Blog::load($id);
+  if (!$blog) {
+    return;
+  }
+
+  echo "Blog id: " . $blog->id() . ", uuid: " . $blog->uuid() . "\n";
+  print_r($blog->toArray());
+}

+ 61 - 0
dr8_zth.module

@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * @file
+ * The blog module.
+ */
+
+use Drupal\Core\Render\Element;
+use Drupal\dr8_zth\Entity\Blog;
+
+/**
+ * Implements hook_theme().
+ */
+function dr8_zth_theme() {
+  return array(
+    'blog' => array(
+      'render element' => 'elements',
+    ),
+  );
+}
+
+/**
+ * Returns whether the current page is the page of the passed-in blog.
+ *
+ * @param \Drupal\dr8_zth\Entity\Blog $blog
+ *   A blog entity.
+ *
+ * @return bool
+ *   Is the current route the canonical route for the blog ?
+ */
+function dr8_zth_blog_is_page(Blog $blog) {
+  if (\Drupal::routeMatch()->getRouteName() == 'entity.blog.canonical' && $page_blog_id = \Drupal::routeMatch()->getRawParameter('blog')) {
+    return $page_blog_id == $blog->id();
+  }
+  return FALSE;
+}
+
+/**
+ * Implements hook_preprocess_blog().
+ */
+function template_preprocess_blog(&$variables) {
+  // Raise deep information to the root.
+  $variables['view_mode'] = $variables['elements']['#view_mode'];
+  $variables['blog'] = $variables['elements']['#blog'];
+
+  /** @var \Drupal\dr8_zth\BlogInterface $blog */
+  $blog = $variables['blog'];
+
+  $variables['url'] = $blog->toUrl()->toString();
+
+  // We use name here because that is what appears in the UI.
+  $variables['title'] = $variables['elements']['title'];
+  unset($variables['elements']['title']);
+  $variables['page'] = $variables['view_mode'] == 'full' && dr8_zth_blog_is_page($blog);
+
+  // Helpful $content variable for templates.
+  $variables['content'] = array();
+  foreach (Element::children($variables['elements']) as $key) {
+    $variables['content'][$key] = $variables['elements'][$key];
+  }
+}

+ 2 - 2
dr8_zth.routing.yml

@@ -11,10 +11,10 @@ entity.blog.canonical:
 entity.blog.add_form:
   path: '/admin/structure/blog/manage/{blog_type}/add'
   defaults:
-    _controller: '\Drupal\taxonomy\Controller\TaxonomyController::addForm'
+    _controller: '\Drupal\dr8_zth\Controller\BlogController::addForm'
     _title: 'Add blog'
   requirements:
-    _entity_create_access: 'blog:{taxonomy_vocabulary}'
+    _entity_create_access: 'blog:{blog_type}'
 
 entity.blog.edit_form:
   path: '/blog/{blog}/edit'

+ 8 - 8
src/Controller/BlogController.php

@@ -6,8 +6,6 @@ use Drupal\Component\Utility\Xss;
 use Drupal\Core\Controller\ControllerBase;
 use Drupal\dr8_zth\BlogInterface;
 use Drupal\dr8_zth\BlogTypeInterface;
-use Drupal\taxonomy\TermInterface;
-use Drupal\taxonomy\VocabularyInterface;
 
 /**
  * Provides route responses for dr8_zth.module.
@@ -17,15 +15,18 @@ class BlogController extends ControllerBase {
   /**
    * Returns a form to add a new term to a vocabulary.
    *
-   * @param \Drupal\taxonomy\VocabularyInterface $taxonomy_vocabulary
-   *   The vocabulary this term will be added to.
+   * @param \Drupal\dr8_zth\BlogTypeInterface $blog_type
+   *   The blog type this blog will be added to.
    *
    * @return array
    *   The taxonomy term add form.
    */
-  public function addForm(VocabularyInterface $taxonomy_vocabulary) {
-    $term = $this->entityManager()->getStorage('taxonomy_term')->create(array('vid' => $taxonomy_vocabulary->id()));
-    return $this->entityFormBuilder()->getForm($term);
+  public function addForm(BlogTypeInterface $blog_type) {
+    $term = $this->entityTypeManager()
+      ->getStorage('blog')
+      ->create(['type' => $blog_type->id()]);
+    return $this->entityFormBuilder()
+      ->getForm($term);
   }
 
   /**
@@ -52,7 +53,6 @@ class BlogController extends ControllerBase {
    */
   public function blogTitle(BlogInterface $blog) {
     $ret = ['#markup' => $blog->label(), '#allowed_tags' => Xss::getHtmlTagList()];
-    ksm($ret);
     return $ret;
   }
 

+ 8 - 2
src/Entity/Blog.php

@@ -50,7 +50,6 @@ use Drupal\Core\Entity\ContentEntityBase;
  *   field_ui_base_route = "entity.blog_type.edit_form",
  *   permission_granularity = "entity_type",
  *   links = {
- *     "add-form" = "/blog/add/{blog_type}",
  *     "add-page" = "/blog/add",
  *     "canonical" = "/blog/{blog}",
  *     "collection" = "/admin/content/blog",
@@ -65,10 +64,15 @@ use Drupal\Core\Entity\ContentEntityBase;
 class Blog extends ContentEntityBase implements BlogInterface {
 
   /**
+   * The id of the blog author.
+   *
    * @var \Drupal\user\Entity\User
    */
   protected $uid;
 
+  /**
+   * {@inheritdoc}
+   */
   public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
     $fields = parent::baseFieldDefinitions($entity_type);
     $fields['title'] = BaseFieldDefinition::create('string')
@@ -111,12 +115,14 @@ class Blog extends ContentEntityBase implements BlogInterface {
       ))
       ->setDisplayConfigurable('form', TRUE);
 
-    ksm($fields);
     return $fields;
   }
 
   /**
+   * Get the blog author.
+   *
    * @return \Drupal\user\Entity\User
+   *   The author user entity.
    */
   public function getAuthor() {
     return $this->get('uid')->entity;

+ 38 - 56
src/Form/BlogForm.php

@@ -2,31 +2,30 @@
 
 namespace Drupal\dr8_zth\Form;
 
-use Drupal\Core\Config\Entity\ConfigEntityStorageInterface;
 use Drupal\Core\Entity\ContentEntityForm;
-use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Entity\ContentEntityStorageInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
- * Class BlogTypeForm is the default add/edit form for BlogType entities.
+ * Class BlogForm is the default add/edit form for Blog entities.
  */
 class BlogForm extends ContentEntityForm {
 
   /**
    * The blog type storage.
    *
-   * @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface
+   * @var \Drupal\Core\Entity\ConfigEntityStorageInterface
    */
   protected $storage;
 
   /**
    * BlogTypeForm constructor.
    *
-   * @param \Drupal\Core\Config\Entity\ConfigEntityStorageInterface $storage
-   *   The blog_type storage.
+   * @param \Drupal\Core\Entity\ContentEntityStorageInterface $storage
+   *   The blog storage.
    */
-  public function __construct(ConfigEntityStorageInterface $storage) {
+  public function __construct(ContentEntityStorageInterface $storage) {
     $this->storage = $storage;
   }
 
@@ -34,7 +33,7 @@ class BlogForm extends ContentEntityForm {
    * {@inheritdoc}
    */
   public static function create(ContainerInterface $container) {
-    $storage = $container->get('entity_type.manager')->getStorage('blog_type');
+    $storage = $container->get('entity_type.manager')->getStorage('blog');
     return new static($storage);
   }
 
@@ -56,36 +55,20 @@ class BlogForm extends ContentEntityForm {
    * {@inheritdoc}
    */
   public function form(array $form, FormStateInterface $form_state) {
-    $type = $this->entity;
-
-    $form['#title'] = $type->isNew()
-      ? $this->t('Add blog type')
-      : $this->t('Edit blog type');
-
-    $form['name'] = array(
-      '#type' => 'textfield',
-      '#title' => $this->t('Name'),
-      '#default_value' => $type->label(),
-      '#maxlength' => 255,
-      '#required' => TRUE,
-    );
-    $form['type'] = array(
-      '#type' => 'machine_name',
-      '#default_value' => $type->id(),
-      '#maxlength' => EntityTypeInterface::BUNDLE_MAX_LENGTH,
-      '#machine_name' => array(
-        'exists' => array($this, 'exists'),
-        'source' => array('name'),
-      ),
-    );
-    $form['description'] = array(
-      '#type' => 'textfield',
-      '#title' => $this->t('Description'),
-      '#default_value' => $type->getDescription(),
-    );
-
-    $form = parent::form($form, $form_state);
-    return $this->protectBundleIdElement($form);
+    $blog = $this->entity;
+
+    $form['type'] = [
+      '#type' => 'value',
+      '#value' => $blog->bundle(),
+    ];
+
+    $form['blog_id'] = [
+      '#type' => 'value',
+      '#value' => $blog->id(),
+    ];
+
+    $form = parent::form($form, $form_state, $blog);
+    return $form;
   }
 
   /**
@@ -93,39 +76,38 @@ class BlogForm extends ContentEntityForm {
    */
   public function save(array $form, FormStateInterface $form_state) {
     $channel = 'dr8_zth';
-    $type = $this->entity;
-
-    // Prevent leading and trailing spaces in names.
-    $type->set('name', trim($type->label()));
+    $blog = $this->entity;
+    $result = $blog->save();
 
-    $status = $type->save();
-    $edit_link = $this->entity
+    $editLink = $blog
       ->toLink($this->t('Edit'), 'edit-form')
       ->toString();
+    $viewLink = $blog
+      ->toLink($blog->label(), 'canonical')
+      ->toString();
     $event_args = [
-      '%name' => $type->label(),
-      'link' => $edit_link,
+      '%blog' => $viewLink,
+      'link' => $editLink,
     ];
-    $collection = $type->toUrl('collection');
 
-    switch ($status) {
+    switch ($result) {
       case SAVED_NEW:
-        drupal_set_message($this->t('Created new %name blog type.', $event_args));
+        drupal_set_message($this->t('Created new %blog blog.', $event_args));
         $this->logger($channel)
-          ->notice('Created new %name blog type.', $event_args);
+          ->notice('Created new %blog blog.', $event_args);
         break;
 
       case SAVED_UPDATED:
-        drupal_set_message($this->t('Updated %name blog type.', $event_args));
+        drupal_set_message($this->t('Updated %blog blog.', $event_args));
         $this->logger($channel)
-          ->notice('Updated %name blog type.', $event_args);
+          ->notice('Updated %name blog.', $event_args);
         break;
     }
 
-    $form_state->setRedirectUrl($collection);
-    $id = $type->id();
-    $form_state->setValue('type', $id);
-    $form_state->set('type', $id);
+    $form_state->setRedirectUrl($blog->toUrl('canonical'));
+    $id = $blog->id();
+    $form_state->setValue('blog_id', $id);
+    $form_state->set('blog_id', $id);
   }
 
 }

+ 23 - 0
templates/blog.html.twig

@@ -0,0 +1,23 @@
+{#
+/**
+ * @file
+ * Default theme implementation to display a blog.
+ *
+ * Available variables:
+ * - attributes: HTML attributes for the wrapper.
+ * - title_prefix
+ * - title_suffix
+ *
+ * @see template_preprocess_taxonomy_term()
+ *
+ * @ingroup themeable
+ */
+#}
+<div{{ attributes }}>
+  {{ title_prefix }}
+  {% if not page %}
+    <h2><a href="{{ url }}">{{ name }}</a></h2>
+  {% endif %}
+  {{ title_suffix }}
+  {{ content }}
+</div>