TYPO3 LTS 9

Aus Vosp.info
Wechseln zu: Navigation, Suche

Typo3

Benötigte Software & Konfiguration

apt-get install imagemagick  wget bash-completion zip unzip  apache2 libapache2-mod-php7.2 php7.2-cli  php7.2 php7.2-common  php7.2-imap php7.2-intl php7.2-mysql php7.2-readline  php7.2-soap php7.2-zip php7.2-zip php7.2-gd php7.2-xml php7.2-gd php7.2-json php7.2-opcache php-imagick  php7.2-curl php7.2-mbstring php7.2-bcmath php7.2-gmp php7.2-zip mysql-server composer

a2enmod deflate rewrite headers mime expires ssl

mysql_secure_installation

USE mysql;
UPDATE user SET plugin='mysql_native_password' WHERE User='root';
FLUSH PRIVILEGES;
exit;

#Falls Die Sicherheit für Passwörte nachträglich geändert werden muss.
mysql$ SHOW VARIABLES LIKE 'validate_password%';

mysql$ SET GLOBAL validate_password_policy=LOW;

vim /etc/mysql/mysql.conf.d/mysqld.cnf
#add 
[mysqld]
validate_password_policy=LOW





Typo3 Grundinstallation

cd in /var/www/domain
git clone https://github.com/TYPO3/TYPO3.CMS.git
cd TYPO3.CMS/
git fetch --tags
git tag --list
git checkout tags/v.9.5.1
#Externe Bibliotheken installieren
composer install

cd ..
ln -s TYPO3.CMS typo3_src
ln -s typo3_src/typo3 typo3
ln -s typo3_src/index.php .
touch FIRST_INSTALL



# /etc/php/7.2/apache2/php.ini
max_execution_time = 240
max_input_vars = 1500

Module

Sites

Sprachen lanugages

Achtung, derzeit existiert ein language fallback BUG :( 
https://forge.typo3.org/issues/86762
Seiten welche noch nicht übersetzt sind, kommen auf ne 404 Seite 
  1. erstmal müssen Sprachen angelegt werden auf der Seite 0 (ganz ganz oben in der Seiten Hierrachie) ... dann kann angefangen werden Sprachen über Sites zu konfigurieren
  2. die Startseite (auch wenn nur Verweis) muss übersetzt werden mit dem Seiten oder Listen Modul
page = PAGE
page {
	10 = FLUIDTEMPLATE
	10 {
		dataProcessing {

			120 = TYPO3\CMS\Frontend\DataProcessing\LanguageMenuProcessor
			120 {
			  languages = auto
			  as = ncMenuLanguage
			}

		}
	} 
}

Entwicklung

Fehlermeldungen (unvollstängig)

class CaptchaValidator extends AbstractValidator
	// .........
	public function isValid($word)
	{
		// .........
		if (!$isValid) {
			// Please enter the word or number as it appears in the image. The entered value was incorrect.
			$this->addError(
				$this->translateErrorMessage(
					'9221561048',
					'sr_freecap'
				),
				9221561048
			);
		}
		return $isValid;
	}
}
alle Fehler anzeigen die so existieren
<f:render partial="FormErrors"  arguments="{for: 'user'}" />

speziellen Fehler anzeigen
 <f:render partial="FieldError"  arguments="{for: 'user', field: 'captcha'}" />

Ableiten

Controller ableiten

TYPO3.CMS_7.6_Schnipsel#Backend_Klassen_ableiten

  • EXT/ancregister/Classes/Controller/NcFeuserEditController.php
<?php
namespace Netzcoop\Ancregister\Controller;

class NcFeuserEditController extends \Evoweb\SfRegister\Controller\FeuserEditController {
	
	public function formAction(\Evoweb\SfRegister\Domain\Model\FrontendUser $user = null)
	{
		 parent::formAction($user);
	}
}
  • ext_localconf.php
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects']['Evoweb\SfRegister\Controller\FeuserEditController'] = array(
	'className' => 'Netzcoop\Ancregister\Controller\NcFeuserEditController'
);


Sprache

Extension Sprache verändern

  • Configuration/TypoScript/setup.txt
plugin.tx_sfregister._LOCAL_LANG.de {
	error_required = Bitte füllen Sie dieses Feld aus.
}

debuggen

sql queries

$objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\ObjectManager');
$frontendUserRepository = $objectManager->get('TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository');
$users = $frontendUserRepository->findAll();
$queryParser = $objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class);
krexx($queryParser->convertQueryToDoctrineQueryBuilder($frontendUserRepository->createQuery())->getSQL());
// ....
$rows = $qB->execute()->fetchAll();
krexx($qB->getSQL());

Einstellungen einer Extension

  • sie befindet sich nicht mehr im Module Extension Manager sondern im Module Einstellungen, desweiteren wird sie durch De- und Neuinstallation der Extension die Einstellungen gelöscht!!! was sehr nervig sein kann
  • ext_conf_template.txt
# cat=basic/enable/010;; type=int+; label=LLL:EXT:ancfeloginaddon/Resources/Private/Language/locallang_be.xml:basic.showsentmailinfoPageId
showsentmailinfoPageId =

# cat=basic/enable/016;; type=int+; label=LLL:EXT:ancfeloginaddon/Resources/Private/Language/locallang_be.xml:basic.showAfterEmailloginPageId
showAfterEmailloginPageId =

# cat=basic/enable/020;; type=int+; label=LLL:EXT:ancfeloginaddon/Resources/Private/Language/locallang_be.xml:basic.forgotTimeForDeactivateLogin
forgotTimeForDeactivateLogin =

# cat=basic/enable/030;; type=string; label=LLL:EXT:ancfeloginaddon/Resources/Private/Language/locallang_be.xml:basic.mailsubject
mailsubject =

# cat=basic/enable/040;; type=string; label=LLL:EXT:ancfeloginaddon/Resources/Private/Language/locallang_be.xml:basic.mailsender
mailsender =

# cat=basic/enable/050;; type=user[Netzcoop\Ancfeloginaddon\ViewHelpers\TextArea->render]; label=LLL:EXT:ancfeloginaddon/Resources/Private/Language/locallang_be.xml:basic.mailtext
mailtext =

# cat=basic/enable/017;; type=options[gleich=0,ungleich=1]; label=LLL:EXT:ancfeloginaddon/Resources/Private/Language/locallang_be.xml:basic.emailcondition2
emailcondition2 =
$confArray = unserialize($GLOBALS["TYPO3_CONF_VARS"]["EXT"]["extConf"][strtolower($this->extensionName)]);


Scheduler

Task

  • Classes/Task/NcIndexTtnewsPdffilesForSearchTask.php
<?php

namespace Netzcoop\Ancext\Task;

/**
 * Description of NcIndexTtnewsPdfFilesForSearch
 *
 * @author nc
 */
class NcIndexTtnewsPdffilesForSearchTask extends \TYPO3\CMS\Scheduler\Task\AbstractTask {
    /**
     * @var string
     */
    protected $commandIdentifier;

    /**
     * @var array
     */
    protected $arguments = [];
	
    /**
     * Function execute from the Scheduler
     *
     * @return bool TRUE on successful execution
     */	
	public function execute() {
		krexx($this->getArguments());
		// ...		
		return true;		
	}
	
	
    /**
     * @param array $arguments
     */
    public function setArguments($arguments)
    {
        $this->arguments = $arguments;
    }

    /**
     * @return array
     */
    public function getArguments()
    {
        return $this->arguments;
    }	
	
    /**
     * Return a text representation of the selected command and arguments
     *
     * @return string Information to display
     */
    public function getAdditionalInformation()
	{
		$label = "spezielle Parameter: \n";
		foreach($this->commandIdentifier as $key => $value ) {
			$label .= "\t".$key.': '.$value."\n";
		}

        return $label;
    }	
	
	
    /**
     * @param string $commandIdentifier
     */
    public function setCommandIdentifier($commandIdentifier)
    {
        $this->commandIdentifier = $commandIdentifier;
    }

    /**
     * @return string
     */
    public function getCommandIdentifier()
    {
        return $this->commandIdentifier;
    }
}

AdditionalFieldProvider

diese Klasse ist für das Formular innerhalb eines Task zuständig, Felder werden definiert, validiert und gespeichert!

  • Classes/Task/NcIndexTtnewsPdffilesForSearchAdditionalFieldProvider.php
<?php

namespace Netzcoop\Ancext\Task;

class NcIndexTtnewsPdffilesForSearchAdditionalFieldProvider extends \TYPO3\CMS\Scheduler\AbstractAdditionalFieldProvider {

    /**
     * @var \TYPO3\CMS\Extbase\Mvc\Cli\CommandManager
     */
    protected $commandManager;

    /**
     * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
     */
    protected $objectManager;

    /**
     * @var \TYPO3\CMS\Extbase\Reflection\ReflectionService
     */
    protected $reflectionService;

    /**
     * @var \TYPO3\CMS\Extbase\Scheduler\Task
     */
    protected $task;

    /**
     * Default language file of the extension linkvalidator
     *
     * @var string
     */
    protected $languageFile = 'LLL:EXT:ancext/Resources/Private/Language/locallang.xlf';
	
	
	const EXT_KEY = 'ancext_task';
	
    /**
     * Constructor
     *
     * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
     * @param \TYPO3\CMS\Extbase\Mvc\Cli\CommandManager $commandManager
     * @param \TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService
     */
    public function __construct(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager = null, \TYPO3\CMS\Extbase\Mvc\Cli\CommandManager $commandManager = null, \TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService = null)
    {
        $this->objectManager = $objectManager ?? \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
        $this->commandManager = $commandManager ?? $this->objectManager->get(\TYPO3\CMS\Extbase\Mvc\Cli\CommandManager::class);
        $this->reflectionService = $reflectionService ?? $this->objectManager->get(\TYPO3\CMS\Extbase\Reflection\ReflectionService::class);
    }	
	
    /**
     * Render additional information fields within the scheduler backend.
     *
     * @param array &$taskInfo Array information of task to return
     * @param AbstractTask|null $task When editing, reference to the current task. NULL when adding.
     * @param SchedulerModuleController $schedulerModule Reference to the calling object (BE module of the Scheduler)
     * @return array Additional fields
     * @see \TYPO3\CMS\Scheduler\AdditionalFieldProvider#getAdditionalFields($taskInfo, $task, $schedulerModule)
     */
    public function getAdditionalFields(array &$taskInfo, $task, \TYPO3\CMS\Scheduler\Controller\SchedulerModuleController $schedulerModule)
    {
        $this->task = $task;
        if ($this->task !== null) {
            $this->task->setScheduler();
        }
		$argumentValues = $this->task->getArguments();
        $fields = [];
		$fields['ancext_task_description'] = $this->getCommandControllerActionDescriptionField();
		$fieldname = 'newsFilePath';
        $fields[$fieldname] = [
            'code' => '<input type="text" class="form-control" name="tx_scheduler['.self::EXT_KEY.'][arguments]['.htmlspecialchars($fieldname).']" value="' . $argumentValues[$fieldname] . '">',
            'label' => $this->languageFile.':ncIndexTtnewsPdffilesForSearchTask.field.newsFilePath',
            'cshKey' => '',
            'cshLabel' => $fieldname		
		];

        return $fields;
    }
	
    /**
     * Get description of selected command
     *
     * @return array
     */
    protected function getCommandControllerActionDescriptionField()
    {
        return [
            'code' => '',
            'label' => $this->languageFile.':ncIndexTtnewsPdffilesForSearchTask.description'
        ];
    }	
	
