[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |