Subversion Repositories web.creative

Rev

Blame | Last modification | View Log | Download

<?php namespace ProcessWire;

/**
 * ProcessWire MarkupPageArray module
 *
 * Adds convenience methods to all PageArray instances for markup generation
 * 
 * It adds PageArray::render() which generates a basic unordered list of linked pages. 
 * It can be called from any PageArray: 
 *
 * $items = $pages->find("id>0, limit=10"); // replace id>0 with your selector
 * echo $items->render(); // renders a basic list of linked pages
 * 
 * It will also generate pagination if the selector had a limit placed on it (i.e. "limit=10"),
 * and there are more pages left to render, and the page's template supports page numbers. 
 *
 * Also adds a PaginatedArray::renderPager() method, which is convenient when you are generating your
 * own page list markup, but just want to use the automatic pagination generator. 
 * 
 * 
 * ProcessWire 3.x, Copyright 2018 by Ryan Cramer
 * https://processwire.com
 *
 *
 */

class MarkupPageArray extends WireData implements Module {

  public static function getModuleInfo() {
    return array(
      'title' => 'PageArray Markup', 
      'summary' => 'Adds renderPager() method to all PaginatedArray types, for easy pagination output. Plus a render() method to PageArray instances.', 
      'version' => 100, 
      'permanent' => false, 
      'singular' => true, 
      'autoload' => true, 
      );
  }

  public function init() { 
    $this->addHook("PageArray::render", $this, "renderPageArray"); 
    $this->addHook("PaginatedArray::renderPager", $this, "renderPager"); 
  } 

  /**
   * Render markup for a PageArray
   *
   * Can be accessed as $mypages->render() where '$mypages' is any instance of a PageArray. 
   *
   * Be sure to see the $defaultOptions in the method if you want to change it's behavior or output. 
   * 
   * @param HookEvent $event
   *
   * #param array $options Optional list of options to modify the behavior and output. 
   * #return string
   *
   */
  public function renderPageArray(HookEvent $event) {

    /** @var PaginatedArray $pageArray */
    $pageArray = $event->object;
    $arguments = $event->arguments;
    $options = array();
    
    if(!count($pageArray)) {
      $event->return = '';
      return;
    }

    $defaultOptions = array(

      // markup for the list container, specify {out} where generated items should go
      'listMarkup' => "\n<ul class='PageArray'>{out}\n</ul>", 

      // markup for list item. note {title} may be any valid page field, or you may use multiple fields
      'itemMarkup' => "\n\t<li><a href='{url}'>{title}</a></li>", 

      // options to send to the pager (optional). See MarkupPagerNav::$options
      'pagerOptions' => array(),  

      // show pagination links at the top (when applicable)?
      'pagerTop' => false,      

      // show pagination links at the bottom (when applicable)?
      'pagerBottom' => true,    

      // getVars for pager, but preferably use $input->whitelist instead!
      'getVars' => array(),     

      // number of links to use for pagination, typically 10. 
      'numPageLinks' => 10,     

      // base URL for pagination
      'baseUrl' => '',
      ); 

    if(isset($arguments[0]) && is_array($arguments[0])) $options = $arguments[0]; 
    $options = array_merge($defaultOptions, $options); 

    $out = '';
    $fields = array();

    if(preg_match_all('/\{[-_a-z0-9|]+\}/i', $options['itemMarkup'], $matches)) {
      $fields = $matches[0];
    }
    
    foreach($pageArray as $page) {
      if($page instanceof Page && !$page->viewable()) continue; 
      $values = array();
      foreach($fields as $field) {
        $values[$field] = $page->get(trim($field, '{}'));
      }
      $out .= str_replace($fields, $values, $options['itemMarkup']); 
    }

    $out = str_replace('{out}', $out, $options['listMarkup']); 

    if(($options['pagerTop'] || $options['pagerBottom']) && $pageArray->getTotal() > count($pageArray))  {

      /** @var MarkupPagerNav $pager */
      $pager = $this->modules->get('MarkupPagerNav');   
      $pagerOptions = $options['pagerOptions']; 

      if(!empty($options['baseUrl'])) $pager->setBaseUrl($options['baseUrl']); 
        else $pager->setBaseUrl($this->page->url); 

      if(empty($options['getVars'])) $pagerOptions['getVars'] = $options['getVars'];
      if(empty($options['numPageLinks'])) $pagerOptions['numPageLinks'] = $options['numPageLinks'];

      $pagerOut = $pager->render($pageArray, $pagerOptions); 

      if($options['pagerTop']) $out = $pagerOut . $out; 
      if($options['pagerBottom']) $out .= $pagerOut; 
    } 

    $event->return = $out; 
  }

  /**
   * Render pagination markup for a PageArray
   *
   * i.e. echo $mypages->renderPager(), where '$mypages' is a PageArray instance
   * 
   * @param HookEvent $event
   *
   * #param array $options Optional options to provide to MarkupPagerNav - see MarkupPagerNav::$options
   * #return string
   *
   */
  public function renderPager(HookEvent $event) {
    /** @var PaginatedArray $pageArray */
    $pageArray = $event->object; 
    if(!$pageArray->getLimit()) return; 
    $arguments = $event->arguments; 
    $options = array();
    if(isset($arguments[0]) && is_array($arguments[0])) $options = $arguments[0]; 
    /** @var MarkupPagerNav $pager */
    $pager = $this->modules->get('MarkupPagerNav'); 
    if(empty($options['baseUrl'])) {
      $baseUrl = $this->wire('page')->url;
      $urlSegmentStr = $this->wire('input')->urlSegmentStr; 
      if(strlen($urlSegmentStr)) $baseUrl = rtrim($baseUrl, '/') . "/$urlSegmentStr/";
      $pager->setBaseUrl($baseUrl); 
    }
    $event->return = $pager->render($pageArray, $options); 
  }


}