abstract class AbstractProject

A useful starting point for creating a "project" within a module.

UML: AbstractProject

@author darrenkelly

Hierarchy

Expanded class hierarchy of AbstractProject

1 file declares its use of AbstractProject
CurrentPosts.php in lib/Drupal/ooe/Demo/Adapted/CurrentPosts.php
CurrentPosts

File

lib/Drupal/ooe/Project/AbstractProject.php, line 27
AbstractProject

Namespace

Drupal\ooe\Project
View source
abstract class AbstractProject extends DefaultModuleHelper implements IProject {

  /**
   * A Drupal access arguments array.
   *
   * @var array
   */
  private $accessArguments;

  /**
   * By default there is no access restriction ! Inject via constructor (only).
   *
   * @todo Sensible default access (currently no restriction)
   *
   * Subclasses may reimplement this to provide more specific access arguments.
   *
   * @return array
   *   An empty Drupal access arguments array.
   */
  protected function accessArguments() {
    if (empty($this->accessArguments)) {
      $this->accessArguments = array();
      // @todo: default no access restriction.
      // @todo consider via myAccessArguments().
    }
    return $this->accessArguments;
  }

  /**
   * A theme region for the default block.
   *
   * @var \Drupal\ooe\Layout\IRegion
   */
  private $blockRegion;

  /**
   * If not injected on construction, defaults to the Bartik theme 1st sidebar.
   *
   * @todo Ensure safe default
   *
   * @return \Drupal\ooe\Layout\IRegion
   *   The constructor-injected, else lazily created and configured,
   *   theme region.
   */
  protected function blockRegion() {
    if (empty($this->blockRegion)) {

      // Create:
      $this->blockRegion = $this->factory()->newRegion(BartikRegions::SIDEBAR_FIRST);
      // @todo sensible default region
      // Configure:
      // $this->blockRegion->set?
    }
    return $this->blockRegion;
  }

  /**
   * Constructor.
   *
   * @param string $module
   *   The machine name of the module
   *
   * @param \Drupal\ooe\Factory\IFactory $factory
   *   Optional factory; if none given or null
   *   a @link DefaultFactory @endlink will be used.
   *
   * @param array $accessArguments
   *   Optional Drupal access arguments array.
   *
   * @param \Drupal\ooe\Layout\IRegion $blockRegion
   *   Optional theme layout region for the default block.
   */
  public function __construct(
  $module, IFactory $factory = NULL, array $accessArguments = NULL, IRegion $blockRegion = NULL) {

    parent::__construct($module, $factory);

    if (!empty($accessArguments)) {
      $this->accessArguments = $accessArguments;
    }

    if (!empty($blockRegion)) {
      $this->blockRegion = $blockRegion;
    }
  }

  /**
   * By default does nothing; reimplement to add additional menu items.
   *
   * Note the main menu item is always already added.
   */
  protected function myFillMenuItemSet() {
  }

  /**
   * A set of menu items.
   *
   * @var \Drupal\ooe\Menu\IMenuItemSet
   */
  private $menuItemSet;

  /**
   * Lazily creates and configures a set/group of menu items.
   *
   * It always already includes the primary menu item !
   *
   * Additional menu items will be automatically added via
   * @link AbstractProject::myFillmenItemSet @endlink().
   *
   * @return \Drupal\ooe\Menu\IMenuItemSet
   *   A lazily created and configured set of menu items.
   */
  final protected function menuItemSet() {
    if (empty($this->menuItemSet)) {

      // Create:
      $this->menuItemSet = $this->factory()->newMenuItemSet();

      // Configure:
      $this->menuItemSet->addMenuItem($this->getMenuItem());
      // Always at least !

      $this->myFillMenuItemSet();
    }
    return $this->menuItemSet;
  }

  /**
   * Adds a menu item to the menu item set of this.
   *
   * @param \Drupal\ooe\Menu\IMenuItem $menuItem
   *   A menu item to add to the menu item set/group.
   *
   * @return \Drupal\ooe\Module\IProject
   *   This.
   */
  final protected function addMenuItem(IMenuItem $menuItem) {
    $this->menuItemSet()->addMenuItem($menuItem);
    return $this;
  }

  /**
   * The set of menu items handled by this.
   *
   * @return \Drupal\ooe\Menu\IMenuItem[]
   *   The array of menu items handled by this.
   */
  public function getMenuItems() {
    return $this->menuItemSet()->getMenuItems();
  }

  /**
   * The (default) block of this project.
   *
   * Need not be used, need not be made visible.
   *
   * @var \Drupal\ooe\Block\IBlock
   */
  private $block;

  /**
   * Lazily creates a demo block.
   *
   * The ultimate block implementation chosen
   * will depend on @link AbstractProject::myBlock @endlink.
   *
   * This strategy also enables one to separate configurations
   * common to all projects from those specific to a specific project.
   *
   * @return \Drupal\ooe\Block\IBlock
   *   A demo block.
   */
  public function getBlock() {
    if (empty($this->block)) {
      $this->block = $this->myBlock();
    }
    return $this->block;
  }

  /**
   * A helper method to assist in implementing @link AbstractBlock::myBlock().
   *
   * There is no obligation to use it, however it provides
   * a sensible default configuration, including enabling the block
   * and assigning it to the default block region managed by this.
   *
   * Please note that $deltaSuffix is NOT the entire block delta identifier,
   * it is only the suffix that will be appended to the module machine name
   * following by an underscore '_'.
   *
   * @param string $deltaSuffix
   *   Will always be appended to 'MYMODULE_' as the block delta identifier.
   * @param string $info
   *   Translated ! Will optionally be prepended with the module display name.
   *
   * @return \Drupal\ooe\Block\IBlock
   *   A new configured block with useful defaults.
   */
  protected function newBlock(
  $deltaSuffix, $info
  ) {

    $fullInfo = $this->doPrefixBlockInfo ?
      t('!module-display-name: !info', 
      array(
        '!module-display-name' => $this->getModuleDisplayName(),
        '!info' => $info,
      )) : $info;

    return $this->block = $this->factory()->newBlock(
    $this->getModule() . "_$deltaSuffix", // POLICY!
    $fullInfo
    )
      ->setCache(BlockCacheKind::CACHE_PER_ROLE)
      ->setStatus(BlockStatusKind::ENABLED)
      ->setRegion($this->blockRegion());
    // Never null !
  }

  /**
   * If TRUE the block info will be automatically prefixed
   * with the module display name followed by ': '
   *
   * @var bool
   */
  private $doPrefixBlockInfo = TRUE;

  /**
   * Sets whether the block info will be automatically prefixed.
   *
   * Sets whether the block info will be automatically prefixed
   * with the module display name followed by ': ",
   *
   * @param bool $doPrefixBlockInfo
   *   If TRUE the block info will be automatically prefixed
   *   with the module display name followed by ': '.
   *
   * @return IProject
   *   This.
   */
  public function setDoPrefixBlockInfo($doPrefixBlockInfo) {
    $this->doPrefixBlockInfo = $doPrefixBlockInfo;
    return $this;
  }

  /**
   * Whether the menu titles will be automatically prefixed.
   *
   * Whether the menu titles will be automatically prefixed
   * with the module display name followed by ': ".
   *
   * @return bool
   *   Whether the menu titles will be automatically
   *   prefixed with the module display name followed by ': ".
   */
  public function isDoPrefixMenuTitles() {
    return $this->doPrefixMenuTitles;
  }

  /**
   * Whether the block info will be automatically prefixed.
   *
   * Whether the block info will be automatically prefixed
   * with the module display name followed by ': ".
   *
   * @return bool
   *   Whether the block info will be automatically prefixed
   *   with the module display name followed by ': ".
   */
  public function isDoPrefixBlockInfo() {
    return $this->doPrefixBlockInfo;
  }

  /**
   * Whether the menu paths will be automatically prefixed.
   *
   * Whether the menu paths will be automatically prefixed
   * with the module machine name followed by ': ".
   *
   * @return bool
   *   Whether the menu paths will be automatically prefixed
   *   with the module machine name followed by ': ".
   */
  public function isDoPrefixMenuPaths() {
    return $this->doPrefixMenuPaths;
  }

  /**
   * Implement to return a new configured block.
   *
   * This is deliberately chosen to be abstract
   * to force implementations of @link IProject @endlink
   * to choose and configure a specific implementation.
   *
   * The term 'hook' is massively overloaded in software engineering.
   * This is a "hook" in a sense slightly different from the Drupal
   * hook mechanism. This stratagy, although it might seem like overkill
   * for the simplest project, is extremely powerful and is used often
   * in the OOE system. It enables a clean separation of configuration
   * specific to all projects from those specific to a given project.
   *
   * @return \Drupal\ooe\Block\IBlock
   *   A block specific to a project.
   */
  abstract protected function myBlock();

  /**
   * A (default) block view for a project.
   *
   * It is not assumed
   * that a block (and block view) is needed or even visible for a
   * given project within a module, so in many cases a
   * @link StubBlockView @endlink
   * is sufficient.
   *
   * Remember, there is no obligation to use an @link IProject @endlink
   * at all, it is merely a useful starting point that covers many cases.
   *
   * @var \Drupal\ooe\Block\IBlockView
   */
  private $blockView;

  /**
   * A (default) block view for a project.
   *
   * It is not assumed
   * that a block is needed or even visible for a given project,
   * so in many cases a @link StubBlockView @endlink is sufficient.
   *
   * The block view chosen will ultimately depend on
   * @link AbstractProject::myBlockView @endlink(IBlock)
   * and it will always be bound to the
   * @link AbstractProject::$block @endlink.
   *
   * @return \Drupal\ooe\Block\IBlockView
   *   A lazily created and configured block view.
   */
  public function getBlockView() {
    if (empty($this->blockView)) {
      $this->blockView = $this->myBlockView($this->getBlock());
    }
    return $this->blockView;
  }

  /**
   * Implement to return a (usually new) configured block view.
   *
   * @param \Drupal\ooe\Block\IBlock $block
   *   The primary block for which this must create a new block view.
   *
   * @return \Drupal\ooe\Block\IBlockView
   *   A configured block view.
   */
  abstract protected function myBlockView(IBlock $block);

  /**
   * The primary menu item of this.
   *
   * @var \Drupal\ooe\Menu\IMenuItem
   */
  private $menuItem;

  /**
   * May be overridden to return a more specialised primary menu item.
   *
   * @return \Drupal\ooe\Menu\IMenuItem
   *   A lazily created and configured menu item.
   */
  public function getMenuItem() {
    if (empty($this->menuItem)) {

      $this->menuItem = $this->myMenuItem();
      //dpm($this->menuItem->getPath());//DEBUG
      //dpm($this->accessArguments(),$this->accessArguments());//DEBUG
      $this->menuItem->setAccessArguments($this->accessArguments());

      //$this->menuItem->forceAccessCallbackTRUE();
      // Concern: setting the access arguments here
      // overrides any set in the myMenuItem().
      // Consider myAccessArguments().
    }
    return $this->menuItem;
  }

  /**
   * If TRUE menu paths will be automatically prefixed
   * with the module machine name followed by '/'
   *
   * @var bool
   */
  private $doPrefixMenuPaths = FALSE;

  /**
   * Sets whether the menu paths will be automatically prefixed.
   *
   * Sets whether the menu paths will be automatically
   * prefixed with the module machine name followed by ': ",
   *
   * @param bool $doPrefixMenuPaths
   *   If TRUE menu paths will be automatically prefixed
   *   with the module machine name followed by '/'.
   *
   * @return IProject
   *   This.
   */
  public function setDoPrefixMenuPaths($doPrefixMenuPaths) {
    $this->doPrefixMenuPaths = $doPrefixMenuPaths;
    return $this;
  }

