Procházet zdrojové kódy

Step 6: complete implementation of the Blog collection route

Frederic G. MARAND před 7 roky
rodič
revize
1e2728be9d

+ 2 - 0
README.md

@@ -28,3 +28,5 @@ the following:
 4. Complete the implementation of the `BlogType` collection route to show type,
   name, description, and operations.
 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.

+ 5 - 5
dr8_zth.links.action.yml

@@ -4,8 +4,8 @@ entity.blog_type.add_form:
   appears_on:
     - entity.blog_type.collection
 
-#entity.taxonomy_term.add_form:
-#  route_name: entity.taxonomy_term.add_form
-#  title: 'Add term'
-#  appears_on:
-#    - entity.taxonomy_vocabulary.overview_form
+entity.blog.add_page:
+  route_name: entity.blog.add_page
+  title: 'Add blog item'
+  appears_on:
+    - entity.blog.collection

+ 4 - 0
dr8_zth.links.task.yml

@@ -0,0 +1,4 @@
+entity.blog.collection:
+  title: Blogs
+  route_name: entity.blog.collection
+  base_route: system.admin_content

+ 41 - 0
dr8_zth.routing.yml

@@ -1,3 +1,44 @@
+entity.blog.canonical:
+  path: '/blog/{blog}'
+  defaults:
+    _entity_view: 'blog.full'
+    _title: 'Blog'
+    _title_callback: '\Drupal\dr8_zth\Controller\BlogController::blogTitle'
+  requirements:
+    _entity_access: 'blog.view'
+    blog: \d+
+
+entity.blog.add_form:
+  path: '/admin/structure/blog/manage/{blog_type}/add'
+  defaults:
+    _controller: '\Drupal\taxonomy\Controller\TaxonomyController::addForm'
+    _title: 'Add blog'
+  requirements:
+    _entity_create_access: 'blog:{taxonomy_vocabulary}'
+
+entity.blog.edit_form:
+  path: '/blog/{blog}/edit'
+  defaults:
+    _entity_form: 'blog.default'
+    _title: 'Edit blog'
+  options:
+    _admin_route: TRUE
+  requirements:
+    _entity_access: 'blog.update'
+    blog: \d+
+
+entity.blog.delete_form:
+  path: '/blog/{blog}/delete'
+  defaults:
+    _entity_form: 'blog.delete'
+    _title: 'Delete blog'
+  options:
+    _admin_route: TRUE
+  requirements:
+    _entity_access: 'blog.delete'
+    blog: \d+
+
+
 entity.blog_type.collection:
   path: '/admin/structure/blog'
   defaults:

+ 12 - 0
src/BlogInterface.php

@@ -0,0 +1,12 @@
+<?php
+
+namespace Drupal\dr8_zth;
+
+use Drupal\Core\Entity\ContentEntityInterface;
+
+/**
+ * The specific operations of the BlogType entity type.
+ */
+interface BlogInterface extends ContentEntityInterface {
+
+}

+ 49 - 0
src/BlogListBuilder.php

