[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/src/MVC/View/ -> JsonApiView.php (source)

   1  <?php
   2  
   3  /**
   4   * Joomla! Content Management System
   5   *
   6   * @copyright  (C) 2019 Open Source Matters, Inc. <https://www.joomla.org>
   7   * @license    GNU General Public License version 2 or later; see LICENSE.txt
   8   */
   9  
  10  namespace Joomla\CMS\MVC\View;
  11  
  12  use Joomla\CMS\Document\JsonapiDocument;
  13  use Joomla\CMS\Factory;
  14  use Joomla\CMS\MVC\View\Event\OnGetApiFields;
  15  use Joomla\CMS\Router\Exception\RouteNotFoundException;
  16  use Joomla\CMS\Serializer\JoomlaSerializer;
  17  use Joomla\CMS\Uri\Uri;
  18  use Tobscure\JsonApi\AbstractSerializer;
  19  use Tobscure\JsonApi\Collection;
  20  use Tobscure\JsonApi\Resource;
  21  
  22  // phpcs:disable PSR1.Files.SideEffects
  23  \defined('_JEXEC') or die;
  24  // phpcs:enable PSR1.Files.SideEffects
  25  
  26  /**
  27   * Base class for a Joomla Json List View
  28   *
  29   * Class holding methods for displaying presentation data.
  30   *
  31   * @since  4.0.0
  32   */
  33  abstract class JsonApiView extends JsonView
  34  {
  35      /**
  36       * The active document object (Redeclared for typehinting)
  37       *
  38       * @var    JsonapiDocument
  39       * @since  3.0
  40       */
  41      public $document;
  42  
  43      /**
  44       * The content type
  45       *
  46       * @var  string
  47       */
  48      protected $type;
  49  
  50      /**
  51       * Item relationship
  52       *
  53       * @var  array
  54       *
  55       * @since  4.0.0
  56       */
  57      protected $relationship = [];
  58  
  59      /**
  60       * Serializer data
  61       *
  62       * @var    AbstractSerializer
  63       * @since  4.0.0
  64       */
  65      protected $serializer;
  66  
  67      /**
  68       * The fields to render item in the documents
  69       *
  70       * @var    array
  71       * @since  4.0.0
  72       */
  73      protected $fieldsToRenderItem = [];
  74  
  75      /**
  76       * The fields to render items in the documents
  77       *
  78       * @var    array
  79       * @since  4.0.0
  80       */
  81      protected $fieldsToRenderList = [];
  82  
  83      /**
  84       * Constructor.
  85       *
  86       * @param   array  $config  A named configuration array for object construction.
  87       *                          contentType: the name (optional) of the content type to use for the serialization
  88       *
  89       * @since   4.0.0
  90       */
  91      public function __construct($config = [])
  92      {
  93          if (\array_key_exists('contentType', $config)) {
  94              $this->type = $config['contentType'];
  95          }
  96  
  97          if ($this->serializer === null) {
  98              $this->serializer = new JoomlaSerializer($this->type);
  99          }
 100  
 101          parent::__construct($config);
 102      }
 103  
 104      /**
 105       * Execute and display a template script.
 106       *
 107       * @param   array|null  $items  Array of items
 108       *
 109       * @return  string
 110       *
 111       * @since   4.0.0
 112       */
 113      public function displayList(array $items = null)
 114      {
 115          /** @var \Joomla\CMS\MVC\Model\ListModel $model */
 116          $model = $this->getModel();
 117  
 118          // Get page query
 119          $currentUrl = Uri::getInstance();
 120          $currentPageDefaultInformation = ['offset' => 0, 'limit' => 20];
 121          $currentPageQuery = $currentUrl->getVar('page', $currentPageDefaultInformation);
 122  
 123          if ($items === null) {
 124              $items = [];
 125  
 126              foreach ($model->getItems() as $item) {
 127                  $items[] = $this->prepareItem($item);
 128              }
 129          }
 130  
 131          $pagination = $model->getPagination();
 132  
 133          // Check for errors.
 134          if (\count($errors = $this->get('Errors'))) {
 135              throw new GenericDataException(implode("\n", $errors), 500);
 136          }
 137  
 138          if ($this->type === null) {
 139              throw new \RuntimeException('Content type missing');
 140          }
 141  
 142          // Set up links for pagination
 143          $totalItemsCount = ($pagination->pagesTotal * $pagination->limit);
 144  
 145          $this->document->addMeta('total-pages', $pagination->pagesTotal)
 146              ->addLink('self', (string) $currentUrl);
 147  
 148          // Check for first and previous pages
 149          if ($pagination->limitstart > 0) {
 150              $firstPage = clone $currentUrl;
 151              $firstPageQuery = $currentPageQuery;
 152              $firstPageQuery['offset'] = 0;
 153              $firstPage->setVar('page', $firstPageQuery);
 154  
 155              $previousPage = clone $currentUrl;
 156              $previousPageQuery = $currentPageQuery;
 157              $previousOffset = $currentPageQuery['offset'] - $pagination->limit;
 158              $previousPageQuery['offset'] = $previousOffset >= 0 ? $previousOffset : 0;
 159              $previousPage->setVar('page', $previousPageQuery);
 160  
 161              $this->document->addLink('first', $this->queryEncode((string) $firstPage))
 162                  ->addLink('previous', $this->queryEncode((string) $previousPage));
 163          }
 164  
 165          // Check for next and last pages
 166          if ($pagination->limitstart + $pagination->limit < $totalItemsCount) {
 167              $nextPage = clone $currentUrl;
 168              $nextPageQuery = $currentPageQuery;
 169              $nextOffset = $currentPageQuery['offset'] + $pagination->limit;
 170              $nextPageQuery['offset'] = ($nextOffset > ($pagination->pagesTotal * $pagination->limit)) ? $pagination->pagesTotal - $pagination->limit : $nextOffset;
 171              $nextPage->setVar('page', $nextPageQuery);
 172  
 173              $lastPage = clone $currentUrl;
 174              $lastPageQuery = $currentPageQuery;
 175              $lastPageQuery['offset'] = ($pagination->pagesTotal - 1) * $pagination->limit;
 176              $lastPage->setVar('page', $lastPageQuery);
 177  
 178              $this->document->addLink('next', $this->queryEncode((string) $nextPage))
 179                  ->addLink('last', $this->queryEncode((string) $lastPage));
 180          }
 181  
 182          $eventData = ['type' => OnGetApiFields::LIST, 'fields' => $this->fieldsToRenderList, 'context' => $this->type];
 183          $event     = new OnGetApiFields('onApiGetFields', $eventData);
 184  
 185          /** @var OnGetApiFields $eventResult */
 186          $eventResult = Factory::getApplication()->getDispatcher()->dispatch('onApiGetFields', $event);
 187  
 188          $collection = (new Collection($items, $this->serializer))
 189              ->fields([$this->type => $eventResult->getAllPropertiesToRender()]);
 190  
 191          if (!empty($this->relationship)) {
 192              $collection->with($this->relationship);
 193          }
 194  
 195          // Set the data into the document and render it
 196          $this->document->setData($collection);
 197  
 198          return $this->document->render();
 199      }
 200  
 201      /**
 202       * Execute and display a template script.
 203       *
 204       * @param   object  $item  Item
 205       *
 206       * @return  string
 207       *
 208       * @since   4.0.0
 209       */
 210      public function displayItem($item = null)
 211      {
 212          if ($item === null) {
 213              /** @var \Joomla\CMS\MVC\Model\AdminModel $model */
 214              $model = $this->getModel();
 215              $item  = $this->prepareItem($model->getItem());
 216          }
 217  
 218          if ($item->id === null) {
 219              throw new RouteNotFoundException('Item does not exist');
 220          }
 221  
 222          // Check for errors.
 223          if (\count($errors = $this->get('Errors'))) {
 224              throw new GenericDataException(implode("\n", $errors), 500);
 225          }
 226  
 227          if ($this->type === null) {
 228              throw new \RuntimeException('Content type missing');
 229          }
 230  
 231          $eventData = [
 232              'type' => OnGetApiFields::ITEM,
 233              'fields' => $this->fieldsToRenderItem,
 234              'relations' => $this->relationship,
 235              'context' => $this->type,
 236          ];
 237          $event     = new OnGetApiFields('onApiGetFields', $eventData);
 238  
 239          /** @var OnGetApiFields $eventResult */
 240          $eventResult = Factory::getApplication()->getDispatcher()->dispatch('onApiGetFields', $event);
 241  
 242          $element = (new Resource($item, $this->serializer))
 243              ->fields([$this->type => $eventResult->getAllPropertiesToRender()]);
 244  
 245          if (!empty($this->relationship)) {
 246              $element->with($eventResult->getAllRelationsToRender());
 247          }
 248  
 249          $this->document->setData($element);
 250          $this->document->addLink('self', Uri::current());
 251  
 252          return $this->document->render();
 253      }
 254  
 255      /**
 256       * Prepare item before render.
 257       *
 258       * @param   object  $item  The model item
 259       *
 260       * @return  object
 261       *
 262       * @since   4.0.0
 263       */
 264      protected function prepareItem($item)
 265      {
 266          return $item;
 267      }
 268  
 269      /**
 270       * Encode square brackets in the URI query, according to JSON API specification.
 271       *
 272       * @param   string  $query  The URI query
 273       *
 274       * @return  string
 275       *
 276       * @since   4.0.0
 277       */
 278      protected function queryEncode($query)
 279      {
 280          return str_replace(array('[', ']'), array('%5B', '%5D'), $query);
 281      }
 282  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer