Initial commit - Typo3 11.5.41
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _addCustomType:
|
||||
|
||||
=================
|
||||
Custom news types
|
||||
=================
|
||||
|
||||
Out of the box news comes with three types built in:
|
||||
|
||||
- "News": Default news record
|
||||
- "Internal Page": The news record is linked to a regular page.
|
||||
- "External Page": The news record is linked to an external URL.
|
||||
|
||||
To add your custom type, you have to follow the steps below.
|
||||
|
||||
.. note::
|
||||
In this example the new type will be called 'myCustomNewsType' and is configured to only show the fields 'title' and 'bodytext'.
|
||||
|
||||
1) Class Mapping
|
||||
----------------
|
||||
|
||||
Create a file `Configuration/Extbase/Persistence/Classes.php`
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
return [
|
||||
\GeorgRinger\News\Domain\Model\News::class => [
|
||||
'subclasses' => [
|
||||
3 => \Vendor\ExtName\Domain\Model\MyCustomNewsType::class,
|
||||
]
|
||||
],
|
||||
\Vendor\ExtName\Domain\Model\MyCustomNewsType::class => [
|
||||
'tableName' => 'tx_news_domain_model_news',
|
||||
'recordType' => 3,
|
||||
]
|
||||
];
|
||||
|
||||
2) TCA
|
||||
------
|
||||
|
||||
In this example, the new type is configured to show the fields `bodytext` and `title`.
|
||||
Therefore, create the file `Configuration/TCA/Overrides/tx_news_domain_model_news.php`.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
if (!defined('TYPO3_MODE')) {
|
||||
die ('Access denied.');
|
||||
}
|
||||
|
||||
$GLOBALS['TCA']['tx_news_domain_model_news']['columns']['type']['config']['items']['3'] =
|
||||
['myCustomNewsType', 3] ;
|
||||
|
||||
$GLOBALS['TCA']['tx_news_domain_model_news']['types']['3'] = [
|
||||
'showitem' => 'title, bodytext'
|
||||
];
|
||||
|
||||
3) Custom class
|
||||
---------------
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
|
||||
namespace Vendor\ExtName\Domain\Model;
|
||||
|
||||
class MyCustomNewsType extends \GeorgRinger\News\Domain\Model\News {
|
||||
|
||||
}
|
||||
|
||||
.. hint:: This is a very basic example.
|
||||
It would also be possible to use your custom news type to show custom fields.
|
||||
How to add custom fields to news is documented :ref:`here <proxyClassGenerator>`.
|
||||
@@ -0,0 +1,38 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _dataProcessing_AddNewsToMenuProcessor:
|
||||
|
||||
======================
|
||||
AddNewsToMenuProcessor
|
||||
======================
|
||||
|
||||
.. versionadded:: 7.2.0
|
||||
With version 7.2 a new data processor, :php:`AddNewsToMenuProcessor` has
|
||||
been added which is useful for detail pages to add the news record as
|
||||
fake menu entry.
|
||||
|
||||
This data processor can be used to add the currently displayed news record
|
||||
to a pages breadcrumb.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
.. code-block:: typoscript
|
||||
|
||||
10 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
|
||||
10 {
|
||||
as = breadcrumbMenu
|
||||
special = rootline
|
||||
# [...] further configuration
|
||||
}
|
||||
20 = GeorgRinger\News\DataProcessing\AddNewsToMenuProcessor
|
||||
20.menus = breadcrumbMenu,specialMenu
|
||||
|
||||
The property :typoscript:`menus` is a comma-separated list of
|
||||
:php:`MenuProcessors` that shall have the currently displayed news record
|
||||
attached as fake menu entry.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
See :ref:`Tutorial: Breadcrumb based on data processing and Fluid <breadcrumbFluid>`.
|
||||
@@ -0,0 +1,15 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _dataProcessing:
|
||||
|
||||
===============
|
||||
Data processing
|
||||
===============
|
||||
|
||||
The extension news currently contains the following data processors:
|
||||
|
||||
.. toctree::
|
||||
:titlesonly:
|
||||
|
||||
AddNewsToMenuProcessor
|
||||
LanguageMenuProcessor
|
||||
@@ -0,0 +1,46 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
|
||||
.. _dataProcessing_LanguageMenuProcessor:
|
||||
|
||||
=====================
|
||||
LanguageMenuProcessor
|
||||
=====================
|
||||
|
||||
.. versionadded:: 8.5.0
|
||||
With version 8.5 a new data processor, :php:`LanguageMenuProcessor` has
|
||||
been added.
|
||||
|
||||
This data processor renders a correct language menu on detail pages, which
|
||||
respects if a news record is translated or not.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
.. code-block:: typoscript
|
||||
|
||||
10 = TYPO3\CMS\Frontend\DataProcessing\LanguageMenuProcessor
|
||||
10 {
|
||||
as = languageMenu
|
||||
addQueryString = 1
|
||||
}
|
||||
|
||||
11 = GeorgRinger\News\DataProcessing\DisableLanguageMenuProcessor
|
||||
11.menus = languageMenu
|
||||
|
||||
The property :typoscript:`menus` is a comma-separated list of
|
||||
:php:`MenuProcessors`.
|
||||
|
||||
If a language menu is rendered on a detail page and the
|
||||
languages are configured to use a strict mode this data processor can be used:
|
||||
|
||||
If no translation exists, the property `available` in the
|
||||
:php:`LanguageMenuProcessor` is set to `false` - just as if the current page
|
||||
is not translated.
|
||||
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
See :ref:`SEO: Language menu on news detail pages <seo_language_menus>`.
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _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>`.
|
||||
|
||||
Hooks
|
||||
=====
|
||||
|
||||
Several hooks can be used to influence the demand object and its usage.
|
||||
|
||||
Hook findDemanded
|
||||
-----------------
|
||||
|
||||
The hook :code:`findDemanded` is very
|
||||
powerful. It allows to modify the query used to fetch the news records depending
|
||||
on values set in the demand object. You can find an example of how to use it in
|
||||
the chapter :ref:`Hooks: Example findDemanded <hooks_example_findDemanded>`.
|
||||
|
||||
Hook createDemandObjectFromSettings
|
||||
-----------------------------------
|
||||
|
||||
The hook :code:`createDemandObjectFromSettings`
|
||||
(:php:`$GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['Controller/NewsController.php']['createDemandObjectFromSettings']`)
|
||||
can be used to influence the settings of the demand object as it is used in
|
||||
most standard actions in the :php:`NewsController`, such as the
|
||||
:php:`listAction()`, :php:`selectedListAction()` and :php:`detailAction()`.
|
||||
|
||||
This hook can be used to insert settings from custom TypoScript or custom
|
||||
FlexForm configuration into the demand object. (See also
|
||||
:ref:`Extend FlexForms <extendFlexforms>`)
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _eventsTutorial:
|
||||
|
||||
======
|
||||
Events
|
||||
======
|
||||
|
||||
Several events can be used to modify the behaviour of EXT:news.
|
||||
|
||||
.. only:: html
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 1
|
||||
|
||||
Connect to Event
|
||||
----------------
|
||||
|
||||
To connect to an event, you need to register an event listener in your custom
|
||||
extension. All what it needs is an entry in your
|
||||
:file:`Configuration\Services.yaml` file:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
services:
|
||||
Vendor\Extension\EventListener\YourListener:
|
||||
tags:
|
||||
- name: event.listener
|
||||
identifier: 'your-self-choosen-identifier'
|
||||
method: 'methodToConnectToEvent'
|
||||
event: GeorgRinger\News\Event\NewsListActionEvent
|
||||
|
||||
Write your EventListener
|
||||
------------------------
|
||||
|
||||
An example event listener can look like this:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Vendor\Extension\EventListener;
|
||||
|
||||
use GeorgRinger\News\Event\NewsListActionEvent;
|
||||
|
||||
/**
|
||||
* Use NewsListActionEvent from ext:news
|
||||
*/
|
||||
class YourListener
|
||||
{
|
||||
/**
|
||||
* Do what you want...
|
||||
*/
|
||||
public function methodToConnectToEvent(NewsListActionEvent $event): void
|
||||
{
|
||||
$values = $event->getAssignedValues();
|
||||
|
||||
// Do some stuff
|
||||
|
||||
$event->setAssignedValues($values);
|
||||
}
|
||||
}
|
||||
|
||||
Available events
|
||||
----------------
|
||||
|
||||
Check out the :ref:`Events reference <referenceEvents>`.
|
||||
@@ -0,0 +1,134 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _extendFlexforms:
|
||||
|
||||
================
|
||||
Extend FlexForms
|
||||
================
|
||||
|
||||
Following fields of the plugin configuration can be extended without
|
||||
overriding the complete FlexForm configuration.
|
||||
|
||||
|
||||
.. only:: html
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 1
|
||||
|
||||
Selectbox "Sort by"
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
The sorting can be extended by adding the value to
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['orderByNews']
|
||||
|
||||
Default values are: tstamp,datetime,crdate,title
|
||||
|
||||
Additional Actions
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
If you need an additional action to select, you can extend it by using:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// Add an additional action: Key is "Controller->action", value is label
|
||||
$GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['switchableControllerActions']['newItems']['News->byFobar'] = 'A fobar action';
|
||||
|
||||
Remove fields in additional actions
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you define an additional action, you won't need all available fields which are available inside the FlexForms. If you want to hide some fields,
|
||||
take a look at the hook inside the class Hooks/BackendUtility.php:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['Hooks/BackendUtility.php']['updateFlexforms']
|
||||
|
||||
Additional Template Selector
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
If you need a kind of template selector inside a plugin, you can add
|
||||
your own selections by adding those to
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['templateLayouts']['myext'] = array('My Title', 'my value');
|
||||
|
||||
You can then access the variable in your template with
|
||||
:code:`{settings.templateLayout}` and use it for a condition or whatever.
|
||||
|
||||
Extend FlexForms with custom fields
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
If you need additional fields in the FlexForm configuration, this can be done by using a hook in the Core.
|
||||
|
||||
**Register the hook**
|
||||
|
||||
Add this to the ``ext_localconf.php`` of your extension:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][\TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools::class]['flexParsing'][]
|
||||
= \Vendor\ExtKey\Hooks\FlexFormHook::class;
|
||||
|
||||
**Add the hook**
|
||||
|
||||
Create the class ``FlexFormHook`` in your extension in ``Classes/Hooks/FlexFormHook.php`` and add the path to an additional
|
||||
FlexForm file.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
|
||||
namespace Vendor\ExtKey\Hooks;
|
||||
|
||||
use TYPO3\CMS\Core\Core\Environment;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
class FlexFormHook
|
||||
{
|
||||
/**
|
||||
* @param array $dataStructure
|
||||
* @param array $identifier
|
||||
* @return array
|
||||
*/
|
||||
public function parseDataStructureByIdentifierPostProcess(array $dataStructure, array $identifier): array
|
||||
{
|
||||
if ($identifier['type'] === 'tca' && $identifier['tableName'] === 'tt_content' && $identifier['dataStructureKey'] === 'news_pi1,list') {
|
||||
$file = Environment::getPublicPath() . '/typo3conf/ext/extKey/Configuration/Example.xml';
|
||||
$content = file_get_contents($file);
|
||||
if ($content) {
|
||||
$dataStructure['sheets']['extraEntry'] = GeneralUtility::xml2array($content);
|
||||
}
|
||||
}
|
||||
return $dataStructure;
|
||||
}
|
||||
}
|
||||
|
||||
**Create the FlexForm file**
|
||||
|
||||
Create the FlexForm file you just referenced in the hook. This can look like that.
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<extra>
|
||||
<ROOT>
|
||||
<TCEforms>
|
||||
<sheetTitle>Fo</sheetTitle>
|
||||
</TCEforms>
|
||||
<type>array</type>
|
||||
<el>
|
||||
<settings.postsPerPage>
|
||||
<TCEforms>
|
||||
<label>Max. number of posts to display per page</label>
|
||||
<config>
|
||||
<type>input</type>
|
||||
<size>2</size>
|
||||
<eval>int</eval>
|
||||
<default>3</default>
|
||||
</config>
|
||||
</TCEforms>
|
||||
</settings.postsPerPage>
|
||||
</el>
|
||||
</ROOT>
|
||||
</extra>
|
||||
|
||||
@@ -0,0 +1,312 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _ext-based-on-news:
|
||||
|
||||
Extensions based on EXT:news
|
||||
============================
|
||||
|
||||
If you are using news records but need custom configuration and custom settings, you should think of creating a separate extension. This is really simple, just take a look at the following example.
|
||||
|
||||
.. only:: html
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 1
|
||||
|
||||
Setup of the extension
|
||||
----------------------
|
||||
|
||||
As a demonstration, a new extension with the extension key ``news_filter`` will be created. The following files and its content is required.
|
||||
|
||||
ext_emconf.php
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
This file containts the basic information about its extension like name, version, author...
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
|
||||
$EM_CONF[$_EXTKEY] = [
|
||||
'title' => 'News Filter',
|
||||
'description' => 'News filtering',
|
||||
'category' => 'fe',
|
||||
'author' => 'John Doe',
|
||||
'author_email' => 'john@doe.net',
|
||||
'shy' => '',
|
||||
'dependencies' => '',
|
||||
'conflicts' => '',
|
||||
'priority' => '',
|
||||
'module' => '',
|
||||
'state' => 'stable',
|
||||
'internal' => '',
|
||||
'uploadfolder' => 0,
|
||||
'modify_tables' => '',
|
||||
'clearCacheOnLoad' => 1,
|
||||
'lockType' => '',
|
||||
'author_company' => '',
|
||||
'version' => '1.0.0',
|
||||
'constraints' => [
|
||||
'depends' => [
|
||||
'typo3' => '7.6.0-8.9.99',
|
||||
],
|
||||
'conflicts' => [],
|
||||
'suggests' => [],
|
||||
],
|
||||
'suggests' => [],
|
||||
];
|
||||
|
||||
ext_localconf.php
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
Create a basic plugin with one action called ``list``.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
defined('TYPO3_MODE') or die();
|
||||
|
||||
$boot = function () {
|
||||
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
|
||||
'GeorgRinger.news_filter',
|
||||
'Filter',
|
||||
[
|
||||
'Filter' => 'list',
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
$boot();
|
||||
unset($boot);
|
||||
|
||||
Configuration/TCA/Overrides/tt_content.php
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Register the plugin:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
defined('TYPO3_MODE') or die();
|
||||
|
||||
/***************
|
||||
* Plugin
|
||||
*/
|
||||
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
|
||||
'news_filter',
|
||||
'Filter',
|
||||
'Some demo'
|
||||
);
|
||||
|
||||
.. _extension_custom_controller:
|
||||
|
||||
Classes/Controller/FilterController.php
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Create a basic controller with the mentioned action.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\NewsFilter\Controller;
|
||||
|
||||
use GeorgRinger\News\Domain\Model\Dto\NewsDemand;
|
||||
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
|
||||
|
||||
class FilterController extends ActionController
|
||||
{
|
||||
|
||||
public function listAction()
|
||||
{
|
||||
$demand = $this->createDemandObject();
|
||||
$this->view->assignMultiple([
|
||||
'news' => $this->newsRepository->findDemanded($demand)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NewsDemand
|
||||
*/
|
||||
protected function createDemandObject()
|
||||
{
|
||||
$demand = $this->objectManager->get(NewsDemand::class);
|
||||
$demand->setLimit(10);
|
||||
|
||||
return $demand;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var \GeorgRinger\News\Domain\Repository\NewsRepository
|
||||
* @inject
|
||||
*/
|
||||
protected $newsRepository;
|
||||
}
|
||||
|
||||
Resources/Private/Templates/Filter/List.html
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Create the template:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<f:if condition="{news}">
|
||||
<f:then>
|
||||
<div class="row">
|
||||
<f:for each="{news}" as="newsItem">
|
||||
<div class="col-md-3">
|
||||
<h5>{newsItem.title}</h5>
|
||||
</div>
|
||||
</f:for>
|
||||
</div>
|
||||
</f:then>
|
||||
<f:else>
|
||||
<div class="alert alert-danger">No news found</div>
|
||||
</f:else>
|
||||
</f:if>
|
||||
|
||||
Setup
|
||||
-----
|
||||
|
||||
After enabling the extension in the Extension Manager and creating a plugin "Filter" on a page, you will see up to 10 news records of your system.
|
||||
|
||||
.. hint::
|
||||
|
||||
If your installation is based on composer, you need to add the classes to the PSR-4 section.
|
||||
|
||||
.. code-block:: js
|
||||
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"GeorgRinger\\NewsFilter\\": "typo3conf/ext/news_filter/Classes/"
|
||||
}
|
||||
}
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
There are multiple ways how to configure which news records should be shown. The fastest way is to hardcode the configuration.
|
||||
|
||||
Hardcode it
|
||||
^^^^^^^^^^^
|
||||
|
||||
By modifying the controller with the following code, you will change the output to show only those news records which fulfill the following requirements:
|
||||
|
||||
- The pid is ``123``
|
||||
- The author is ``John``
|
||||
- The id of the records is neither ``12`` nor ``45``.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
/**
|
||||
* @return NewsDemand
|
||||
*/
|
||||
protected function createDemandObject()
|
||||
{
|
||||
$demand = $this->objectManager->get(NewsDemand::class);
|
||||
$demand->setStoragePage('123');
|
||||
$demand->setAuthor('John');
|
||||
$demand->setHideIdList('12,45');
|
||||
|
||||
return $demand;
|
||||
}
|
||||
|
||||
Use FlexForms
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
Flexforms are a powerful tool to let editors configure plugins.
|
||||
|
||||
Configuration/TCA/Overrides/tt_content.php
|
||||
""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
Exchange the existing file with the following content.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
defined('TYPO3_MODE') or die();
|
||||
|
||||
/***************
|
||||
* Plugin
|
||||
*/
|
||||
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
|
||||
'news_filter',
|
||||
'Filter',
|
||||
'Some demo'
|
||||
);
|
||||
|
||||
$GLOBALS['TCA']['tt_content']['types']['list']['subtypes_excludelist']['newsfilter_filter'] = 'recursive,select_key,pages';
|
||||
$GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist']['newsfilter_filter'] = 'pi_flexform';
|
||||
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue('newsfilter_filter',
|
||||
'FILE:EXT:news_filter/Configuration/FlexForms/flexform_news_filter.xml');
|
||||
|
||||
Configuration/FlexForms/flexform_news_filter.xml
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
The syntax of ``FlexForms`` is identical to the one of ``TCA`` with the only difference that it is written in XML instead of PHP.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<T3DataStructure>
|
||||
<sheets>
|
||||
<sDEF>
|
||||
<ROOT>
|
||||
<TCEforms>
|
||||
<sheetTitle>LLL:EXT:news/Resources/Private/Language/locallang_be.xlf:flexforms_tab.settings
|
||||
</sheetTitle>
|
||||
</TCEforms>
|
||||
<type>array</type>
|
||||
<el>
|
||||
<settings.startingpoint>
|
||||
<TCEforms>
|
||||
<label>LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.startingpoint</label>
|
||||
<config>
|
||||
<type>group</type>
|
||||
<internal_type>db</internal_type>
|
||||
<allowed>pages</allowed>
|
||||
<size>3</size>
|
||||
<maxitems>50</maxitems>
|
||||
<minitems>0</minitems>
|
||||
<wizards>
|
||||
<suggest>
|
||||
<type>suggest</type>
|
||||
<default>
|
||||
<searchWholePhrase>1</searchWholePhrase>
|
||||
</default>
|
||||
</suggest>
|
||||
</wizards>
|
||||
</config>
|
||||
</TCEforms>
|
||||
</settings.startingpoint>
|
||||
</el>
|
||||
</ROOT>
|
||||
</sDEF>
|
||||
</sheets>
|
||||
</T3DataStructure>
|
||||
|
||||
Important is that each element's name is prepended with ``settings.``.
|
||||
|
||||
.. hint::
|
||||
Take a look at the FlexForms of the news extension for inspiration. You can even just copy & paste settings from there.
|
||||
The file can be found at ``EXT:news/Configuration/FlexForms/flexform_news.xml``.
|
||||
|
||||
|
||||
Classes/Controller/FilterController.php
|
||||
"""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
Adopt the controller to use the settings instead of the hardcoded ones.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
/**
|
||||
* @return NewsDemand
|
||||
*/
|
||||
protected function createDemandObject()
|
||||
{
|
||||
$demand = $this->objectManager->get(NewsDemand::class);
|
||||
// Because of the naming "<settings.startingpoint>", you can use $this->settings['startingpoint']
|
||||
$demand->setStoragePage($this->settings['startingpoint']);
|
||||
$demand->setLimit(10);
|
||||
|
||||
return $demand;
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _hooks:
|
||||
|
||||
=====
|
||||
Hooks
|
||||
=====
|
||||
|
||||
Several hooks can be used to modify the behaviour of EXT:news.
|
||||
|
||||
.. only:: html
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 1
|
||||
|
||||
Hooks
|
||||
-----
|
||||
|
||||
.. _hooks_example_findDemanded:
|
||||
|
||||
Domain/Repository/AbstractDemandedRepository.php findDemanded
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This hook is very powerful, as it allows to modify the query used to fetch the news records.
|
||||
|
||||
Example
|
||||
"""""""
|
||||
This examples modifies the query and adds a constraint that only news records are shown which contain the word *yeah*.
|
||||
|
||||
|
||||
First, register your implementation in the file ``ext_localconf.php``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
defined('TYPO3_MODE') or die();
|
||||
|
||||
$GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['Domain/Repository/AbstractDemandedRepository.php']['findDemanded'][$_EXTKEY]
|
||||
= 'YourVendor\\Extkey\\Hooks\\Repository->modify';
|
||||
|
||||
Now create the file ``Classes/Hooks/Repository.php``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
|
||||
namespace YourVendor\Extkey\Hooks;
|
||||
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use \GeorgRinger\News\Domain\Repository\NewsRepository;
|
||||
|
||||
class Repository {
|
||||
|
||||
public function modify(array $params, NewsRepository $newsRepository) {
|
||||
$this->updateConstraints($params['demand'], $params['respectEnableFields'], $params['query'], $params['constraints']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \GeorgRinger\News\Domain\Model\Dto\NewsDemand $demand
|
||||
* @param bool $respectEnableFields
|
||||
* @param \TYPO3\CMS\Extbase\Persistence\QueryInterface $query
|
||||
* @param array $constraints
|
||||
*/
|
||||
protected function updateConstraints($demand, $respectEnableFields, \TYPO3\CMS\Extbase\Persistence\QueryInterface $query, array &$constraints) {
|
||||
$subject = 'yeah';
|
||||
$constraints[] = $query->like('title', '%' . $subject . '%');
|
||||
}
|
||||
}
|
||||
|
||||
.. hint:: Please change the vendor and extension key to your real life code.
|
||||
|
||||
Controller/NewsController overrideSettings
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Use this hook to change the final settings which are for building queries, for the template, ...
|
||||
|
||||
Example
|
||||
"""""""
|
||||
This examples modifies the settings by changing the category selection.
|
||||
|
||||
First, register your implementation in the file ``ext_localconf.php``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
defined('TYPO3_MODE') or die();
|
||||
|
||||
$GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['Controller/NewsController.php']['overrideSettings'][$_EXTKEY]
|
||||
= 'YourVendor\\Extkey\\Hooks\\NewsControllerSettings->modify';
|
||||
|
||||
Now create the file ``Classes/Hooks/NewsControllerSettings.php``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
|
||||
namespace YourVendor\Extkey\Hooks;
|
||||
|
||||
class NewsControllerSettings {
|
||||
|
||||
public function modify(array $params) {
|
||||
$settings = $params['originalSettings'];
|
||||
$settings['categories'] = '2,3';
|
||||
|
||||
return $settings;
|
||||
}
|
||||
}
|
||||
|
||||
.. hint:: Please change the vendor and extension key to your real life code.
|
||||
|
||||
|
||||
121
typo3conf/ext/news/Documentation/Tutorials/ExtendNews/Index.rst
Normal file
121
typo3conf/ext/news/Documentation/Tutorials/ExtendNews/Index.rst
Normal file
@@ -0,0 +1,121 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _tutorialExtendNews:
|
||||
|
||||
===========
|
||||
Extend News
|
||||
===========
|
||||
|
||||
.. container:: row m-0 p-0
|
||||
|
||||
.. container:: col-12 col-md-6 pl-0 pr-3 py-3 m-0
|
||||
|
||||
.. container:: card px-0 h-100
|
||||
|
||||
.. rst-class:: card-header h3
|
||||
|
||||
.. rubric:: :ref:`Custom extension <ext-based-on-news>`
|
||||
|
||||
.. container:: card-body
|
||||
|
||||
All changes listed on this page should be done in a custom
|
||||
extension that extends EXT:news. Learn how to set it up.
|
||||
|
||||
.. container:: col-12 col-md-6 pl-0 pr-3 py-3 m-0
|
||||
|
||||
.. container:: card px-0 h-100
|
||||
|
||||
.. rst-class:: card-header h3
|
||||
|
||||
.. rubric:: :ref:`Extend FlexForms <extendFlexforms>`
|
||||
|
||||
.. container:: card-body
|
||||
|
||||
Influence the fields available in the plugins backend FlexForm.
|
||||
|
||||
.. container:: col-12 col-md-6 pl-0 pr-3 py-3 m-0
|
||||
|
||||
.. container:: card px-0 h-100
|
||||
|
||||
.. rst-class:: card-header h3
|
||||
|
||||
.. rubric:: :ref:`Events <eventsTutorial>`
|
||||
|
||||
.. container:: card-body
|
||||
|
||||
Extend the code of EXT:news by using PSR-14 Events.
|
||||
|
||||
.. container:: col-12 col-md-6 pl-0 pr-3 py-3 m-0
|
||||
|
||||
.. container:: card px-0 h-100
|
||||
|
||||
.. rst-class:: card-header h3
|
||||
|
||||
.. rubric:: :ref:`Hooks <hooks>`
|
||||
|
||||
.. container:: card-body
|
||||
|
||||
If there is no PSR-14 Event, try using a hook instead.
|
||||
|
||||
.. container:: col-12 col-md-6 pl-0 pr-3 py-3 m-0
|
||||
|
||||
.. container:: card px-0 h-100
|
||||
|
||||
.. rst-class:: card-header h3
|
||||
|
||||
.. rubric:: :ref:`Demands <demands>`
|
||||
|
||||
.. container:: card-body
|
||||
|
||||
Learn how to filter and sort the displayed news using demands.
|
||||
|
||||
.. container:: col-12 col-md-6 pl-0 pr-3 py-3 m-0
|
||||
|
||||
.. container:: card px-0 h-100
|
||||
|
||||
.. rst-class:: card-header h3
|
||||
|
||||
.. rubric:: :ref:`Data processing <dataProcessing>`
|
||||
|
||||
.. container:: card-body
|
||||
|
||||
Display news in menus using data processing
|
||||
|
||||
.. container:: col-12 col-md-6 pl-0 pr-3 py-3 m-0
|
||||
|
||||
.. container:: card px-0 h-100
|
||||
|
||||
.. rst-class:: card-header h3
|
||||
|
||||
.. rubric:: :ref:`Add custom fields <proxyClassGenerator>`
|
||||
|
||||
.. container:: card-body
|
||||
|
||||
Learn how to add custom fields to news records and extend the
|
||||
:php:`News` model using the ProxyClassGenerator
|
||||
|
||||
.. container:: col-12 col-md-6 pl-0 pr-3 py-3 m-0
|
||||
|
||||
.. container:: card px-0 h-100
|
||||
|
||||
.. rst-class:: card-header h3
|
||||
|
||||
.. rubric:: :ref:`Custom news types <addCustomType>`
|
||||
|
||||
.. container:: card-body
|
||||
|
||||
Add additional custom news types
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 5
|
||||
:titlesonly:
|
||||
:hidden:
|
||||
|
||||
ExtensionBasedOnNews/Index
|
||||
ExtendFlexforms/Index
|
||||
Events/Index
|
||||
Hooks/Index
|
||||
Demands/Index
|
||||
DataProcessing/Index
|
||||
ProxyClassGenerator/Index
|
||||
AddCustomType/Index
|
||||
@@ -0,0 +1,182 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _proxyClassGenerator:
|
||||
|
||||
=================
|
||||
Add custom fields
|
||||
=================
|
||||
|
||||
Follow this chapter to learn how to add new fields or actions.
|
||||
|
||||
It is important to know how this concept is implemented. If a class should be extended, EXT:news will generate
|
||||
a new file containing the original class of the extension itself and all other classes which should extended it.
|
||||
|
||||
Take a look at the following 2 working examples:
|
||||
|
||||
- Add relation to a FE user: https://github.com/cyberhouse/t3ext-newsauthor
|
||||
- Add an image gallery to a news record: https://github.com/cyberhouse/t3ext-news_gallery
|
||||
|
||||
.. attention:: This generator works only with the news version 3.2.0 or higher.
|
||||
|
||||
.. warning:: The drawbacks are easy to identify:
|
||||
|
||||
- Don't use any use statements as those are currently ignored!
|
||||
- It is not possible to override an actual method or property!
|
||||
|
||||
The files are saved by using the Caching Framework in the directory :file:`typo3temp/Cache/Code/news`.
|
||||
|
||||
.. only:: html
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 1
|
||||
|
||||
1) Add a new field in the backend
|
||||
---------------------------------
|
||||
To add new fields, use either the extension `extension_builder <http://typo3.org/extensions/repository/view/extension_builder>`__ or create the extension from scratch.
|
||||
|
||||
The extension key used in this examples is :code:`eventnews`.
|
||||
|
||||
Create the fields
|
||||
^^^^^^^^^^^^^^^^^
|
||||
3 files are basically all what you need:
|
||||
|
||||
ext_emconf.php
|
||||
""""""""""""""
|
||||
The file :file:`ext_emconf.php` holds all basic information about the extension like the title, description and version number.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
|
||||
$EM_CONF[$_EXTKEY] = array(
|
||||
'title' => 'news events',
|
||||
'description' => 'Events for news',
|
||||
'category' => 'plugin',
|
||||
'author' => 'Georg Ringer',
|
||||
'author_email' => '',
|
||||
'state' => 'alpha',
|
||||
'uploadfolder' => FALSE,
|
||||
'createDirs' => '',
|
||||
'clearCacheOnLoad' => TRUE,
|
||||
'version' => '1.0.0',
|
||||
'constraints' => array(
|
||||
'depends' => array(
|
||||
'typo3' => '7.6.13-8.7.99',
|
||||
'news' => '6.2.0-6.9.99',
|
||||
),
|
||||
'conflicts' => array(),
|
||||
'suggests' => array(),
|
||||
),
|
||||
);
|
||||
|
||||
SQL definition
|
||||
""""""""""""""
|
||||
Create the file :file:`ext_tables.sql` in the root of the extension directory with the following content:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
|
||||
# Table structure for table 'tx_news_domain_model_news '
|
||||
#
|
||||
CREATE TABLE tx_news_domain_model_news (
|
||||
location_simple varchar(255) DEFAULT '' NOT NULL
|
||||
);
|
||||
|
||||
|
||||
TCA definition
|
||||
""""""""""""""
|
||||
The TCA defines which tables and fields are available in the backend and how those are rendered (e.g. as input field, textarea, select field, ...).
|
||||
|
||||
In this example, the table :sql:`tx_news_domain_model_news` will be extended by a simple input field.
|
||||
Therefore, create the file :file:`Configuration/TCA/Overrides/tx_news_domain_model_news.php`.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
defined('TYPO3_MODE') or die();
|
||||
|
||||
$fields = array(
|
||||
'location_simple' => array(
|
||||
'exclude' => 1,
|
||||
'label' => 'My location',
|
||||
'config' => array(
|
||||
'type' => 'input',
|
||||
'size' => 15
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('tx_news_domain_model_news', $fields);
|
||||
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes('tx_news_domain_model_news', 'location_simple');
|
||||
|
||||
|
||||
Install the extension
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
Now you should be able to install the extension and if you open a news record, you should see the new field in the last tab.
|
||||
|
||||
.. TODO: what if something wrong
|
||||
|
||||
|
||||
2) Register the class
|
||||
---------------------
|
||||
|
||||
Until now, EXT:news won't use the new field because it doesn't know about it. To change that, you need to register your new model.
|
||||
|
||||
Registration
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Create the file :file:`ext_localconf.php` in the root of the extension:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
defined('TYPO3_MODE') or die();
|
||||
|
||||
$GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['classes']['Domain/Model/News']['eventnews'] = 'eventnews';
|
||||
|
||||
:php:`Domain/Model/News` is the namespace to the class which should be extended and :code:`eventnews` is the extension key.
|
||||
|
||||
Custom class
|
||||
^^^^^^^^^^^^
|
||||
As the class :php:`Domain/Model/News` should be extended, create a file at the same path in the own extension which is
|
||||
:file:`typo3conf/ext/eventnews/Classes/Domain/Model/News.php`:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
|
||||
namespace GeorgRinger\Eventnews\Domain\Model;
|
||||
|
||||
/**
|
||||
* News
|
||||
*/
|
||||
class News extends \GeorgRinger\News\Domain\Model\News {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $locationSimple;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLocationSimple() {
|
||||
return $this->locationSimple;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $locationSimple
|
||||
*/
|
||||
public function setLocationSimple($locationSimple) {
|
||||
$this->locationSimple = $locationSimple;
|
||||
}
|
||||
}
|
||||
|
||||
.. hint::
|
||||
If you are using the extension :file:`extension_builder`, this class might have been created for you already.
|
||||
|
||||
Clear system cache
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
Now it is time to clear the :guilabel:`system cache`, either via the dropdown in the backend or in the module :guilabel:`Admin Tools`.
|
||||
|
||||
Reference in New Issue
Block a user