  /**
   * If TRUE menu title will be automatically prefixed
   * with the module display name followed by ': ".
   *
   * @var bool
   */
  private $doPrefixMenuTitles = TRUE;

  /**
   * Sets whether the menu titles will be automatically prefixed.
   *
   * Sets whether the menu titles will be automatically prefixed
   * with the module display name followed by ': ",
   *
   * @param bool $doPrefixMenuTitles
   *   If TRUE menu titles will be automatically prefixed
   *   with the module display name followed by ': ".
   *
   * @return IProject
   *   This.
   */
  public function setDoPrefixMenuTitles($doPrefixMenuTitles) {
    $this->doPrefixMenuTitles = $doPrefixMenuTitles;
    return $this;
  }

  /**
   * Creates a new basic menu item with an explicit .module file callback.
   *
   * Applies any access arguments.
   *
   * It is here to help one implement myMenuItem(); it has sensible defaults
   * that one can further configure using the return IMenuItem.
   *
   * The top-level callback must be a function in the .module file !
   *
   * This method is only here to show you the "old" Drupal7 way
   * and to support some of the simpler demo projects here such as
   * @end CurrentPosts @endlink.
   *
   * (You SHOULD when working with OOE always prefer where possible extending
   * an @link AbstractControlledProject @endlink which offers
   * an @link IPageMenuItem @endlink with an @link IPageController @endlink !.)
   *
   * You are free to use any valid menu $path, however
   * it is a good idea to include the module machine name in the
   * given $path or to switch on the option
   * @link AbstractProject::$doPrefixMenuPaths @endlink
   * to automatically prefix it with the module machine name and '/'.
   *
   * Please note however that parameter $pageCallbackSuffix is always appended
   * to the module machine name in lower case prefixed AND followed by '_'
   * so that "uncontrolled" module file callback function conventions are met.
   *
   * When using .module level callbacks (which with OOE you need no longer do)
   * please always prefix your module callback functions with '_MYMODULE_' !
   * The initial underscore helps to distinguish
   * custom callbacks from Drupal hooks and handlers.
   *
   * Example: to create a callback to .module file
   * _ooe_page_callback() where 'ooe' is the module:
   *
   *  $pageCallbackSuffix='page_callback'
   *
   * @param string $title
   *   The title of the menu item (optionally automatically
   *   prepended with the module display name and ': ').
   * @param string $path
   *   The menu path (optionally automatically prepended
   *   with the module machine name followed by '/'.
   * @param string $pageCallbackSuffix
   *   Always only the "tail" of a .module callback function
   *   as in 'mycallback' in '_MYMODULE_mycallback()'.
   *
   * @return \Drupal\ooe\Menu\IMenuItem
   *   A new configured menu item.
   */
  protected function newMenuItem($title, $path, $pageCallbackSuffix) {

    $fullTitle = $this->doPrefixMenuTitles ?
      $this->getModuleDisplayName() . ": $title" : $title;
    $fullPath = $this->doPrefixMenuPaths ?
      $this->getModule() . "/$path" : $path;

    return $this->factory()->newMenuItem(
    $fullTitle, $fullPath
    )->setPageCallback('_' . $this->getModule() . '_' . $pageCallbackSuffix)
      ->setAccessArguments($this->accessArguments());

    //->setTypeNormal(true);// Redundant, default.
  }

  /**
   * Concrete subclasses must implement this to return a new menu item.
   *
   * Concrete subclasses must implement this to return a new,
   * configured, basic (uncontrolled)
   * @IMenuItem or any other subclass kind of menu item
   * such as a controlled @IPageMenuItem.
   *
   * @return \Drupal\ooe\Menu\IMenuItem
   *   Creates and configures a new menu item.
   */
  abstract protected function myMenuItem();
}