@@ -0,0 +1,49 @@
+<?php
+
+namespace Drupal\dr8_zth;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityListBuilder;
+use Drupal\dr8_zth\Entity\Blog;
+use Drupal\dr8_zth\Entity\BlogType;
+
+/**
+ * Class BlogListBuilder is the list builder for Blog entities.
+ */
+class BlogListBuilder extends EntityListBuilder {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildHeader() {
+    $parentHeader = parent::buildHeader();
+    $header = [
+      $this->t('ID'),
+      $this->t('Title'),
+      $this->t('Type'),
+      $this->t('Author'),
+    ];
+    $ret = array_merge($header, $parentHeader);
+    return $ret;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildRow(EntityInterface $entity) {
+    assert($entity instanceof Blog);
+    $author = $entity->getAuthor()->toLink();
+    $bundle = $entity->bundle();
+    $blogType = BlogType::load($bundle);
+    $blogTypeEditLink = $blogType->toLink($bundle, 'edit-form');
+    $row = [
+      $entity->id(),
+      $entity->label(),
+      $blogTypeEditLink,
+      $author,
+    ];
+    $ret = array_merge($row, parent::buildRow($entity));
+    return $ret;
+  }
+
+}

+ 8 - 5
src/Controller/BlogController.php

@@ -4,6 +4,7 @@ namespace Drupal\dr8_zth\Controller;
 
 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;
@@ -43,14 +44,16 @@ class BlogController extends ControllerBase {
   /**
    * Route title callback.
    *
-   * @param \Drupal\taxonomy\TermInterface $taxonomy_term
-   *   The taxonomy term.
+   * @param \Drupal\dr8_zth\BlogInterface $blog
+   *   The blog instance.
    *
    * @return array
-   *   The term label as a render array.
+   *   The blog label as a render array.
    */
-  public function termTitle(TermInterface $taxonomy_term) {
-    return ['#markup' => $taxonomy_term->getName(), '#allowed_tags' => Xss::getHtmlTagList()];
+  public function blogTitle(BlogInterface $blog) {
+    $ret = ['#markup' => $blog->label(), '#allowed_tags' => Xss::getHtmlTagList()];
+    ksm($ret);
+    return $ret;
   }
 
 }

+ 77 - 4
src/Entity/Blog.php

@@ -2,6 +2,9 @@
 
 namespace Drupal\dr8_zth\Entity;
 
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Field\BaseFieldDefinition;
+use Drupal\dr8_zth\BlogInterface;
 use Drupal\Core\Entity\ContentEntityBase;
 
 /**
@@ -31,9 +34,14 @@ use Drupal\Core\Entity\ContentEntityBase;
  *     "langcode" = "langcode",
  *     "uuid" = "uuid",
  *     "status" = "status",
- *     "author" = "uid",
+ *     "uid" = "uid",
  *   },
  *   handlers = {
+ *     "form" = {
+ *       "default" = "Drupal\dr8_zth\Form\BlogForm",
+ *       "delete" = "Drupal\dr8_zth\Form\BlogDeleteForm"
+ *     },
+ *     "list_builder" = "Drupal\dr8_zth\BlogListBuilder",
  *     "route_provider" = {
  *       "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
  *     }
@@ -42,8 +50,8 @@ use Drupal\Core\Entity\ContentEntityBase;
  *   field_ui_base_route = "entity.blog_type.edit_form",
  *   permission_granularity = "entity_type",
  *   links = {
- *     "add-form" = "/admin/content/blog/add/{blog_type}",
- *     "add-page" = "/admin/content/blog/add",
+ *     "add-form" = "/blog/add/{blog_type}",
+ *     "add-page" = "/blog/add",
  *     "canonical" = "/blog/{blog}",
  *     "collection" = "/admin/content/blog",
  *     "delete-form" = "/blog/{blog}/delete",
@@ -54,6 +62,71 @@ use Drupal\Core\Entity\ContentEntityBase;
  *   admin_permission = "administer blog",
  * )
  */
-class Blog extends ContentEntityBase {
+class Blog extends ContentEntityBase implements BlogInterface {
+
+  /**
+   * @var \Drupal\user\Entity\User
+   */
+  protected $uid;
+
+  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
+    $fields = parent::baseFieldDefinitions($entity_type);
+    $fields['title'] = BaseFieldDefinition::create('string')
+      ->setLabel(t('Title'))
+      ->setRequired(TRUE)
+      ->setTranslatable(TRUE)
+      ->setRevisionable(TRUE)
+      ->setSetting('max_length', 255)
+      ->setDisplayOptions('view', array(
+        'label' => 'hidden',
+        'type' => 'string',
+        'weight' => -5,
+      ))
+      ->setDisplayOptions('form', array(
+        'type' => 'string_textfield',
+        'weight' => -5,
+      ))
+      ->setDisplayConfigurable('form', TRUE);
+
+    $fields['uid'] = BaseFieldDefinition::create('entity_reference')
+      ->setLabel(t('Authored by'))
+      ->setDescription(t('The username of the blog author.'))
+      ->setRevisionable(TRUE)
+      ->setSetting('target_type', 'user')
+      ->setDefaultValueCallback('Drupal\node\Entity\Node::getCurrentUserId')
+      ->setTranslatable(TRUE)
+      ->setDisplayOptions('view', array(
+        'label' => 'hidden',
+        'type' => 'author',
+        'weight' => 0,
+      ))
+      ->setDisplayOptions('form', array(
+        'type' => 'entity_reference_autocomplete',
+        'weight' => 5,
+        'settings' => array(
+          'match_operator' => 'CONTAINS',
+          'size' => '60',
+          'placeholder' => '',
+        ),
+      ))
+      ->setDisplayConfigurable('form', TRUE);
+
+    ksm($fields);
+    return $fields;
+  }
+
+  /**
+   * @return \Drupal\user\Entity\User
+   */
+  public function getAuthor() {
+    return $this->get('uid')->entity;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getAuthorId() {
+    return $this->getEntityKey('uid');
+  }
 
 }

+ 42 - 0
src/Form/BlogDeleteForm.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace Drupal\dr8_zth\Form;
+
+use Drupal\Core\Entity\ContentEntityDeleteForm;
+
+/**
+ * Provides a deletion confirmation form for blog types.
+ */
+class BlogDeleteForm extends ContentEntityDeleteForm {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'blog_confirm_delete';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getQuestion() {
+    return $this->t('Are you sure you want to delete the %title blog?', [
+      '%title' => $this->entity->label(),
+    ]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDescription() {
+    return $this->t('Deleting a blog will delete all its revisions. This action cannot be undone.');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getDeletionMessage() {
+    return $this->t('Deleted %title blog.', ['%title' => $this->entity->label()]);
+  }
+
+}

+ 131 - 0
src/Form/BlogForm.php

@@ -0,0 +1,131 @@
+<?php
+
+namespace Drupal\dr8_zth\Form;
+
+use Drupal\Core\Config\Entity\ConfigEntityStorageInterface;
+use Drupal\Core\Entity\ContentEntityForm;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Form\FormStateInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Class BlogTypeForm is the default add/edit form for BlogType entities.
+ */
+class BlogForm extends ContentEntityForm {
+
+  /**
+   * The blog type storage.
+   *
+   * @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface
+   */
+  protected $storage;
+
+  /**
+   * BlogTypeForm constructor.
+   *
+   * @param \Drupal\Core\Config\Entity\ConfigEntityStorageInterface $storage
+   *   The blog_type storage.
+   */
+  public function __construct(ConfigEntityStorageInterface $storage) {
+    $this->storage = $storage;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    $storage = $container->get('entity_type.manager')->getStorage('blog_type');
+    return new static($storage);
+  }
+
+  /**
+   * Determines if the blog type already exists.
+   *
+   * @param string $type
+   *   The blog type ID.
+   *
+   * @return bool
+   *   TRUE if the blog type exists, FALSE otherwise.
+   */
+  public function exists($type) {
+    $action = $this->storage->load($type);
+    return !empty($action);
+  }
+
+  /**
+   * {@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);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  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()));
+
+    $status = $type->save();
+    $edit_link = $this->entity
+      ->toLink($this->t('Edit'), 'edit-form')
+      ->toString();
+    $event_args = [
+      '%name' => $type->label(),
+      'link' => $edit_link,
+    ];
+    $collection = $type->toUrl('collection');
+
+    switch ($status) {
+      case SAVED_NEW:
+        drupal_set_message($this->t('Created new %name blog type.', $event_args));
+        $this->logger($channel)
+          ->notice('Created new %name blog type.', $event_args);
+        break;
+
+      case SAVED_UPDATED:
+        drupal_set_message($this->t('Updated %name blog type.', $event_args));
+        $this->logger($channel)
+          ->notice('Updated %name blog type.', $event_args);
+        break;
+    }
+
+    $form_state->setRedirectUrl($collection);
+    $id = $type->id();
+    $form_state->setValue('type', $id);
+    $form_state->set('type', $id);
+  }
+
+}