@font-your-face

Learning (some) Drupal 8

Ashok Modi - LADrupal - April 2016

About @font-your-face

  • Its a way to select typography on your site
  • Nice UI (at least in D7)
  • Supported Google Fonts, Typekit, Fontsquirrel, etc
  • https://www.drupal.org/project/fontyourface
  • https://www.github.com/fontyourface/fontyourface

I have my own side project, webfont loader

  • Good, but not as friendly
  • Integrated to work with @font-your-face
  • Competing modules complementing each other
    • The Drupal Way

Scott Reynen needed help

  • Not really working with Drupal
  • Module not really been maintained since 2013

Port a module

  • Learn a lot about Drupal 8
  • Learn a lot about where things are headed

Talk a bit about

  • *Entities (Replacing data storage)
  • **Routes (replacing Menus)

Please ask questions

Can go whichever direction the group prefers

D7 to D8

  • Challenging
  • Interesting

Drupal 8 is complicated

  • A bajillion yml files
  • Even more PHP files
  • So many things are OO
  • And we still have hooks?!?

PSA: Use Drupal console

Its ****ing amazing

Drupal Console

  • Run tasks much like Drush
  • Even slicker
  • --learning flag to really learn it all
  • Creates skeleton code for you
    • Module
    • Entities (including config)
    • Routes
    • Saved me time
      • Generated > 2k lines of code
      • Helped me understand structure

Architecture

  • Font-your-face provides certain actions
    • Saving fonts (and certain properties)
    • Enabling / Disabling fonts to load on page
    • Saving css for where font displays (optional)
  • Contrib submodules implement hooks
    • Import Fonts
    • Load Fonts

Entity - Font

  • Font entity
    • Font friendly name (like Alex Brush)
    • Font css family name (might be alex-brush)
    • Font Style (normal or italic)
    • Font Weight (100 - 900, light, normal, bold)
    • Subprovider module (google fonts, typekit, etc)
    • Canonical URL
      • Unique that can be used in configuration
    • Etc (license, designer, foundry)

Entity - Font

  • Just defined my table

Entity - Font

  • Write our class files
  • Classes follow psr-4 format
    • **src/FontInterface.php
    • **src/Entity/Font.php
    • src/Form/FontForm.php (add / delete / etc)
    • src/Form/FontSettingsForm.php
    • src/FontAccessControlHandler.php
    • src/FontHtmlRouteProvider.php
    • src/FontListBuilder.php
    • src/FontStorageSchema.php

Holy **** thats a lot

Use Drupal Console

Demo

Entity - FontInterface.php

  • Defines how users interact with a Font Entity
  • A developer could override the Font.php class
    • Must still conform to FontInterface
    • At least write all functions listed in FontInterface
  • Show Code

Entity - Font.php

  • The main class
  • Define annotations
    • Reusable components
    • Lets your Entity pick up behaviors
  • The internal entity name (font)
  • Handlers (forms, access control, etc)
  • Tables (your fields will go here)
  • Links (no need to define routes)
  • <show code>

Entity - Font.php

  • The main class
  • Define your fields
  • function baseFieldDefinitions()
    • Standard field style definitions
    • Can even include entity references
    • Remember multifield? Kinda like that!

Entity - Font.php

    $fields['url'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Font URL'))
      ->setDescription(t('A URL for the font.'))
      ->setSettings([
        'max_length' => 191,
        'text_processing' => 0,
      ])
      ->setDefaultValue('')
      ->setDisplayOptions('view', [
        'label' => 'above',
        'type' => 'string',
        'weight' => -4,
      ])
      ->setDisplayOptions('form', [
        'type' => 'string_textfield',
        'weight' => -4,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

Entity - Font.php

  • Automatic getters and setters unless you make them private
    • $font->url->value (GET)
    • $font->url->value = 'https://groups.drupal.org/la' (SET)
    • Or define your own functions (first implement in interface) - useful if weird variable names or variables are private
      • function getUrl()
      • function setUrl()

Entity - Font.php

  • If you update field definitions down the line
    • Drush
    • Drupal Console
drush updb --entity-updates
drupal update:entities

Switching to Routes

  • A bit like hook_menu
  • If you need a url path to do something (like show a page, perform an action, etc)
    • admin/appearance/font/{font}/{js}/enable
      • Can add multiple arguments
      • Words like {font}, {node}, {user} set to load entity since Drupal knows about them
      • Define your own (like {js})
        • Specify accepted arguments!

Switching to Routes

  • 4 files to enable routing
    • fontyourface.routing.yml
    • fontyourface.links.menu.yml
    • fontyourface.links.action.yml
    • fontyourface.links.tasks.yml
  • Routes defined as classes
    • src/Controller/FontYourFaceController.php

Switching to Routes

  • The controller can actually have the arguments in the preferred order vs what the url has
fontyourface.routing.yml

entity.font.enable:
  path: '/admin/appearance/font/{font}/{js}/enable'
  defaults:
    _title: 'Enable font'
    _controller: '\Drupal\fontyourface\Controller\FontYourFaceController::enableFont'
  requirements:
    _permission: 'administer font entities'
    js: 'nojs|ajax'
/**
 * Controller routines for forum routes.
 */
class FontYourFaceController extends ControllerBase {

  /**
   * {@inheritdoc}
   */
  public function enableFont($js, Font $font) {

Switching to Routes

fontyourface.links.action.yml

entity.font_display.add_form:
  route_name: 'entity.font_display.add_form'
  title: 'Add Font display'
  appears_on:
    - entity.font_display.collection
fontyourface.links.task.yml

entity.font.collection:
  route_name: entity.font.collection
  base_route: system.themes_page
  title: '@font-your-face'
entity.font.browse:
  route_name: entity.font.collection
  parent_id: entity.font.collection
  title: 'Browse'
fontyourface.links.menu.yml

entity.font.collection:
  title: '@font-your-face'
  route_name: entity.font.collection
  description: 'List Font entities'
  parent: system.themes_page
  weight: 100
entity.font.browse:
  title: 'Browse'
  route_name: entity.font.collection
  description: 'List Font entities'
  parent: entity.font.collection

Lessons

  • Writing modules for Drupal 8 are more daunting
    • Worth it
    • Automatic views integration
      • Only need to create your own customization after
    • Automatic field-ability
    • Automatic unlimited view modes

Lessons

  • Initially hated routes
    • Loved them once I understood menu, links, actions

Lessons

  • Use Drupal Console
    • I know, repeated so many times
    • It saved time initially creating entities
    • learn them at my own pace as I needed to flesh out functionality

Next Time

  • Configuration
  • Configuration Entities
  • Light Theming
    • Weak point

Questions?

Thank you!