Members

Contains filters are case sensitive
Namesort descending Modifiers Type Description
AbstractProject::$accessArguments private property A Drupal access arguments array.
AbstractProject::$block private property The (default) block of this project.
AbstractProject::$blockRegion private property A theme region for the default block.
AbstractProject::$blockView private property A (default) block view for a project.
AbstractProject::$doPrefixBlockInfo private property If TRUE the block info will be automatically prefixed with the module display name followed by ': '
AbstractProject::$doPrefixMenuPaths private property If TRUE menu paths will be automatically prefixed with the module machine name followed by '/'
AbstractProject::$doPrefixMenuTitles private property If TRUE menu title will be automatically prefixed with the module display name followed by ': ".
AbstractProject::$menuItem private property The primary menu item of this.
AbstractProject::$menuItemSet private property A set of menu items.
AbstractProject::accessArguments protected function By default there is no access restriction ! Inject via constructor (only).
AbstractProject::addMenuItem final protected function Adds a menu item to the menu item set of this.
AbstractProject::blockRegion protected function If not injected on construction, defaults to the Bartik theme 1st sidebar.
AbstractProject::getBlock public function Lazily creates a demo block. Overrides IProject::getBlock
AbstractProject::getBlockView public function A (default) block view for a project. Overrides IProject::getBlockView
AbstractProject::getMenuItem public function May be overridden to return a more specialised primary menu item. Overrides IProject::getMenuItem
AbstractProject::getMenuItems public function The set of menu items handled by this. Overrides IProject::getMenuItems
AbstractProject::isDoPrefixBlockInfo public function Whether the block info will be automatically prefixed.
AbstractProject::isDoPrefixMenuPaths public function Whether the menu paths will be automatically prefixed.
AbstractProject::isDoPrefixMenuTitles public function Whether the menu titles will be automatically prefixed.
AbstractProject::menuItemSet final protected function Lazily creates and configures a set/group of menu items.
AbstractProject::myBlock abstract protected function Implement to return a new configured block.
AbstractProject::myBlockView abstract protected function Implement to return a (usually new) configured block view.
AbstractProject::myFillMenuItemSet protected function By default does nothing; reimplement to add additional menu items.
AbstractProject::myMenuItem abstract protected function Concrete subclasses must implement this to return a new menu item.
AbstractProject::newBlock protected function A helper method to assist in implementing @link AbstractBlock::myBlock().
AbstractProject::newMenuItem protected function Creates a new basic menu item with an explicit .module file callback.
AbstractProject::setDoPrefixBlockInfo public function Sets whether the block info will be automatically prefixed.
AbstractProject::setDoPrefixMenuPaths public function Sets whether the menu paths will be automatically prefixed.
AbstractProject::setDoPrefixMenuTitles public function Sets whether the menu titles will be automatically prefixed.
AbstractProject::__construct public function Constructor. Overrides DefaultModuleHelper::__construct
DefaultModuleHelper::$displayName private property A human readable and displayable name of the module.
DefaultModuleHelper::$factory private property The current factory of this.
DefaultModuleHelper::$module private property The module machine name.
DefaultModuleHelper::f protected function The current factory, or a lazily created DefaultFactory.
DefaultModuleHelper::factory protected function The current factory or a lazily created DefaultFactory.
DefaultModuleHelper::getFactory public function The current factory. Overrides IModuleHelper::getFactory
DefaultModuleHelper::getModule public function Gets the module machine name. Overrides IModuleHelper::getModule
DefaultModuleHelper::getModuleDisplayName public function A human readable and displayable name of the module. Overrides IModuleHelper::getModuleDisplayName
DefaultModuleHelper::setFactory protected function Sets the factory of this.
DefaultModuleHelper::setModule private function Sets the module machine name.
DefaultModuleHelper::setModuleDisplayName public function Sets a human readable and displayable name of the module. Overrides IModuleHelper::setModuleDisplayName