	public function validateAdditionalFields(array &$submittedData, \TYPO3\CMS\Scheduler\Controller\SchedulerModuleController $parentObject) 
	{
		if(is_dir($submittedData[self::EXT_KEY]['arguments']['newsFilePath']) 
			|| is_dir(\TYPO3\CMS\Core\Core\Environment::getPublicPath().'/'.$submittedData[self::EXT_KEY]['arguments']['newsFilePath']) 
			|| is_dir(\TYPO3\CMS\Core\Core\Environment::getProjectPath().'/'.$submittedData[self::EXT_KEY]['arguments']['newsFilePath'])
		) {
			return true;
		} else {
			$this->addMessage(
				$GLOBALS['LANG']->sL($this->languageFile . ':ncIndexTtnewsPdffilesForSearchTask.field.newsFilePath.error')
					.'( '.$submittedData[self::EXT_KEY]['arguments']['newsFilePath']
					.' || '.\TYPO3\CMS\Core\Core\Environment::getPublicPath().'/'.$submittedData[self::EXT_KEY]['arguments']['newsFilePath']
					.' || '.\TYPO3\CMS\Core\Core\Environment::getProjectPath().'/'.$submittedData[self::EXT_KEY]['arguments']['newsFilePath']
					.' )'
				,
				\TYPO3\CMS\Core\Messaging\FlashMessage::ERROR
			);			
			return false;
		}
	}
	public function saveAdditionalFields(array $submittedData, \TYPO3\CMS\Scheduler\Task\AbstractTask $task) 
	{
		if(is_dir(\TYPO3\CMS\Core\Core\Environment::getPublicPath().'/'.$submittedData[self::EXT_KEY]['arguments']['newsFilePath'])) {
			$submittedData[self::EXT_KEY]['arguments']['newsFilePath'] = \TYPO3\CMS\Core\Core\Environment::getPublicPath().'/'.$submittedData[self::EXT_KEY]['arguments']['newsFilePath'];
		} else if(is_dir(\TYPO3\CMS\Core\Core\Environment::getProjectPath().'/'.$submittedData[self::EXT_KEY]['arguments']['newsFilePath'])) {
			$submittedData[self::EXT_KEY]['arguments']['newsFilePath'] = \TYPO3\CMS\Core\Core\Environment::getProjectPath().'/'.$submittedData[self::EXT_KEY]['arguments']['newsFilePath'];
		}
		$task->setCommandIdentifier($submittedData[self::EXT_KEY]['arguments']);
		$task->setArguments((array)$submittedData[self::EXT_KEY]['arguments']);
	}
}

ext_localconf.php

$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][\Netzcoop\Ancext\Task\NcIndexTtnewsPdffilesForSearchTask::class] = array(
	'extension' => $_EXTKEY,
	'title' => 'LLL:EXT:'.$_EXTKEY.'/Resources/Private/Language/locallang.xlf:ncIndexTtnewsPdffilesForSearchTask.name',
	'description' => 'LLL:EXT:'.$_EXTKEY.'/Resources/Private/Language/locallang.xlf:ncIndexTtnewsPdffilesForSearchTask.description',
	'additionalFields' => \Netzcoop\Ancext\Task\NcIndexTtnewsPdffilesForSearchAdditionalFieldProvider::class
);


Backend

javascript im iframe im Backend einbinden

(Lösung von TYPO3.CMS_7.6_Schnipsel#Javascript_in_Iframe_im_Backend funzt nicht mehr )


  • ext_localconf.php
<?php 
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects']['TYPO3\CMS\Backend\Form\FormResultCompiler'] = array(
	'className' => 'Netzcoop\Extensionsname\Form\NcFormResultCompiler'
);
  • extensionsname/Classes/Form/NcFormResultCompiler.php
<?php
namespace Netzcoop\Extensionsname\Form;

class NcFormResultCompiler extends \TYPO3\CMS\Backend\Form\FormResultCompiler {

	public function printNeededJSFunctions() {	
			
		$pageRenderer = $this->getPageRenderer();
		$pageRenderer->addJsFile('EXT:ancextensionname/Resources/Public/JavaScript/ancbackendIframe.js');
			
		return parent::printNeededJSFunctions();
	}	
}

Extensions

scheduler

über EM Local

vhs

über EM Repository

includekrexx

über EM Repository

ws_scss

git clone https://github.com/svewap/ws_scss.git

gridelements

git clone https://github.com/TYPO3-extensions/gridelements.git

t3sbootstrap

lang (Sprache)

Die Sprachkonfiguration wurde in das installtool verlegt


alte Extension Anpassungen

@inject => @TYPO3\CMS\Extbase\Annotation\Inject
@ignorevalidation => @TYPO3\CMS\Extbase\Annotation\IgnoreValidation


render Mode deprecated

<f:flashMessages renderMode="div" />
<f:flashMessages  />

htmlEscape="false" deprecated

<f:translate key="email_user_salutation" htmlEscape="false"/>
<f:translate key="email_user_salutation" />

<f:translate key="email_user_salutation" htmlEscape="false"/>,

netz.coop Extensions

anclib

ancbasic

Konfiguration:

Beispiel Seitenbaum

id:0 nctypo

  • id:1; Typ: Standard; Verhalten: Als Anfang der Website benutzen; Ressourcen: ancbasic; Erscheinungsbild > Backend-Layout ancbasic layout template; add Template enthält fluid_styled_content,gridelements, t3sbootstrap, anclib, ancbasic
    • id:2; Typ: Ordner; Name: menu_main
      • id:4: Typ: Seite; Name: Seite 1
      • id:5: Typ: Seite; Name: Seite 2
        • id:7: Typ: Seite; Name: Seite 2.1
        • id:8: Typ: Seite; Name: Seite 2.2
        • id:9: Typ: Seite; Name: Seite 2.3
      • id:6: Typ: Seite; Name: Seite 3
    • id:3; Typ: Ordner; Name: menu_footer
      • id:10: Typ: Seite; Name: Kontakt
      • id:11: Typ: Seite; Name: Impressum
      • id:12: Typ: Seite; Name: Sitemap
      • id:13: Typ: Seite; Name: Datenschutz


Speaking URLS

Site management => Sites


Source Code Änderungen - deprecated ...

@TYPO3\CMS\Extbase\Annotation\Inject not @inject


Query Builder

Klassen

use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\Utility\GeneralUtility;

queryBuilder

$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
 ->getQueryBuilderForTable('tt_news');

FROM

$qB = $queryBuilder->from('tt_news', 'n');

WHERE

$qB->where(
      $queryBuilder->expr()->eq('pid', (int) $store_page_id)
);

$qB->andWhere(
 '  n.ncindexcontent like \'%' . $searchword . '%\' '
 );

Komplexe Abfragen

join
$qB->join(
     'n',
     'tt_news_cat_mm',
      'p2c' . $join_i,
       $queryBuilder->expr()->andX(
         $queryBuilder->expr()->eq('p2c' . $join_i . '.uid_local', $queryBuilder->quoteIdentifier('n.uid')),
         $queryBuilder->expr()->in('p2c' . $join_i . '.uid_foreign', trim(implode(",", $ORCategoriesArray),','))
        )
);


Equal
$qB->andWhere(
   $qB->expr()->eq('mm.uid_local', $uid)
);


Equal OR Equal
$qB->andWhere(
      $qB->expr()->orX(
           $qB->expr()->eq('nc.parent_category', 1),
           $qB->expr()->eq('nc.uid', 2)
      )
);


LIKE =
$qB->where(
     $qB->expr()->like(
            'email',
            $qB->createNamedParameter('%' . $qB->escapeLikeWildcards($domain) . '%')
      )
);
Limit
$qB->setMaxResults(10);
Offset
$qB->setFirstResult(20);
Select
$qB->select('*', 'n.uid as uid');
Order By
$qB->orderBy('crdate', 'DESC');
Ausführen
$rows = $qB->execute()->fetchAll();

Count Distinct AS COUNT

 $qB->addSelectLiteral(
    $queryBuilder->expr()->count('n.uid', 'count')
);
Count Ausführen
$rows = $qB->execute()->fetch();


Wenn Querybuilder keine Option ist

Klassen

use TYPO3\CMS\Core\Database\ConnectionPool;
Individuelle SELECT Abfragen
 protected $connectionPool;
  /**
     * @param string $table
     *
     * @return \TYPO3\CMS\Core\Database\Connection
     */
    protected function getConnection(string $table)
    {
        if (empty($this->connectionPool)) {
            $this->connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
        }

        return $this->connectionPool->getConnectionForTable($table);
    }

... 

 $statement =  'SELECT * fe_users.email  from fe_users   WHERE	 activated_on>0  ORDER BY domains ASC';
 $rows= $this->getConnection('fe_users')->executeQuery($statement)->fetchAll(\PDO::FETCH_BOTH);