.. _demands:

=======
Demands
=======

A demand is a configuration object used by the repository to decide which
news records should be fetched.

The default demand class implementation for the frontend output of news
is :php:`GeorgRinger\News\Domain\Model\Dto\NewsDemand`. It has a couple of
useful properties that can be used to filter news records, for example
:php:`$categories`, :php:`$searchFields`, :php:`$author` and many more.

There is also the property :php:`$customSettings` an array of custom settings
by extensions. You should use your extension name as key in this array.

Demand objects can be changed in a couple of ways, see below:

URL Parameter
=============

The URL parameter :code:`overwriteDemand` can be used to override properties
of the demand.

You can set this parameter in a Fluid link (see
:ref:`Set overwriteDemand in Frontend <overwriteDemand-in-frontend>`) or via
TypoScript in a typolink (See
:ref:`TypoScript reference: typolink <t3tsref:typolink>`).

It would even be possible to configure a :ref:`LinkHandler <linkhandler>`
for this parameter.

.. important::

   The checkbox :guilabel:`Disable override demand` in the list plugin
   (Tab Additional) must **not** be set to allow overriding the properties.

   Additionally the TypoScript setting
   :ref:`settings.disableOverrideDemand <tsDisableOverrideDemand>` must be set to
   :code:`0`.

Via TypoScript
==============

TypoScript can be used to define a class containing a
:ref:`custom implementation <demand_custom>`
of the demand object. This can be achieved by the TypoScript setting
:ref:`settings.demandClass <tsDemandClass>`.

Custom controllers
==================

The demand object can be used in a custom controller used in an extension
extending EXT:news. Read more about using a demand object in a custom
controller:
:ref:`Extension based on EXT:news: FilterController.php <extension_custom_controller>`.

.. _demand_factory:

Building a demand outside of a controller
=========================================

The service :php:`GeorgRinger\News\Service\NewsDemandFactory` turns a settings
array - typically the TypoScript settings of a news plugin - into a demand
object. Use it whenever news records have to be fetched outside of the
:php:`NewsController`, for example in a ViewHelper, a DataProcessor, a
middleware or an API endpoint.

The service applies the same rules as the plugin does: it respects
:ref:`settings.demandClass <tsDemandClass>`, resolves
:code:`settings.startingpoint` and :code:`settings.recursive` into the storage
page list and dispatches the
:php:`\GeorgRinger\News\Event\CreateDemandObjectFromSettingsEvent`. Listeners
registered for that event therefore also apply to demands built this way.

.. code-block:: php

   <?php

   namespace Vendor\MyNews\Api;

   use GeorgRinger\News\Domain\Repository\NewsRepository;
   use GeorgRinger\News\Service\NewsDemandFactory;

   class LatestNewsProvider
   {
      public function __construct(
         private readonly NewsDemandFactory $newsDemandFactory,
         private readonly NewsRepository $newsRepository
      ) {}

      public function findLatest(int $storagePid): array
      {
         $demand = $this->newsDemandFactory->create([
            'startingpoint' => (string)$storagePid,
            'orderBy' => 'datetime',
            'orderDirection' => 'desc',
            'limit' => 5,
         ]);

         return $this->newsRepository->findDemanded($demand)->toArray();
      }
   }

The second, optional argument of :php:`create()` defines the demand class to
use when the settings contain no :code:`demandClass` key:

.. code-block:: php

   $demand = $this->newsDemandFactory->create($settings, MyNewsDemand::class);

.. note::

   The protected method :php:`NewsController::createDemandObjectFromSettings()`
   is deprecated since version 14.1 and only delegates to this service. Custom
   controllers extending :php:`NewsController` should use the factory or the
   :php:`CreateDemandObjectFromSettingsEvent` instead of overriding it.

Events
======

Multiple events can change or use demand objects. For example the events of
the main actions in the :php:`NewsController`, for example
:php:`NewsListActionEvent` and :php:`NewsDetailActionEvent`. For more
information refer to the chapter :ref:`Events <events>`.

.. _demand_custom:

Custom demand class
===================

All custom frontend news demand classes must extend
:php:`GeorgRinger\News\Domain\Model\Dto\NewsDemand`. The demand object is
a simple configuration object. It should contain no business logic. For each
property there must be a setter and a getter.

Example:

.. code-block:: php

   <?php

   namespace Vendor\MyNews\Domain\Model\Dto;

   use \GeorgRinger\News\Domain\Model\Dto\NewsDemand;

   class MyNewsDemand extends NewsDemand {

      /**
      * @var string
      */
      protected $myCustomField = '';

      /**
      * Set myCustomField
      *
      * @param string $myCustomField
      * @return NewsDemand
      */
      public function setMyCustomField(string $myCustomField): NewsDemand
      {
         $this->myCustomField = $myCustomField;
         return $this;
      }

      /**
      * Get myCustomField
      *
      * @return string
      */
      public function getMyCustomField(): string
      {
         return $this->myCustomField;
      }
   }
