Zwischenstand
This commit is contained in:
parent
fde2759722
commit
ce6b9e38dc
51
.editorconfig
Normal file
51
.editorconfig
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# EditorConfig is awesome: http://EditorConfig.org
|
||||||
|
|
||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# Unix-style newlines with a newline ending every file
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
# TS/JS-Files
|
||||||
|
[*.{ts,js}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# JSON-Files
|
||||||
|
[*.json]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
# ReST-Files
|
||||||
|
[*.rst]
|
||||||
|
indent_size = 3
|
||||||
|
max_line_length = 80
|
||||||
|
|
||||||
|
# YAML-Files
|
||||||
|
[*.{yaml,yml}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# package.json
|
||||||
|
[package.json]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# TypoScript
|
||||||
|
[*.{typoscript,tsconfig}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# XLF-Files
|
||||||
|
[*.xlf]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
# SQL-Files
|
||||||
|
[*.sql]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# .htaccess
|
||||||
|
[{_.htaccess,.htaccess}]
|
||||||
|
indent_style = tab
|
@ -7,10 +7,10 @@
|
|||||||
* LICENSE file that was distributed with this source code.
|
* LICENSE file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace WapplerSystems\BookmarkPages\Controller;
|
namespace WapplerSystems\BookmarksLikesRatings\Controller;
|
||||||
|
|
||||||
use WapplerSystems\BookmarkPages\Model\Bookmark;
|
use WapplerSystems\BookmarksLikesRatings\Model\Bookmark;
|
||||||
use WapplerSystems\BookmarkPages\Model\Bookmarks;
|
use WapplerSystems\BookmarksLikesRatings\Model\Bookmarks;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
|
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
|
||||||
|
|
||||||
|
1316
Classes/Controller/VoteController.php
Normal file
1316
Classes/Controller/VoteController.php
Normal file
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@
|
|||||||
* LICENSE file that was distributed with this source code.
|
* LICENSE file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace WapplerSystems\BookmarkPages\Model;
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Model;
|
||||||
|
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ class Bookmark
|
|||||||
* @param null $pid page id
|
* @param null $pid page id
|
||||||
* @param null $parameter
|
* @param null $parameter
|
||||||
*/
|
*/
|
||||||
public function __construct($url, $title=null, $pid=null, $parameter=null)
|
public function __construct($url, $title = null, $pid = null, $parameter = null)
|
||||||
{
|
{
|
||||||
if (is_array($url)) {
|
if (is_array($url)) {
|
||||||
$this->id = $url['id'];
|
$this->id = $url['id'];
|
||||||
@ -223,7 +223,7 @@ class Bookmark
|
|||||||
*/
|
*/
|
||||||
protected static function getCurrentPageTitle()
|
protected static function getCurrentPageTitle()
|
||||||
{
|
{
|
||||||
return self::getFrontend()->altPageTitle? self::getFrontend()->altPageTitle : self::getFrontend()->page['title'];
|
return self::getFrontend()->altPageTitle ? self::getFrontend()->altPageTitle : self::getFrontend()->page['title'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
@ -7,7 +7,7 @@
|
|||||||
* LICENSE file that was distributed with this source code.
|
* LICENSE file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace WapplerSystems\BookmarkPages\Model;
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Model;
|
||||||
|
|
||||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||||
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
|
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
|
410
Classes/Domain/Model/Rating.php
Normal file
410
Classes/Domain/Model/Rating.php
Normal file
@ -0,0 +1,410 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Model;
|
||||||
|
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Repository\VoteRepository;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Service\JsonService;
|
||||||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use TYPO3\CMS\Extbase\Annotation as Extbase;
|
||||||
|
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
|
||||||
|
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
|
||||||
|
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||||
|
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model for object rating
|
||||||
|
*
|
||||||
|
* @copyright Copyright belongs to the respective authors
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GNU Public License, version 2
|
||||||
|
* @entity
|
||||||
|
*/
|
||||||
|
class Rating extends AbstractEntity
|
||||||
|
{
|
||||||
|
//TODO check deleted referenced records
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Extbase\Validate("\WapplerSystems\BookmarksLikesRatings\Domain\Validator\RatingobjectValidator")
|
||||||
|
* @Extbase\Validate("NotEmpty")
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject
|
||||||
|
*/
|
||||||
|
protected $ratingobject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ratings uid of this object
|
||||||
|
*
|
||||||
|
* @Extbase\Validate("NumberRange", options={"minimum": 1})
|
||||||
|
* @Extbase\Validate("NotEmpty")
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $ratedobjectuid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ratings of this object
|
||||||
|
*
|
||||||
|
* @Extbase\ORM\Lazy
|
||||||
|
* @Extbase\ORM\Cascade("remove")
|
||||||
|
* @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote>
|
||||||
|
*/
|
||||||
|
protected $votes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
|
||||||
|
*/
|
||||||
|
protected $objectManager;
|
||||||
|
/**
|
||||||
|
* @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
|
||||||
|
*/
|
||||||
|
/** @noinspection PhpUnused */
|
||||||
|
public function injectObjectManager(ObjectManagerInterface $objectManager)
|
||||||
|
{
|
||||||
|
$this->objectManager = $objectManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Service\JsonService
|
||||||
|
*/
|
||||||
|
protected $jsonService;
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Service\JsonService $jsonService
|
||||||
|
*/
|
||||||
|
public function injectJsonService(JsonService $jsonService)
|
||||||
|
{
|
||||||
|
$this->jsonService = $jsonService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Repository\VoteRepository
|
||||||
|
*/
|
||||||
|
protected $voteRepository;
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Repository\VoteRepository $voteRepository
|
||||||
|
*/
|
||||||
|
public function injectVoteRepository(VoteRepository $voteRepository)
|
||||||
|
{
|
||||||
|
$this->voteRepository = $voteRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService
|
||||||
|
*/
|
||||||
|
protected $extensionHelperService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService $extensionHelperService
|
||||||
|
*/
|
||||||
|
/** @noinspection PhpUnused */
|
||||||
|
public function injectExtensionHelperService(ExtensionHelperService $extensionHelperService)
|
||||||
|
{
|
||||||
|
$this->extensionHelperService = $extensionHelperService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current calculated rates
|
||||||
|
*
|
||||||
|
* Redundant information to enhance performance in displaying calculated information
|
||||||
|
* This is a JSON encoded string with the following keys
|
||||||
|
* - votecounts(1...n) vote counts of the specific ratingstep
|
||||||
|
* It be updated every time a vote is created, changed or deleted.
|
||||||
|
* Specific handling must be defined when ratingsteps are added or removed or stepweights are changed
|
||||||
|
* Calculation of ratings:
|
||||||
|
* currentrate = ( sum of all ( stepweight(n) * votecounts(n) ) ) / number of all votes
|
||||||
|
* currentwidth = round (currentrate * 100 / number of ratingsteps, 1)
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $currentrates;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new rating object
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject|null $ratingobject
|
||||||
|
* @param int|null $ratedobjectuid
|
||||||
|
* @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
|
||||||
|
*/
|
||||||
|
public function __construct(Ratingobject $ratingobject = null, $ratedobjectuid = null)
|
||||||
|
{
|
||||||
|
if ($ratingobject) {
|
||||||
|
$this->setRatingobject($ratingobject);
|
||||||
|
}
|
||||||
|
if ($ratedobjectuid) {
|
||||||
|
$this->setRatedobjectuid($ratedobjectuid);
|
||||||
|
}
|
||||||
|
$this->initializeObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new rating object
|
||||||
|
* @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
|
||||||
|
*/
|
||||||
|
public function initializeObject()
|
||||||
|
{
|
||||||
|
if (empty($this->objectManager)) {
|
||||||
|
$this->objectManager = GeneralUtility::makeInstance(ObjectManager::class);
|
||||||
|
}
|
||||||
|
$this->settings = $this->objectManager
|
||||||
|
->get(ConfigurationManager::class)
|
||||||
|
->getConfiguration('Settings', 'thRating', 'pi1');
|
||||||
|
|
||||||
|
//Initialize vote storage if rating is new
|
||||||
|
if (!is_object($this->votes)) {
|
||||||
|
$this->votes = new ObjectStorage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the ratingobject this rating is part of
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject $ratingobject The Rating
|
||||||
|
*/
|
||||||
|
public function setRatingobject(Ratingobject $ratingobject)
|
||||||
|
{
|
||||||
|
$this->ratingobject = $ratingobject;
|
||||||
|
$this->setPid($ratingobject->getPid());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the ratingobject this rating is part of
|
||||||
|
*
|
||||||
|
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject The ratingobject this rating is part of
|
||||||
|
*/
|
||||||
|
public function getRatingobject(): Ratingobject
|
||||||
|
{
|
||||||
|
return $this->ratingobject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the rating object uid
|
||||||
|
*
|
||||||
|
* @param int $ratedobjectuid
|
||||||
|
*/
|
||||||
|
public function setRatedobjectuid($ratedobjectuid)
|
||||||
|
{
|
||||||
|
$this->ratedobjectuid = $ratedobjectuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the rating object uid
|
||||||
|
*
|
||||||
|
* @return int Rating object row uid field value
|
||||||
|
*/
|
||||||
|
public function getRatedobjectuid()
|
||||||
|
{
|
||||||
|
return $this->ratedobjectuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a vote to this rating
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote $vote
|
||||||
|
*/
|
||||||
|
public function addVote(Vote $vote)
|
||||||
|
{
|
||||||
|
$this->votes->attach($vote);
|
||||||
|
$this->addCurrentrate($vote);
|
||||||
|
$this->extensionHelperService->persistRepository(VoteRepository::class, $vote);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates an existing vote to this rating
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote $existingVote
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote $newVote
|
||||||
|
*/
|
||||||
|
public function updateVote(Vote $existingVote, Vote $newVote)
|
||||||
|
{
|
||||||
|
$this->removeCurrentrate($existingVote);
|
||||||
|
$existingVote->setVote($newVote->getVote());
|
||||||
|
$this->addCurrentrate($existingVote);
|
||||||
|
$this->extensionHelperService->persistRepository(VoteRepository::class, $existingVote);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a vote from this rating
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote $voteToRemove The vote to be removed
|
||||||
|
*/
|
||||||
|
/** @noinspection PhpUnused */
|
||||||
|
public function removeVote(Vote $voteToRemove)
|
||||||
|
{
|
||||||
|
$this->removeCurrentrate($voteToRemove);
|
||||||
|
$this->votes->detach($voteToRemove);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all votes from this rating
|
||||||
|
*/
|
||||||
|
/** @noinspection PhpUnused */
|
||||||
|
public function removeAllVotes()
|
||||||
|
{
|
||||||
|
$this->votes = new ObjectStorage();
|
||||||
|
unset($this->currentrates);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all votes in this rating
|
||||||
|
*
|
||||||
|
* @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote>
|
||||||
|
*/
|
||||||
|
public function getVotes()
|
||||||
|
{
|
||||||
|
return clone $this->votes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks all votes of this rating and sets currentrates accordingly
|
||||||
|
*
|
||||||
|
* This method is used for maintenance to assure consistency
|
||||||
|
*/
|
||||||
|
public function checkCurrentrates()
|
||||||
|
{
|
||||||
|
$currentratesDecoded['weightedVotes'] = [];
|
||||||
|
$currentratesDecoded['sumWeightedVotes'] = [];
|
||||||
|
$numAllVotes = 0;
|
||||||
|
$numAllAnonymousVotes = 0;
|
||||||
|
foreach ($this->getRatingobject()->getStepconfs() as $stepConf) {
|
||||||
|
$stepOrder = $stepConf->getSteporder();
|
||||||
|
$voteCount = $this->voteRepository->countByMatchingRatingAndVote($this, $stepConf);
|
||||||
|
$anonymousCount = $this->voteRepository->countAnonymousByMatchingRatingAndVote(
|
||||||
|
$this,
|
||||||
|
$stepConf,
|
||||||
|
$this->settings['mapAnonymous']
|
||||||
|
);
|
||||||
|
$currentratesDecoded['weightedVotes'][$stepOrder] = $voteCount * $stepConf->getStepweight();
|
||||||
|
$currentratesDecoded['sumWeightedVotes'][$stepOrder] =
|
||||||
|
$currentratesDecoded['weightedVotes'][$stepOrder] * $stepOrder;
|
||||||
|
$numAllVotes += $voteCount;
|
||||||
|
$numAllAnonymousVotes += $anonymousCount;
|
||||||
|
}
|
||||||
|
$currentratesDecoded['numAllVotes'] = $numAllVotes;
|
||||||
|
$currentratesDecoded['anonymousVotes'] = $numAllAnonymousVotes;
|
||||||
|
$this->currentrates = $this->jsonService->encodeToJson($currentratesDecoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a vote to the calculations of this rating
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote $voting The vote to be added
|
||||||
|
*/
|
||||||
|
public function addCurrentrate(Vote $voting)
|
||||||
|
{
|
||||||
|
if (empty($this->currentrates)) {
|
||||||
|
$this->checkCurrentrates(); //initialize entry
|
||||||
|
}
|
||||||
|
$currentratesDecoded = $this->jsonService->decodeJsonToArray($this->currentrates);
|
||||||
|
$currentratesDecoded['numAllVotes']++;
|
||||||
|
if ($voting->isAnonymous()) {
|
||||||
|
$currentratesDecoded['anonymousVotes']++;
|
||||||
|
}
|
||||||
|
$votingStep = $voting->getVote();
|
||||||
|
/** @noinspection NullPointerExceptionInspection */
|
||||||
|
$votingSteporder = $votingStep->getSteporder();
|
||||||
|
/** @noinspection NullPointerExceptionInspection */
|
||||||
|
$votingStepweight = $votingStep->getStepweight();
|
||||||
|
$currentratesDecoded['weightedVotes'][$votingSteporder] += $votingStepweight;
|
||||||
|
$currentratesDecoded['sumWeightedVotes'][$votingSteporder] += $votingStepweight * $votingSteporder;
|
||||||
|
$this->currentrates = $this->jsonService->encodeToJson($currentratesDecoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a vote to the calculations of this rating
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote $voting The vote to be removed
|
||||||
|
*/
|
||||||
|
public function removeCurrentrate(Vote $voting)
|
||||||
|
{
|
||||||
|
if (empty($this->currentrates)) {
|
||||||
|
$this->checkCurrentrates(); //initialize entry
|
||||||
|
}
|
||||||
|
$currentratesDecoded = $this->jsonService->decodeJsonToArray($this->currentrates);
|
||||||
|
$currentratesDecoded['numAllVotes']--;
|
||||||
|
if ($voting->isAnonymous()) {
|
||||||
|
$currentratesDecoded['anonymousVotes']--;
|
||||||
|
}
|
||||||
|
$votingStep = $voting->getVote();
|
||||||
|
/** @noinspection NullPointerExceptionInspection */
|
||||||
|
$votingSteporder = $votingStep->getSteporder();
|
||||||
|
/** @noinspection NullPointerExceptionInspection */
|
||||||
|
$votingStepweight = $votingStep->getStepweight();
|
||||||
|
$currentratesDecoded['weightedVotes'][$votingSteporder] -= $votingStepweight;
|
||||||
|
$currentratesDecoded['sumWeightedVotes'][$votingSteporder] -= $votingStepweight * $votingSteporder;
|
||||||
|
$this->currentrates = $this->jsonService->encodeToJson($currentratesDecoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the calculated rating
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getCurrentrates(): array
|
||||||
|
{
|
||||||
|
$currentratesDecoded = $this->jsonService->decodeJsonToArray($this->currentrates);
|
||||||
|
if (empty($currentratesDecoded['numAllVotes'])) {
|
||||||
|
$this->checkCurrentrates();
|
||||||
|
$currentratesDecoded = $this->jsonService->decodeJsonToArray($this->currentrates);
|
||||||
|
}
|
||||||
|
$numAllVotes = $currentratesDecoded['numAllVotes'];
|
||||||
|
if (!empty($numAllVotes)) {
|
||||||
|
$currentrate = array_sum($currentratesDecoded['sumWeightedVotes']) / $numAllVotes;
|
||||||
|
} else {
|
||||||
|
$currentrate = 0;
|
||||||
|
$numAllVotes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sumAllWeightedVotes = array_sum($currentratesDecoded['weightedVotes']);
|
||||||
|
|
||||||
|
//initialize array to handle missing stepconfs correctly
|
||||||
|
$currentPollDimensions = [];
|
||||||
|
|
||||||
|
foreach ($this->getRatingobject()->getStepconfs() as $stepConf) {
|
||||||
|
if (empty($sumAllWeightedVotes)) {
|
||||||
|
//set current polling styles to zero percent and prevent division by zero error in lower formula
|
||||||
|
$currentPollDimensions[$stepConf->getStepOrder()]['pctValue'] = 0;
|
||||||
|
} else {
|
||||||
|
/* calculate current polling styles -> holds a percent value for usage in CSS
|
||||||
|
to display polling relations */
|
||||||
|
$currentPollDimensions[$stepConf->getStepOrder()]['pctValue'] =
|
||||||
|
round(
|
||||||
|
($currentratesDecoded['weightedVotes'][$stepConf->getStepOrder()] * 100) /
|
||||||
|
$sumAllWeightedVotes,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['currentrate' => $currentrate,
|
||||||
|
'weightedVotes' => $currentratesDecoded['weightedVotes'],
|
||||||
|
'sumWeightedVotes' => $currentratesDecoded['sumWeightedVotes'],
|
||||||
|
'anonymousVotes' => $currentratesDecoded['anonymousVotes'],
|
||||||
|
'currentPollDimensions' => $currentPollDimensions,
|
||||||
|
'numAllVotes' => $numAllVotes, ];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the calculated rating in percent
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getCalculatedRate(): int
|
||||||
|
{
|
||||||
|
$currentrate = $this->getCurrentrates();
|
||||||
|
if (!empty($currentrate['weightedVotes'])) {
|
||||||
|
$calculatedRate = round(($currentrate['currentrate'] * 100) / count($currentrate['weightedVotes']), 1);
|
||||||
|
} else {
|
||||||
|
$calculatedRate = 0;
|
||||||
|
}
|
||||||
|
return $calculatedRate;
|
||||||
|
}
|
||||||
|
}
|
196
Classes/Domain/Model/RatingImage.php
Normal file
196
Classes/Domain/Model/RatingImage.php
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Model;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\Core\Environment;
|
||||||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
|
||||||
|
use TYPO3\CMS\Frontend\Imaging\GifBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model for rating votes
|
||||||
|
*
|
||||||
|
* @copyright Copyright belongs to the respective authors
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GNU Public License, version 2
|
||||||
|
* @entity
|
||||||
|
*/
|
||||||
|
class RatingImage extends AbstractEntity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $isBuilderObject = false;
|
||||||
|
/**
|
||||||
|
* The filename of the final image
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $imageFile;
|
||||||
|
/**
|
||||||
|
* The typoscript image configuration array
|
||||||
|
* Only the top level node ['GIFBUILDER'] will be used for building the image
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $conf;
|
||||||
|
/**
|
||||||
|
* @var GifBuilder
|
||||||
|
*/
|
||||||
|
protected $gifBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param GifBuilder $gifBuilder
|
||||||
|
*/
|
||||||
|
public function injectGifBuilder(GifBuilder $gifBuilder)
|
||||||
|
{
|
||||||
|
$this->gifBuilder = $gifBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new image object
|
||||||
|
*
|
||||||
|
* @param mixed $conf either an array consisting of GIFBUILDER typoscript or a plain string having the filename
|
||||||
|
*/
|
||||||
|
public function __construct($conf = null)
|
||||||
|
{
|
||||||
|
$this->initializeObject();
|
||||||
|
if (!empty($conf)) {
|
||||||
|
$this->setConf($conf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the new vote object
|
||||||
|
*/
|
||||||
|
public function initializeObject()
|
||||||
|
{
|
||||||
|
if (empty($this->gifBuilder)) {
|
||||||
|
$this->injectGifBuilder(GeneralUtility::makeInstance(GifBuilder::class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the typoscript configuration for the GIFBUILDER object
|
||||||
|
*
|
||||||
|
* @param mixed $conf either an array consisting of GIFBUILDER typoscript or a plain string having the filename
|
||||||
|
*/
|
||||||
|
public function setConf($conf)
|
||||||
|
{
|
||||||
|
switch (gettype($conf)) {
|
||||||
|
case 'string':
|
||||||
|
$this->setImageFile($conf);
|
||||||
|
break;
|
||||||
|
case 'array':
|
||||||
|
$this->conf = $conf;
|
||||||
|
$this->generateImage();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//TODO: Error message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current typoscript configuration of the GIFBUILDER object
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getConf(): array
|
||||||
|
{
|
||||||
|
if (empty($this->conf)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the filename of the image
|
||||||
|
*
|
||||||
|
* @param string $imageFile
|
||||||
|
*/
|
||||||
|
public function setImageFile($imageFile)
|
||||||
|
{
|
||||||
|
$fullImagePath = Environment::getPublicPath() . '/' . $imageFile;
|
||||||
|
if (file_exists($fullImagePath)) {
|
||||||
|
$this->imageFile = $imageFile;
|
||||||
|
$this->isBuilderObject = false;
|
||||||
|
} else {
|
||||||
|
//clear path if given file is invalid
|
||||||
|
unset($this->imageFile, $this->isBuilderObject);
|
||||||
|
//TODO: error handling
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the filename of the image
|
||||||
|
*
|
||||||
|
* @param mixed $fullPath
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getImageFile($fullPath = false)
|
||||||
|
{
|
||||||
|
$checkedFile = $this->gifBuilder->checkFile($this->imageFile);
|
||||||
|
if (empty($checkedFile)) {
|
||||||
|
//clear image if file doe not exist
|
||||||
|
$this->setImageFile('xxx');
|
||||||
|
}
|
||||||
|
return $fullPath ? Environment::getPublicPath() . '/' . $this->imageFile : $this->imageFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the image using the given typoscript
|
||||||
|
*
|
||||||
|
* @return bool The result; true if the given the image has been created successfully; otherwise false
|
||||||
|
*/
|
||||||
|
public function generateImage()
|
||||||
|
{
|
||||||
|
if (!empty($this->conf)) {
|
||||||
|
$this->gifBuilder->start($this->getConf(), []);
|
||||||
|
$genImageFile = $this->gifBuilder->gifBuild();
|
||||||
|
if (!file_exists($genImageFile)) {
|
||||||
|
//TODO: error handling
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$this->setImageFile($genImageFile);
|
||||||
|
$this->isBuilderObject = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the filename of the image
|
||||||
|
*
|
||||||
|
* @var bool switch if absolute path should be returned
|
||||||
|
* @return array('width','height')
|
||||||
|
*/
|
||||||
|
public function getImageDimensions()
|
||||||
|
{
|
||||||
|
if ($this->isBuilderObject) {
|
||||||
|
[$width, $height] = $this->gifBuilder->getImageDimensions($this->imageFile);
|
||||||
|
} else {
|
||||||
|
[$width, $height] = getimagesize($this->getImageFile(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['width' => $width, 'height' => $height, 'builderObject' => $this->isBuilderObject];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to use Object as plain string
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return $this->imageFile;
|
||||||
|
}
|
||||||
|
}
|
257
Classes/Domain/Model/Ratingobject.php
Normal file
257
Classes/Domain/Model/Ratingobject.php
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Model;
|
||||||
|
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Repository\RatingRepository;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepconfRepository;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService;
|
||||||
|
use TYPO3\CMS\Extbase\Annotation as Extbase;
|
||||||
|
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aggregate object for rating of content objects
|
||||||
|
*
|
||||||
|
* @version $Id:$
|
||||||
|
* @copyright Copyright belongs to the respective authors
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GNU Public License, version 2
|
||||||
|
* @entity
|
||||||
|
*/
|
||||||
|
class Ratingobject extends AbstractEntity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Table name of the cObj
|
||||||
|
* Defaults to Typo3 tablename of pages
|
||||||
|
*
|
||||||
|
* @Extbase\Validate("StringLength", options={"minimum": 3})
|
||||||
|
* @Extbase\Validate("StringLength", options={"maximum": 60})
|
||||||
|
* @Extbase\Validate("NotEmpty")
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $ratetable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fieldname within the table of the cObj
|
||||||
|
* Defaults to the field 'uid'
|
||||||
|
*
|
||||||
|
* @Extbase\Validate("StringLength", options={"minimum": 3})
|
||||||
|
* @Extbase\Validate("StringLength", options={"maximum": 60})
|
||||||
|
* @Extbase\Validate("NotEmpty")
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $ratefield;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The stepconfs of this object
|
||||||
|
*
|
||||||
|
* @Extbase\ORM\Lazy
|
||||||
|
* @Extbase\ORM\Cascade("remove")
|
||||||
|
* @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf>
|
||||||
|
*/
|
||||||
|
protected $stepconfs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ratings of this object
|
||||||
|
*
|
||||||
|
* @Extbase\ORM\Lazy
|
||||||
|
* @Extbase\ORM\Cascade("remove")
|
||||||
|
* @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating>
|
||||||
|
*/
|
||||||
|
protected $ratings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepconfRepository
|
||||||
|
*/
|
||||||
|
protected $stepconfRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepconfRepository $stepconfRepository
|
||||||
|
*/
|
||||||
|
public function injectStepconfRepository(StepconfRepository $stepconfRepository)
|
||||||
|
{
|
||||||
|
$this->stepconfRepository = $stepconfRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService
|
||||||
|
*/
|
||||||
|
protected $extensionHelperService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService $extensionHelperService
|
||||||
|
*/
|
||||||
|
/** @noinspection PhpUnused */
|
||||||
|
public function injectExtensionHelperService(ExtensionHelperService $extensionHelperService)
|
||||||
|
{
|
||||||
|
$this->extensionHelperService = $extensionHelperService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new rating object
|
||||||
|
* @param string $ratetable The rating objects table name
|
||||||
|
* @param string $ratefield The rating objects field name
|
||||||
|
* @Extbase\Validate("StringLength", options={"minimum": 3}, param="ratetable")
|
||||||
|
* @Extbase\Validate("StringLength", options={"maximum": 60}, param="ratetable")
|
||||||
|
* @Extbase\Validate("StringLength", options={"minimum": 3}, param="ratefield")
|
||||||
|
* @Extbase\Validate("StringLength", options={"maximum": 60}, param="ratefield")
|
||||||
|
*/
|
||||||
|
public function __construct($ratetable = null, $ratefield = null)
|
||||||
|
{
|
||||||
|
if ($ratetable) {
|
||||||
|
$this->setRatetable($ratetable);
|
||||||
|
}
|
||||||
|
if ($ratefield) {
|
||||||
|
$this->setRatefield($ratefield);
|
||||||
|
}
|
||||||
|
$this->initializeObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new ratingobject
|
||||||
|
*/
|
||||||
|
public function initializeObject()
|
||||||
|
{
|
||||||
|
//Initialize rating storage if ratingobject is new
|
||||||
|
if (!is_object($this->ratings)) {
|
||||||
|
$this->ratings = new ObjectStorage();
|
||||||
|
}
|
||||||
|
//Initialize stepconf storage if ratingobject is new
|
||||||
|
if (!is_object($this->stepconfs)) {
|
||||||
|
$this->stepconfs = new ObjectStorage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the rating table name
|
||||||
|
*
|
||||||
|
* @param string $ratetable
|
||||||
|
*/
|
||||||
|
public function setRatetable($ratetable)
|
||||||
|
{
|
||||||
|
$this->ratetable = $ratetable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the rating table name
|
||||||
|
*
|
||||||
|
* @return string Rating object table name
|
||||||
|
*/
|
||||||
|
public function getRatetable()
|
||||||
|
{
|
||||||
|
return $this->ratetable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the rating field name
|
||||||
|
*
|
||||||
|
* @param string $ratefield
|
||||||
|
*/
|
||||||
|
public function setRatefield($ratefield)
|
||||||
|
{
|
||||||
|
$this->ratefield = $ratefield;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the rating field name
|
||||||
|
*
|
||||||
|
* @return string Rating object field name
|
||||||
|
*/
|
||||||
|
public function getRatefield()
|
||||||
|
{
|
||||||
|
return $this->ratefield;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a rating to this object
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating $rating
|
||||||
|
*/
|
||||||
|
/** @noinspection PhpUnused */
|
||||||
|
public function addRating(Rating $rating)
|
||||||
|
{
|
||||||
|
$this->ratings->attach($rating);
|
||||||
|
$this->extensionHelperService->persistRepository(RatingRepository::class, $rating);
|
||||||
|
$this->extensionHelperService->clearDynamicCssFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a rating from this object
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating $rating The rating to be removed
|
||||||
|
*/
|
||||||
|
public function removeRating(Rating $rating): void
|
||||||
|
{
|
||||||
|
$this->ratings->detach($rating);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all ratings from this object
|
||||||
|
*/
|
||||||
|
public function removeAllRatings(): void
|
||||||
|
{
|
||||||
|
$this->ratings = new ObjectStorage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a stepconf to this object
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf $stepconf
|
||||||
|
*/
|
||||||
|
public function addStepconf(Stepconf $stepconf): void
|
||||||
|
{
|
||||||
|
if (!$this->stepconfRepository->existStepconf($stepconf)) {
|
||||||
|
$this->stepconfs->attach($stepconf);
|
||||||
|
$this->extensionHelperService->persistRepository(StepconfRepository::class, $stepconf);
|
||||||
|
$this->extensionHelperService->clearDynamicCssFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets all ratings of this ratingobject
|
||||||
|
*
|
||||||
|
* @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf> $stepconfs
|
||||||
|
* The step configurations for this ratingobject
|
||||||
|
*/
|
||||||
|
public function setStepconfs(ObjectStorage $stepconfs)
|
||||||
|
{
|
||||||
|
$this->stepconfs = $stepconfs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all ratings in this object
|
||||||
|
*
|
||||||
|
* @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf>
|
||||||
|
*/
|
||||||
|
public function getStepconfs()
|
||||||
|
{
|
||||||
|
return clone $this->stepconfs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets all ratings of this ratingobject
|
||||||
|
*
|
||||||
|
* @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating> $ratings
|
||||||
|
* The ratings of the organization
|
||||||
|
*/
|
||||||
|
public function setRatings(ObjectStorage $ratings)
|
||||||
|
{
|
||||||
|
$this->ratings = $ratings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all ratings in this object
|
||||||
|
*
|
||||||
|
* @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating>
|
||||||
|
*/
|
||||||
|
public function getRatings()
|
||||||
|
{
|
||||||
|
return clone $this->ratings;
|
||||||
|
}
|
||||||
|
}
|
271
Classes/Domain/Model/Stepconf.php
Normal file
271
Classes/Domain/Model/Stepconf.php
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Model;
|
||||||
|
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepconfRepository;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepnameRepository;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService;
|
||||||
|
use TYPO3\CMS\Extbase\Annotation as Extbase;
|
||||||
|
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
|
||||||
|
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model for ratingstep configuration
|
||||||
|
*
|
||||||
|
* @copyright Copyright belongs to the respective authors
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GNU Public License, version 2
|
||||||
|
* @entity
|
||||||
|
*/
|
||||||
|
class Stepconf extends AbstractEntity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Extbase\Validate("\WapplerSystems\BookmarksLikesRatings\Domain\Validator\RatingobjectValidator")
|
||||||
|
* @Extbase\Validate("NotEmpty")
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject
|
||||||
|
*/
|
||||||
|
protected $ratingobject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The order of this config entry
|
||||||
|
*
|
||||||
|
* @Extbase\Validate("NumberRange", options={"minimum": 1})
|
||||||
|
* @Extbase\Validate("NotEmpty")
|
||||||
|
* @var int discrete order of ratingsteps
|
||||||
|
*/
|
||||||
|
protected $steporder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The weight of this config entry
|
||||||
|
*
|
||||||
|
* @Extbase\Validate("Integer")
|
||||||
|
* @Extbase\Validate("NumberRange", options={"minimum": 1})
|
||||||
|
* @var int default is 1 which is equal weight
|
||||||
|
*/
|
||||||
|
protected $stepweight;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of this config entry
|
||||||
|
*
|
||||||
|
* @Extbase\ORM\Lazy
|
||||||
|
* @Extbase\ORM\Cascade("remove")
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepname
|
||||||
|
*/
|
||||||
|
protected $stepname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ratings of this object
|
||||||
|
*
|
||||||
|
* @Extbase\ORM\Lazy
|
||||||
|
* @Extbase\ORM\Cascade("remove")
|
||||||
|
* @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote>
|
||||||
|
*/
|
||||||
|
protected $votes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
|
||||||
|
*/
|
||||||
|
protected $objectManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
|
||||||
|
*/
|
||||||
|
public function injectObjectManager(ObjectManagerInterface $objectManager)
|
||||||
|
{
|
||||||
|
$this->objectManager = $objectManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepnameRepository $stepnameRepository
|
||||||
|
*/
|
||||||
|
protected $stepnameRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepnameRepository $stepnameRepository
|
||||||
|
*/
|
||||||
|
public function injectStepnameRepository(StepnameRepository $stepnameRepository)
|
||||||
|
{
|
||||||
|
$this->stepnameRepository = $stepnameRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService
|
||||||
|
*/
|
||||||
|
protected $extensionHelperService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService $extensionHelperService
|
||||||
|
*/
|
||||||
|
public function injectExtensionHelperService(ExtensionHelperService $extensionHelperService)
|
||||||
|
{
|
||||||
|
$this->extensionHelperService = $extensionHelperService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new stepconfig object
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject|null $ratingobject
|
||||||
|
* @param int|null $steporder
|
||||||
|
*/
|
||||||
|
public function __construct(Ratingobject $ratingobject = null, $steporder = null)
|
||||||
|
{
|
||||||
|
if ($ratingobject) {
|
||||||
|
$this->setRatingobject($ratingobject);
|
||||||
|
}
|
||||||
|
if ($steporder) {
|
||||||
|
$this->setSteporder($steporder);
|
||||||
|
}
|
||||||
|
$this->initializeObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new stepconf object
|
||||||
|
*/
|
||||||
|
public function initializeObject()
|
||||||
|
{
|
||||||
|
//Initialize vote storage if rating is new
|
||||||
|
if (!is_object($this->votes)) {
|
||||||
|
$this->votes = new ObjectStorage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the ratingobject this rating is part of
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject $ratingobject The Rating
|
||||||
|
*/
|
||||||
|
public function setRatingobject(Ratingobject $ratingobject)
|
||||||
|
{
|
||||||
|
$this->ratingobject = $ratingobject;
|
||||||
|
$this->setPid($ratingobject->getPid());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the ratingobject this rating is part of
|
||||||
|
*
|
||||||
|
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject|null
|
||||||
|
*/
|
||||||
|
public function getRatingobject()
|
||||||
|
{
|
||||||
|
return $this->ratingobject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the stepconfig order
|
||||||
|
*
|
||||||
|
* @param int $steporder
|
||||||
|
*/
|
||||||
|
public function setSteporder($steporder)
|
||||||
|
{
|
||||||
|
$this->steporder = $steporder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the stepconfig order
|
||||||
|
*
|
||||||
|
* @return int stepconfig position
|
||||||
|
*/
|
||||||
|
public function getSteporder(): int
|
||||||
|
{
|
||||||
|
return $this->steporder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the stepconfig value
|
||||||
|
*
|
||||||
|
* @param int $stepweight
|
||||||
|
*/
|
||||||
|
public function setStepweight($stepweight)
|
||||||
|
{
|
||||||
|
$this->stepweight = $stepweight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the stepconfig value
|
||||||
|
* If not set steporder is copied
|
||||||
|
*
|
||||||
|
* @return int Stepconfig value
|
||||||
|
*/
|
||||||
|
public function getStepweight()
|
||||||
|
{
|
||||||
|
empty($this->stepweight) && $this->stepweight = $this->steporder;
|
||||||
|
return $this->stepweight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a localized stepname to this stepconf
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepname $stepname
|
||||||
|
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
|
||||||
|
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function addStepname(Stepname $stepname): bool
|
||||||
|
{
|
||||||
|
$success = true;
|
||||||
|
$stepname->setStepconf($this);
|
||||||
|
if (!$this->stepnameRepository->existStepname($stepname)) {
|
||||||
|
$defaultLanguageObject = $this->stepnameRepository->findDefaultStepname($stepname);
|
||||||
|
if (is_object($defaultLanguageObject)) {
|
||||||
|
//handle localization if an entry for the default language exists
|
||||||
|
$stepname->setL18nParent($defaultLanguageObject->getUid());
|
||||||
|
}
|
||||||
|
$this->stepnameRepository->add($stepname);
|
||||||
|
$this->extensionHelperService->persistRepository(StepnameRepository::class, $stepname);
|
||||||
|
$stepname->getStepconf()->getStepname();
|
||||||
|
$this->extensionHelperService->persistRepository(StepconfRepository::class, $this);
|
||||||
|
$this->extensionHelperService->clearDynamicCssFile();
|
||||||
|
$this->stepname = $stepname;
|
||||||
|
} else {
|
||||||
|
//warning - existing stepname entry for a language will not be overwritten
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the localized stepname object of this stepconf
|
||||||
|
*
|
||||||
|
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepname|null
|
||||||
|
*/
|
||||||
|
public function getStepname(): ?Stepname
|
||||||
|
{
|
||||||
|
/* @phpstan-ignore-next-line */
|
||||||
|
if ($this->stepname instanceof LazyLoadingProxy) {
|
||||||
|
$this->stepname = $this->stepname->_loadRealInstance();
|
||||||
|
}
|
||||||
|
return $this->stepname;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all votes in this rating
|
||||||
|
*
|
||||||
|
* @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote>
|
||||||
|
*/
|
||||||
|
public function getVotes()
|
||||||
|
{
|
||||||
|
return clone $this->votes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to use Object as plain string
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
$stepnameText = $this->getStepname();
|
||||||
|
if (!$stepnameText) {
|
||||||
|
$stepnameText = $this->getSteporder();
|
||||||
|
}
|
||||||
|
return (string)$stepnameText;
|
||||||
|
}
|
||||||
|
}
|
158
Classes/Domain/Model/Stepname.php
Normal file
158
Classes/Domain/Model/Stepname.php
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types = 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Model;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Extbase\Annotation as Extbase;
|
||||||
|
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
|
||||||
|
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model for ratingstep configuration names
|
||||||
|
*
|
||||||
|
* @copyright Copyright belongs to the respective authors
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GNU Public License, version 2
|
||||||
|
* @entity
|
||||||
|
*/
|
||||||
|
class Stepname extends AbstractEntity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Extbase\Validate("\WapplerSystems\BookmarksLikesRatings\Domain\Validator\StepconfValidator")
|
||||||
|
* @Extbase\Validate("NotEmpty")
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf
|
||||||
|
*/
|
||||||
|
protected $stepconf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of this config entry
|
||||||
|
*
|
||||||
|
* @var string Name or description to display
|
||||||
|
*/
|
||||||
|
protected $stepname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Localization entry
|
||||||
|
* workaround to help avoiding bug in Typo 4.7 handling localized objects
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $l18nParent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $sysLanguageUid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the stepconf this rating is part of
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf $stepconf The Rating
|
||||||
|
*/
|
||||||
|
public function setStepconf(Stepconf $stepconf): void
|
||||||
|
{
|
||||||
|
$this->stepconf = $stepconf;
|
||||||
|
$this->setPid($stepconf->getPid());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the stepconf this rating is part of
|
||||||
|
*
|
||||||
|
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf The stepconf this rating is part of
|
||||||
|
*/
|
||||||
|
public function getStepconf(): Stepconf
|
||||||
|
{
|
||||||
|
return $this->stepconf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the stepconfig name
|
||||||
|
*
|
||||||
|
* @param string $stepname
|
||||||
|
*/
|
||||||
|
public function setStepname($stepname): void
|
||||||
|
{
|
||||||
|
$this->stepname = $stepname;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the stepconfig name
|
||||||
|
* If not set stepweight is copied
|
||||||
|
*
|
||||||
|
* @return string Stepconfig name
|
||||||
|
*/
|
||||||
|
public function getStepname(): string
|
||||||
|
{
|
||||||
|
$value = $this->stepname;
|
||||||
|
if (stripos($value, 'LLL:') === 0) {
|
||||||
|
$value = 'stepnames.' . substr($value, 4);
|
||||||
|
$value = LocalizationUtility::translate($value, 'ThRating');
|
||||||
|
}
|
||||||
|
if (empty($value)) {
|
||||||
|
$value = (string)$this->getStepconf()->getSteporder();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
/** @noinspection PhpUnused */
|
||||||
|
public function getL18nParent(): int
|
||||||
|
{
|
||||||
|
return $this->l18nParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $l18nParent
|
||||||
|
*/
|
||||||
|
public function setL18nParent($l18nParent): void
|
||||||
|
{
|
||||||
|
$this->l18nParent = $l18nParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get sys language
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getSysLanguageUid(): int
|
||||||
|
{
|
||||||
|
return $this->_languageUid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set sys language
|
||||||
|
*
|
||||||
|
* @param int $sysLanguageUid language uid
|
||||||
|
*/
|
||||||
|
public function setSysLanguageUid($sysLanguageUid): void
|
||||||
|
{
|
||||||
|
$this->_languageUid = $sysLanguageUid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isValid(): bool
|
||||||
|
{
|
||||||
|
return !empty($this->stepconf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to use Object as plain string
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString(): string
|
||||||
|
{
|
||||||
|
return $this->getStepname();
|
||||||
|
}
|
||||||
|
}
|
242
Classes/Domain/Model/Vote.php
Normal file
242
Classes/Domain/Model/Vote.php
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Model;
|
||||||
|
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService;
|
||||||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use TYPO3\CMS\Extbase\Annotation as Extbase;
|
||||||
|
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
|
||||||
|
use TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException;
|
||||||
|
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
|
||||||
|
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||||
|
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model for rating votes
|
||||||
|
*
|
||||||
|
* @copyright Copyright belongs to the respective authors
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GNU Public License, version 2
|
||||||
|
* @entity
|
||||||
|
*/
|
||||||
|
class Vote extends AbstractEntity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Extbase\Validate("\WapplerSystems\BookmarksLikesRatings\Domain\Validator\RatingValidator")
|
||||||
|
* @Extbase\Validate("NotEmpty")
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating
|
||||||
|
*/
|
||||||
|
protected $rating;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The voter of this object
|
||||||
|
*
|
||||||
|
* @Extbase\Validate("NotEmpty")
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Voter
|
||||||
|
*/
|
||||||
|
protected $voter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The actual voting of this object
|
||||||
|
*
|
||||||
|
* @Extbase\Validate("\WapplerSystems\BookmarksLikesRatings\Domain\Validator\StepconfValidator")
|
||||||
|
* @Extbase\Validate("NotEmpty")
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf
|
||||||
|
*/
|
||||||
|
protected $vote;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
|
||||||
|
*/
|
||||||
|
protected $objectManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Core\Log\Logger
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
|
||||||
|
*/
|
||||||
|
public function injectObjectManager(ObjectManagerInterface $objectManager)
|
||||||
|
{
|
||||||
|
$this->objectManager = $objectManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService
|
||||||
|
*/
|
||||||
|
protected $extensionHelperService;
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService $extensionHelperService
|
||||||
|
*/
|
||||||
|
public function injectExtensionHelperService(ExtensionHelperService $extensionHelperService): void
|
||||||
|
{
|
||||||
|
$this->extensionHelperService = $extensionHelperService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new rating object
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating|null $rating
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Voter|null $voter
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf|null $vote
|
||||||
|
* @throws InvalidConfigurationTypeException
|
||||||
|
*/
|
||||||
|
/** @noinspection PhpUnused */
|
||||||
|
public function __construct(
|
||||||
|
Rating $rating = null,
|
||||||
|
Voter $voter = null,
|
||||||
|
Stepconf $vote = null
|
||||||
|
) {
|
||||||
|
if ($rating) {
|
||||||
|
$this->setRating($rating);
|
||||||
|
}
|
||||||
|
if ($voter) {
|
||||||
|
$this->setVoter($voter);
|
||||||
|
}
|
||||||
|
if ($vote) {
|
||||||
|
$this->setVote($vote);
|
||||||
|
}
|
||||||
|
$this->initializeObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the new vote object
|
||||||
|
* @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
|
||||||
|
*/
|
||||||
|
public function initializeObject()
|
||||||
|
{
|
||||||
|
if (empty($this->objectManager)) {
|
||||||
|
$this->objectManager = GeneralUtility::makeInstance(ObjectManager::class);
|
||||||
|
}
|
||||||
|
if (empty($this->extensionHelperService)) {
|
||||||
|
$this->extensionHelperService = GeneralUtility::makeInstance(ExtensionHelperService::class);
|
||||||
|
}
|
||||||
|
$this->logger = $this->extensionHelperService->getLogger(__CLASS__);
|
||||||
|
$this->settings = $this->objectManager->get(ConfigurationManager::class)->getConfiguration(
|
||||||
|
'Settings',
|
||||||
|
'thRating',
|
||||||
|
'pi1'
|
||||||
|
);
|
||||||
|
//\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($this,get_class($this).' initializeObject');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the rating this vote is part of
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating $rating The Rating
|
||||||
|
*/
|
||||||
|
public function setRating(Rating $rating)
|
||||||
|
{
|
||||||
|
$this->rating = $rating;
|
||||||
|
$this->setPid($rating->getPid());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the rating this vote is part of
|
||||||
|
*
|
||||||
|
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating The rating this vote is part of
|
||||||
|
*/
|
||||||
|
public function getRating(): Rating
|
||||||
|
{
|
||||||
|
return $this->rating;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the frontenduser of this vote
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Voter $voter The frontenduser
|
||||||
|
*/
|
||||||
|
public function setVoter(Voter $voter)
|
||||||
|
{
|
||||||
|
$this->voter = $voter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the frontenduser of this vote
|
||||||
|
*
|
||||||
|
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Voter|null
|
||||||
|
*/
|
||||||
|
public function getVoter(): ?Voter
|
||||||
|
{
|
||||||
|
return $this->voter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the choosen stepconfig
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf $vote
|
||||||
|
*/
|
||||||
|
public function setVote($vote)
|
||||||
|
{
|
||||||
|
$this->vote = $vote;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the rating object uid
|
||||||
|
*
|
||||||
|
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf|null Reference to selected stepconfig
|
||||||
|
*/
|
||||||
|
public function getVote()
|
||||||
|
{
|
||||||
|
return $this->vote;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the rating this vote is part of
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
/** @noinspection PhpUnused */
|
||||||
|
public function hasRated()
|
||||||
|
{
|
||||||
|
return $this->getVote() !== null && ($this->getVote() instanceof Stepconf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if vote is done by anonymous user
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isAnonymous(): bool
|
||||||
|
{
|
||||||
|
return !empty($this->settings['mapAnonymous']) && !empty($this->getVoter()) &&
|
||||||
|
$this->getVoter()->getUid() === (int)$this->settings['mapAnonymous'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks cookie if anonymous vote is already done
|
||||||
|
* always false if cookie checks is deactivated
|
||||||
|
*
|
||||||
|
* @param string $prefixId Extension prefix to identify cookie
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasAnonymousVote($prefixId = 'DummyPrefix'): bool
|
||||||
|
{
|
||||||
|
$anonymousRating = GeneralUtility::makeInstance(\WapplerSystems\BookmarksLikesRatings\Service\JsonService::class)
|
||||||
|
->decodeJsonToArray($_COOKIE[$prefixId . '_AnonymousRating_' . $this->getRating()->getUid()]);
|
||||||
|
return !empty($anonymousRating['voteUid']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to use Object as plain string
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString(): string
|
||||||
|
{
|
||||||
|
return (string)$this->getVote();
|
||||||
|
}
|
||||||
|
}
|
17
Classes/Domain/Model/Voter.php
Normal file
17
Classes/Domain/Model/Voter.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The voter
|
||||||
|
*/
|
||||||
|
class Voter extends \TYPO3\CMS\Extbase\Domain\Model\FrontendUser
|
||||||
|
{
|
||||||
|
}
|
89
Classes/Domain/Repository/RatingRepository.php
Normal file
89
Classes/Domain/Repository/RatingRepository.php
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Repository;
|
||||||
|
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Validator\RatingValidator;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService;
|
||||||
|
use TYPO3\CMS\Extbase\Annotation as Extbase;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\Repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A repository for ratings
|
||||||
|
*/
|
||||||
|
class RatingRepository extends Repository
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Defines name for function parameter
|
||||||
|
*/
|
||||||
|
public const ADD_IF_NOT_FOUND = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService
|
||||||
|
*/
|
||||||
|
protected $extensionHelperService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService $extensionHelperService
|
||||||
|
*/
|
||||||
|
public function injectExtensionHelperService(ExtensionHelperService $extensionHelperService): void
|
||||||
|
{
|
||||||
|
$this->extensionHelperService = $extensionHelperService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the specific rating by giving the object and row uid
|
||||||
|
*
|
||||||
|
* @Extbase\Validate("\WapplerSystems\BookmarksLikesRatings\Domain\Validator\RatingobjectValidator", param="ratingobject")
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject $ratingobject The concerned ratingobject
|
||||||
|
* @Extbase\Validate("NumberRange", options={"minimum": 1}, param="ratedobjectuid")
|
||||||
|
* @param int $ratedobjectuid The Uid of the rated row
|
||||||
|
* @param bool $addIfNotFound Set to true if new objects should instantly be added
|
||||||
|
* @return Rating
|
||||||
|
* @throws IllegalObjectTypeException
|
||||||
|
*/
|
||||||
|
public function findMatchingObjectAndUid(
|
||||||
|
Ratingobject $ratingobject,
|
||||||
|
int $ratedobjectuid,
|
||||||
|
$addIfNotFound = false
|
||||||
|
): Rating {
|
||||||
|
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating $foundRow */
|
||||||
|
$foundRow = $this->objectManager->get(Rating::class);
|
||||||
|
|
||||||
|
$query = $this->createQuery();
|
||||||
|
$query->matching($query->logicalAnd(
|
||||||
|
[
|
||||||
|
$query->equals('ratingobject', $ratingobject->getUid()),
|
||||||
|
$query->equals('ratedobjectuid', $ratedobjectuid)
|
||||||
|
]
|
||||||
|
))->setLimit(1);
|
||||||
|
/*$queryParser = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class);
|
||||||
|
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($queryParser->convertQueryToDoctrineQueryBuilder($query)->getSQL(), get_class($this).' SQL');
|
||||||
|
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($queryParser->convertQueryToDoctrineQueryBuilder($query)->getParameters(), get_class($this).' SQL Parameter');*/
|
||||||
|
|
||||||
|
$queryResult = $query->execute();
|
||||||
|
if ($queryResult->count() > 0) {
|
||||||
|
$foundRow = $queryResult->getFirst();
|
||||||
|
} elseif ($addIfNotFound) {
|
||||||
|
$foundRow->setRatingobject($ratingobject);
|
||||||
|
$foundRow->setRatedobjectuid($ratedobjectuid);
|
||||||
|
$validator = $this->objectManager->get(RatingValidator::class);
|
||||||
|
if (!$validator->validate($foundRow)->hasErrors()) {
|
||||||
|
$this->add($foundRow);
|
||||||
|
}
|
||||||
|
$this->extensionHelperService->persistRepository(__CLASS__, $foundRow);
|
||||||
|
$foundRow = $this->findMatchingObjectAndUid($ratingobject, $ratedobjectuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $foundRow;
|
||||||
|
}
|
||||||
|
}
|
114
Classes/Domain/Repository/RatingobjectRepository.php
Normal file
114
Classes/Domain/Repository/RatingobjectRepository.php
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Repository;
|
||||||
|
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Validator\RatingobjectValidator;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Exception\RecordNotFoundException;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService;
|
||||||
|
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\Repository;
|
||||||
|
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A repository for rating objects
|
||||||
|
*/
|
||||||
|
class RatingobjectRepository extends Repository
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Defines name for function parameter
|
||||||
|
*/
|
||||||
|
public const ADD_IF_NOT_FOUND = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService
|
||||||
|
*/
|
||||||
|
protected $extensionHelperService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService $extensionHelperService
|
||||||
|
*/
|
||||||
|
public function injectExtensionHelperService(ExtensionHelperService $extensionHelperService): void
|
||||||
|
{
|
||||||
|
$this->extensionHelperService = $extensionHelperService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
|
||||||
|
*/
|
||||||
|
protected $configurationManager;
|
||||||
|
/**
|
||||||
|
* @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
|
||||||
|
*/
|
||||||
|
public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager): void
|
||||||
|
{
|
||||||
|
$this->configurationManager = $configurationManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the specific ratingobject by giving table and fieldname
|
||||||
|
*
|
||||||
|
* @param string $ratetable The tablename of the ratingobject
|
||||||
|
* @param string $ratefield The fieldname of the ratingobject
|
||||||
|
* @param bool $addIfNotFound Set to true if new objects should instantly be added
|
||||||
|
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject The ratingobject
|
||||||
|
* @throws RecordNotFoundException
|
||||||
|
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
|
||||||
|
*/
|
||||||
|
public function findMatchingTableAndField(string $ratetable, string $ratefield, bool $addIfNotFound = false): Ratingobject
|
||||||
|
{
|
||||||
|
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject $foundRow */
|
||||||
|
$foundRow = $this->objectManager->get(Ratingobject::class);
|
||||||
|
|
||||||
|
$query = $this->createQuery();
|
||||||
|
|
||||||
|
$query->matching($query->logicalAnd([
|
||||||
|
$query->equals('ratetable', $ratetable),
|
||||||
|
$query->equals('ratefield', $ratefield),
|
||||||
|
]))->setLimit(1);
|
||||||
|
|
||||||
|
/*$queryParser = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class);
|
||||||
|
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($queryParser->convertQueryToDoctrineQueryBuilder($query)->getSQL(), get_class($this).' SQL');
|
||||||
|
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($queryParser->convertQueryToDoctrineQueryBuilder($query)->getParameters(), get_class($this).' SQL Parameter');*/
|
||||||
|
|
||||||
|
/** @var \TYPO3\CMS\Extbase\Persistence\QueryResultInterface $queryResult */
|
||||||
|
$queryResult = $query->execute();
|
||||||
|
|
||||||
|
if ($queryResult->count() > 0) {
|
||||||
|
$foundRow = $queryResult->getFirst();
|
||||||
|
} elseif ($addIfNotFound) {
|
||||||
|
$foundRow->setRatetable($ratetable);
|
||||||
|
$foundRow->setRatefield($ratefield);
|
||||||
|
|
||||||
|
if (!$this->objectManager->get(RatingobjectValidator::class)->validate($foundRow)->hasErrors()) {
|
||||||
|
$this->add($foundRow);
|
||||||
|
}
|
||||||
|
$this->extensionHelperService->persistRepository(self::class, $foundRow);
|
||||||
|
$foundRow = $this->findMatchingTableAndField($ratetable, $ratefield);
|
||||||
|
} else {
|
||||||
|
throw new RecordNotFoundException(LocalizationUtility::translate('recordNotFound', 'ThRating'), 1567962473);
|
||||||
|
}
|
||||||
|
return $foundRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the specific ratingobject by giving table and fieldname
|
||||||
|
*
|
||||||
|
* @param bool Switch to fetch ALL entries regardless of their pid
|
||||||
|
* @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface|array All ratingobjects of the site
|
||||||
|
*/
|
||||||
|
/** @noinspection PhpMissingParentCallCommonInspection */
|
||||||
|
public function findAll($ignoreStoragePage = false)
|
||||||
|
{
|
||||||
|
$query = $this->createQuery();
|
||||||
|
$query->getQuerySettings()->setRespectStoragePage(!$ignoreStoragePage);
|
||||||
|
return $query->execute();
|
||||||
|
}
|
||||||
|
}
|
78
Classes/Domain/Repository/StepconfRepository.php
Normal file
78
Classes/Domain/Repository/StepconfRepository.php
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Repository;
|
||||||
|
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Validator\StepconfValidator;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\Repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A repository for ratingstep configurations
|
||||||
|
* @method findByRatingobject(Ratingobject $getRatingobject)
|
||||||
|
*/
|
||||||
|
class StepconfRepository extends Repository
|
||||||
|
{
|
||||||
|
protected $defaultOrderings = ['steporder' => QueryInterface::ORDER_ASCENDING];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize this repository
|
||||||
|
*/
|
||||||
|
public function initializeObject(): void
|
||||||
|
{
|
||||||
|
//disable RespectStoragePage as pid is always bound to parent objects pid
|
||||||
|
|
||||||
|
/** @var \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface $defaultQuerySettings */
|
||||||
|
$defaultQuerySettings = $this->objectManager->get(QuerySettingsInterface::class);
|
||||||
|
$defaultQuerySettings->setRespectStoragePage(false);
|
||||||
|
$this->setDefaultQuerySettings($defaultQuerySettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the given stepconf object in the repository
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf $stepconf The ratingobject to look for
|
||||||
|
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf
|
||||||
|
*/
|
||||||
|
public function findStepconfObject(Stepconf $stepconf): Stepconf
|
||||||
|
{
|
||||||
|
$query = $this->createQuery();
|
||||||
|
/** @noinspection NullPointerExceptionInspection */
|
||||||
|
$query->matching($query->logicalAnd([
|
||||||
|
$query->equals('ratingobject', $stepconf->getRatingobject()->getUid()),
|
||||||
|
$query->equals('steporder', $stepconf->getSteporder()),
|
||||||
|
]))->setLimit(1);
|
||||||
|
$queryResult = $query->execute();
|
||||||
|
|
||||||
|
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf $foundRow */
|
||||||
|
$foundRow = $this->objectManager->get(Stepconf::class);
|
||||||
|
|
||||||
|
if (count($queryResult) !== 0) {
|
||||||
|
$foundRow = $queryResult->getFirst();
|
||||||
|
}
|
||||||
|
return $foundRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the ratingstep entry by giving ratingobjectUid
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf $stepconf The uid of the ratingobject
|
||||||
|
* @return bool true if stepconf object exists in repository
|
||||||
|
*/
|
||||||
|
public function existStepconf(Stepconf $stepconf): bool
|
||||||
|
{
|
||||||
|
$foundRow = $this->findStepconfObject($stepconf);
|
||||||
|
$stepconfValidator = $this->objectManager->get(StepconfValidator::class);
|
||||||
|
|
||||||
|
return !$stepconfValidator->validate($foundRow)->hasErrors();
|
||||||
|
}
|
||||||
|
}
|
255
Classes/Domain/Repository/StepnameRepository.php
Normal file
255
Classes/Domain/Repository/StepnameRepository.php
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Repository;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepname;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService;
|
||||||
|
use TYPO3\CMS\Core\Site\Entity\Site;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\Repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A repository for ratingstep configurations
|
||||||
|
*/
|
||||||
|
class StepnameRepository extends Repository
|
||||||
|
{
|
||||||
|
protected const TABLE_NAME = 'tx_thrating_domain_model_stepname';
|
||||||
|
protected const STEPCONF_NAME = 'stepconf';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string $syslangUidLiteral
|
||||||
|
*/
|
||||||
|
protected $syslangUidLiteral;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $defaultOrderings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize this repository
|
||||||
|
*/
|
||||||
|
public function initializeObject(): void
|
||||||
|
{
|
||||||
|
$this->syslangUidLiteral = $GLOBALS['TCA'][self::TABLE_NAME]['ctrl']['languageField'];
|
||||||
|
$this->defaultOrderings = [ $this->syslangUidLiteral => QueryInterface::ORDER_ASCENDING];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if stepname got a valid language code
|
||||||
|
*
|
||||||
|
* @param Stepname $stepname The stepname object
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function checkStepnameLanguage(Stepname $stepname): bool
|
||||||
|
{
|
||||||
|
$stepnameLang = $stepname->getSysLanguageUid();
|
||||||
|
if ($stepnameLang > 0) {
|
||||||
|
//check if given language exist
|
||||||
|
|
||||||
|
try {
|
||||||
|
// only get language and do not assign the result to check if it exists
|
||||||
|
$this->objectManager
|
||||||
|
->get(ExtensionHelperService::class)
|
||||||
|
->getStaticLanguageById($stepnameLang);
|
||||||
|
} catch (InvalidArgumentException $exception) {
|
||||||
|
//invalid language code -> NOK
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//language code found -> OK
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the given stepconf object in the repository
|
||||||
|
*
|
||||||
|
* @param Stepname $stepname The ratingname to look for
|
||||||
|
* @return Stepname|null
|
||||||
|
*/
|
||||||
|
public function findStepnameObject(Stepname $stepname): ?Stepname
|
||||||
|
{
|
||||||
|
$query = $this->createQuery();
|
||||||
|
$query->getQuerySettings()->setRespectSysLanguage(false);
|
||||||
|
$query->getQuerySettings()->setLanguageOverlayMode(false);
|
||||||
|
$query->matching(
|
||||||
|
$query->logicalAnd(
|
||||||
|
[
|
||||||
|
$query->equals(self::STEPCONF_NAME, $stepname->getStepconf()),
|
||||||
|
$query->equals($this->syslangUidLiteral, $stepname->getSysLanguageUid()),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)->setLimit(1);
|
||||||
|
|
||||||
|
/** @var \TYPO3\CMS\Extbase\Persistence\QueryResultInterface $queryResult */
|
||||||
|
$queryResult = $query->execute();
|
||||||
|
|
||||||
|
/*
|
||||||
|
$queryParser = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class);
|
||||||
|
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($queryParser->convertQueryToDoctrineQueryBuilder($query)->getSQL(), get_class($this).' SQL');
|
||||||
|
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($queryParser->convertQueryToDoctrineQueryBuilder($query)->getParameters(), get_class($this).' SQL Parameter');
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepname $foundRow */
|
||||||
|
$foundRow = null;
|
||||||
|
|
||||||
|
if ($queryResult->count() > 0) {
|
||||||
|
$foundRow = $queryResult->getFirst();
|
||||||
|
}
|
||||||
|
return $foundRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the given stepname object in the repository
|
||||||
|
*
|
||||||
|
* @param int $uid
|
||||||
|
* @return Stepname|null
|
||||||
|
*/
|
||||||
|
public function findStrictByUid(int $uid): ?Stepname
|
||||||
|
{
|
||||||
|
$query = $this->createQuery();
|
||||||
|
$query->getQuerySettings()->setRespectSysLanguage(false);
|
||||||
|
$query->getQuerySettings()->setRespectStoragePage(false);
|
||||||
|
$query->getQuerySettings()->setLanguageOverlayMode(false);
|
||||||
|
$query->matching(
|
||||||
|
$query->logicalAnd(
|
||||||
|
[$query->equals('uid', $uid)]
|
||||||
|
)
|
||||||
|
)->setLimit(1);
|
||||||
|
$queryResult = $query->execute();
|
||||||
|
|
||||||
|
/** @var Stepname $foundRow */
|
||||||
|
$foundRow = null;
|
||||||
|
if ($queryResult->count() > 0) {
|
||||||
|
$foundRow = $queryResult->getFirst();
|
||||||
|
}
|
||||||
|
return $foundRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check on double language entries
|
||||||
|
*
|
||||||
|
* @param Stepname $stepname The ratingname to look for
|
||||||
|
* @return array return values false says OK
|
||||||
|
*/
|
||||||
|
public function checkConsistency(Stepname $stepname): array
|
||||||
|
{
|
||||||
|
$query = $this->createQuery();
|
||||||
|
$query ->getQuerySettings()->setRespectSysLanguage(false);
|
||||||
|
$query ->matching(
|
||||||
|
$query->equals(self::STEPCONF_NAME, $stepname->getStepconf()->getUid())
|
||||||
|
);
|
||||||
|
$queryResult = $query
|
||||||
|
->execute(true);
|
||||||
|
$checkConsistency = [];
|
||||||
|
if (count($queryResult) > 1) {
|
||||||
|
$websiteLanguagesArray = [];
|
||||||
|
$allWebsiteLanguages = $this->getCurrentSite()->getAllLanguages();
|
||||||
|
|
||||||
|
/** @var \TYPO3\CMS\Core\Site\Entity\SiteLanguage $language */
|
||||||
|
foreach (array_values($allWebsiteLanguages) as $language) {
|
||||||
|
$websiteLanguagesArray[] = $language->getLanguageId();
|
||||||
|
}
|
||||||
|
$languageCounter = [];
|
||||||
|
foreach (array_values($queryResult) as $value) {
|
||||||
|
$languageUid = $value[$this->syslangUidLiteral];
|
||||||
|
$languageCounter[$languageUid]++;
|
||||||
|
if ($languageCounter[$languageUid] > 1) {
|
||||||
|
$checkConsistency['doubleLang'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//check if language flag exists in current website
|
||||||
|
if (($languageUid > 0) && in_array($languageUid, $websiteLanguagesArray, true)) {
|
||||||
|
$checkConsistency['existLang'] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $checkConsistency;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the default language stepconf by giving ratingobject and steporder
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepname $stepname The ratingname to look for
|
||||||
|
* @throws InvalidQueryException
|
||||||
|
* @return Stepname|null The stepname in default language
|
||||||
|
* @var Stepname $foundRow
|
||||||
|
*/
|
||||||
|
public function findDefaultStepname(Stepname $stepname): ?Stepname
|
||||||
|
{
|
||||||
|
$foundRow = $this->objectManager->get(Stepname::class);
|
||||||
|
|
||||||
|
$query = $this->createQuery();
|
||||||
|
$query->getQuerySettings()->setRespectSysLanguage(false);
|
||||||
|
$query->getQuerySettings()->setLanguageOverlayMode(false);
|
||||||
|
$query->matching(
|
||||||
|
$query->logicalAnd(
|
||||||
|
[
|
||||||
|
$query->equals(self::STEPCONF_NAME, $stepname->getStepconf()),
|
||||||
|
$query->in($this->syslangUidLiteral, [0, -1])
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)->setLimit(1);
|
||||||
|
|
||||||
|
/** @var QueryResultInterface $queryResult */
|
||||||
|
$queryResult = $query->execute();
|
||||||
|
|
||||||
|
/*
|
||||||
|
$queryParser = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class);
|
||||||
|
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($queryParser->convertQueryToDoctrineQueryBuilder($query)->getSQL(), get_class($this).' SQL');
|
||||||
|
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($queryParser->convertQueryToDoctrineQueryBuilder($query)->getParameters(), get_class($this).' SQL Parameter');
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @var Stepname $foundRow */
|
||||||
|
$foundRow = null;
|
||||||
|
if ($queryResult->count() > 0) {
|
||||||
|
$foundRow = $queryResult->getFirst();
|
||||||
|
}
|
||||||
|
return $foundRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the localized ratingstep entry by giving ratingobjectUid
|
||||||
|
*
|
||||||
|
* @param Stepname $stepname The ratingname to look for
|
||||||
|
* @return bool true if stepconf having same steporder and _languageUid exists
|
||||||
|
*/
|
||||||
|
public function existStepname(Stepname $stepname): bool
|
||||||
|
{
|
||||||
|
$lookForStepname = $this->findStepnameObject($stepname);
|
||||||
|
return !is_null($lookForStepname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default query settings to find ALL records
|
||||||
|
*/
|
||||||
|
public function clearQuerySettings(): void
|
||||||
|
{
|
||||||
|
$querySettings = $this->createQuery()->getQuerySettings();
|
||||||
|
$querySettings->setRespectSysLanguage(true);
|
||||||
|
$querySettings->setIgnoreEnableFields(true);
|
||||||
|
$querySettings->setLanguageOverlayMode(false);
|
||||||
|
$this->setDefaultQuerySettings($querySettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getCurrentSite(): ?Site
|
||||||
|
{
|
||||||
|
if ($GLOBALS['TYPO3_REQUEST'] instanceof ServerRequestInterface
|
||||||
|
&& $GLOBALS['TYPO3_REQUEST']->getAttribute('site') instanceof Site) {
|
||||||
|
return $GLOBALS['TYPO3_REQUEST']->getAttribute('site');
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
105
Classes/Domain/Repository/VoteRepository.php
Normal file
105
Classes/Domain/Repository/VoteRepository.php
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Repository;
|
||||||
|
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Voter;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\Repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A repository for votes
|
||||||
|
*/
|
||||||
|
class VoteRepository extends Repository
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Defines name for function parameter
|
||||||
|
*/
|
||||||
|
public const /** @noinspection PhpUnused */
|
||||||
|
ADD_IF_NOT_FOUND = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize this repository
|
||||||
|
*/
|
||||||
|
/** @noinspection PhpUnused */
|
||||||
|
public function initializeObject(): void
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the voting by giving the rating and voter objects
|
||||||
|
*
|
||||||
|
* @param Rating|null $rating The concerned ratingobject
|
||||||
|
* @param Voter|null $voter The Uid of the rated row
|
||||||
|
* @return Vote|object The voting
|
||||||
|
*/
|
||||||
|
public function findMatchingRatingAndVoter($rating = null, $voter = null)
|
||||||
|
{
|
||||||
|
/** @var \TYPO3\CMS\Extbase\Persistence\QueryInterface $query */
|
||||||
|
$query = $this->createQuery();
|
||||||
|
|
||||||
|
return $query->matching(
|
||||||
|
$query->logicalAnd(
|
||||||
|
[
|
||||||
|
$query->equals('rating', $rating),
|
||||||
|
$query->equals('voter', $voter)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)->execute()->getFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counts all votings by giving the rating and ratingstep
|
||||||
|
*
|
||||||
|
* @param Rating $rating The concerned ratingobject
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf $stepconf The stepconf object
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function countByMatchingRatingAndVote($rating = null, $stepconf = null): int
|
||||||
|
{
|
||||||
|
$query = $this->createQuery();
|
||||||
|
$query->matching($query->logicalAnd(
|
||||||
|
[
|
||||||
|
$query->equals('rating', $rating->getUid()),
|
||||||
|
$query->equals('vote', $stepconf->getUid())
|
||||||
|
]
|
||||||
|
));
|
||||||
|
|
||||||
|
return count($query->execute());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counts all anonymous votings by giving the rating and ratingstep
|
||||||
|
*
|
||||||
|
* @param Rating $rating The concerned ratingobject
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf $stepconf The stepconf object
|
||||||
|
* @param int $anonymousVoter UID of the anonymous account
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function countAnonymousByMatchingRatingAndVote($rating = null, $stepconf = null, $anonymousVoter = null): int
|
||||||
|
{
|
||||||
|
/** @var int $count */
|
||||||
|
$count = 0;
|
||||||
|
|
||||||
|
if ($anonymousVoter !== null) {
|
||||||
|
$query = $this->createQuery();
|
||||||
|
$query->matching(
|
||||||
|
$query->logicalAnd([
|
||||||
|
$query->equals('rating', $rating->getUid()),
|
||||||
|
$query->equals('vote', $stepconf->getUid()),
|
||||||
|
$query->equals('voter', $anonymousVoter),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
$count = count($query->execute());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $count;
|
||||||
|
}
|
||||||
|
}
|
31
Classes/Domain/Repository/VoterRepository.php
Normal file
31
Classes/Domain/Repository/VoterRepository.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Repository;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A repository for votes
|
||||||
|
*/
|
||||||
|
class VoterRepository extends FrontendUserRepository
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Initialze this repository
|
||||||
|
*/
|
||||||
|
public function initializeObject()
|
||||||
|
{
|
||||||
|
//Even hidden or deleted FE Users should be found
|
||||||
|
/** @var \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface $querySettings */
|
||||||
|
$querySettings = $this->objectManager->get(QuerySettingsInterface::class);
|
||||||
|
$querySettings->setIgnoreEnableFields(true);
|
||||||
|
$this->setDefaultQuerySettings($querySettings);
|
||||||
|
}
|
||||||
|
}
|
60
Classes/Domain/Validator/RatingValidator.php
Normal file
60
Classes/Domain/Validator/RatingValidator.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Validator;
|
||||||
|
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject;
|
||||||
|
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||||
|
use TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A validator for Ratings
|
||||||
|
*
|
||||||
|
* @copyright Copyright belongs to the respective authors
|
||||||
|
* @scope singleton
|
||||||
|
*/
|
||||||
|
class RatingValidator extends AbstractValidator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* This validator always needs to be executed even if the given value is empty.
|
||||||
|
* See AbstractValidator::validate()
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $acceptsEmptyValues = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the given Rating is valid
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating $rating
|
||||||
|
* @noinspection PhpUnnecessaryFullyQualifiedNameInspection
|
||||||
|
*/
|
||||||
|
protected function isValid($rating): void
|
||||||
|
{
|
||||||
|
/** @noinspection NotOptimalIfConditionsInspection */
|
||||||
|
if (!$this->isEmpty($rating) && $rating instanceof Rating) {
|
||||||
|
$ratedobjectuid = $rating->getRatedobjectuid();
|
||||||
|
if (empty($ratedobjectuid)) {
|
||||||
|
$this->addError(
|
||||||
|
LocalizationUtility::translate('error.validator.rating.ratedobjectuid', 'ThRating'),
|
||||||
|
1283536994
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!$rating->getRatingobject() instanceof Ratingobject) {
|
||||||
|
$this->addError(
|
||||||
|
LocalizationUtility::translate('error.validator.rating.ratingobject', 'ThRating'),
|
||||||
|
1283538549
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->addError(LocalizationUtility::translate('error.validator.rating.empty', 'ThRating'), 1568138421);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
54
Classes/Domain/Validator/RatingobjectValidator.php
Normal file
54
Classes/Domain/Validator/RatingobjectValidator.php
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Validator;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||||
|
use TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A validator for Ratingobjects
|
||||||
|
*
|
||||||
|
* @copyright Copyright belongs to the respective author
|
||||||
|
* @scope singleton
|
||||||
|
*/
|
||||||
|
class RatingobjectValidator extends AbstractValidator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* If the given Ratingobject is valid
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject $ratingobject The ratingobject
|
||||||
|
*/
|
||||||
|
protected function isValid($ratingobject)
|
||||||
|
{
|
||||||
|
/** @var string $ratetable */
|
||||||
|
$ratetable = $ratingobject->getRatetable();
|
||||||
|
/** @var string $ratefield */
|
||||||
|
$ratefield = $ratingobject->getRatefield();
|
||||||
|
|
||||||
|
if (empty($ratetable)) {
|
||||||
|
$this->addError(
|
||||||
|
LocalizationUtility::translate(
|
||||||
|
'error.validator.ratingobject_table_extbase',
|
||||||
|
'ThRating'
|
||||||
|
),
|
||||||
|
1283528638
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (empty($ratefield)) {
|
||||||
|
$this->addError(
|
||||||
|
LocalizationUtility::translate(
|
||||||
|
'error.validator.ratingobject_field_extbase',
|
||||||
|
'ThRating'
|
||||||
|
),
|
||||||
|
1283536038
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
185
Classes/Domain/Validator/StepconfValidator.php
Normal file
185
Classes/Domain/Validator/StepconfValidator.php
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Validator;
|
||||||
|
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepconfRepository;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepnameRepository;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
|
||||||
|
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||||
|
use TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A validator for Ratings
|
||||||
|
*
|
||||||
|
* @copyright Copyright belongs to the respective authors
|
||||||
|
* @scope singleton
|
||||||
|
*/
|
||||||
|
class StepconfValidator extends AbstractValidator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepconfRepository
|
||||||
|
*/
|
||||||
|
protected $stepconfRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepconfRepository $stepconfRepository
|
||||||
|
*/
|
||||||
|
public function injectStepconfRepository(StepconfRepository $stepconfRepository)
|
||||||
|
{
|
||||||
|
$this->stepconfRepository = $stepconfRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepnameRepository
|
||||||
|
*/
|
||||||
|
protected $stepnameRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepnameRepository $stepnameRepository
|
||||||
|
*/
|
||||||
|
public function injectStepnameRepository(StepnameRepository $stepnameRepository)
|
||||||
|
{
|
||||||
|
$this->stepnameRepository = $stepnameRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the given step is valid
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf $stepconf
|
||||||
|
* @throws InvalidQueryException
|
||||||
|
*/
|
||||||
|
protected function isValid($stepconf): void
|
||||||
|
{
|
||||||
|
/** @noinspection NotOptimalIfConditionsInspection */
|
||||||
|
if (!$this->isEmpty($stepconf) && $stepconf instanceof Stepconf) {
|
||||||
|
$this->checkRatingobject($stepconf);
|
||||||
|
if (!$this->result->hasErrors()) {
|
||||||
|
$this->checkSteporder($stepconf);
|
||||||
|
}
|
||||||
|
if (!$this->result->hasErrors()) {
|
||||||
|
$this->validateStepnames($stepconf);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->addError(LocalizationUtility::translate('error.validator.stepconf.empty', 'ThRating'), 1568139528);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A stepconf object must have a ratingobject
|
||||||
|
* @param Stepconf $stepconf
|
||||||
|
*/
|
||||||
|
protected function checkRatingobject(Stepconf $stepconf): void
|
||||||
|
{
|
||||||
|
if (!$stepconf->getRatingobject() instanceof Ratingobject) {
|
||||||
|
$this->addError(
|
||||||
|
LocalizationUtility::translate('error.validator.stepconf.ratingobject', 'ThRating'),
|
||||||
|
1284700846
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* At least a steporder value must be set and a positive integer ( >0 ) and valid regaing existing values
|
||||||
|
* @param Stepconf $stepconf
|
||||||
|
*/
|
||||||
|
protected function checkSteporder(Stepconf $stepconf): void
|
||||||
|
{
|
||||||
|
$steporder = $stepconf->getSteporder();
|
||||||
|
if (empty($steporder)) {
|
||||||
|
$this->addError(
|
||||||
|
LocalizationUtility::translate('error.validator.stepconf.steps', 'ThRating'),
|
||||||
|
1284700903
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_int($stepconf->getSteporder()) || $stepconf->getSteporder() < 1) {
|
||||||
|
$this->addError(
|
||||||
|
LocalizationUtility::translate(
|
||||||
|
'error.validator.stepconf.invalidSteporderNumber',
|
||||||
|
'ThRating'
|
||||||
|
),
|
||||||
|
1368123953
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//check if given steporder is valid (integer, maximum +1)
|
||||||
|
/** @var object $maxSteporderStepconfobject */
|
||||||
|
$maxSteporderStepconfobject = $this->stepconfRepository->findByRatingobject($stepconf->getRatingobject());
|
||||||
|
$maxSteporder = $maxSteporderStepconfobject[$maxSteporderStepconfobject->count() - 1]->getSteporder();
|
||||||
|
if ($stepconf->getSteporder() > $maxSteporder + 1) {
|
||||||
|
$this->addError(
|
||||||
|
LocalizationUtility::translate('error.validator.stepconf.maxSteporder', 'ThRating'),
|
||||||
|
1368123970
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the given step is valid
|
||||||
|
*
|
||||||
|
* @param Stepconf $stepconf
|
||||||
|
* @throws InvalidQueryException
|
||||||
|
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
|
||||||
|
*/
|
||||||
|
protected function validateStepnames($stepconf): void
|
||||||
|
{
|
||||||
|
//check if a stepname is given that at least has the default language definition
|
||||||
|
//TODO move to query on stepname repository
|
||||||
|
$stepname = $stepconf->getStepname();
|
||||||
|
$countNames = 0;
|
||||||
|
if ($stepname instanceof ObjectStorage) {
|
||||||
|
$countNames = $stepname->count();
|
||||||
|
}
|
||||||
|
if ($countNames != 0) {
|
||||||
|
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepname $firstStepname */
|
||||||
|
$firstStepname = $stepname->current();
|
||||||
|
|
||||||
|
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepname|object $defaultName */
|
||||||
|
$defaultName = $this->stepnameRepository->findDefaultStepname($firstStepname);
|
||||||
|
if (!$defaultName->isValid()) {
|
||||||
|
$this->addError(
|
||||||
|
LocalizationUtility::translate(
|
||||||
|
'error.validator.stepconf.defaultStepname',
|
||||||
|
'ThRating',
|
||||||
|
[$firstStepname->getStepconf()->getUid()]
|
||||||
|
),
|
||||||
|
1384374165
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
//Finally check on language consistency
|
||||||
|
$checkConsistency = $this->stepnameRepository->checkConsistency($firstStepname);
|
||||||
|
if ($checkConsistency['doubleLang']) {
|
||||||
|
$this->addError(
|
||||||
|
LocalizationUtility::translate(
|
||||||
|
'error.validator.stepconf.doubleLangEntry',
|
||||||
|
'ThRating',
|
||||||
|
[$firstStepname->getStepconf()->getUid()]
|
||||||
|
),
|
||||||
|
1384374589
|
||||||
|
);
|
||||||
|
} elseif ($checkConsistency['existLang']) {
|
||||||
|
$this->addError(
|
||||||
|
LocalizationUtility::translate(
|
||||||
|
'error.validator.stepconf.notExistingLanguage',
|
||||||
|
'ThRating',
|
||||||
|
[$firstStepname->getUid()]
|
||||||
|
),
|
||||||
|
1384374589
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
72
Classes/Domain/Validator/StepnameValidator.php
Normal file
72
Classes/Domain/Validator/StepnameValidator.php
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @noinspection PhpFullyQualifiedNameUsageInspection */
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Validator;
|
||||||
|
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepname;
|
||||||
|
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||||
|
use TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A validator for Ratings
|
||||||
|
*
|
||||||
|
* @copyright Copyright belongs to the respective authors
|
||||||
|
* @scope singleton
|
||||||
|
*/
|
||||||
|
class StepnameValidator extends AbstractValidator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepnameRepository
|
||||||
|
*/
|
||||||
|
protected $stepnameRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepnameRepository $stepnameRepository
|
||||||
|
*/
|
||||||
|
public function injectStepnameRepository(\WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepnameRepository $stepnameRepository)
|
||||||
|
{
|
||||||
|
$this->stepnameRepository = $stepnameRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the given step is valid
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepname $stepname
|
||||||
|
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
|
||||||
|
*/
|
||||||
|
protected function isValid($stepname): void
|
||||||
|
{
|
||||||
|
//a stepname object must have a stepconf
|
||||||
|
if (!$stepname->getStepconf() instanceof Stepconf) {
|
||||||
|
$this->addError(
|
||||||
|
LocalizationUtility::translate('error.validator.stepname.stepconf', 'ThRating'),
|
||||||
|
1382895072
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//check if given languagecode exists in website
|
||||||
|
if (!$this->stepnameRepository->checkStepnameLanguage($stepname)) {
|
||||||
|
$this->addError(LocalizationUtility::translate('error.validator.stepname.sysLang', 'ThRating'), 1382895089);
|
||||||
|
}
|
||||||
|
|
||||||
|
//now check if entry for default language exists
|
||||||
|
$langUid = $stepname->getSysLanguageUid();
|
||||||
|
if (!empty($langUid)) {
|
||||||
|
$defaultStepname = $this->stepnameRepository->findDefaultStepname($stepname);
|
||||||
|
if (get_class($defaultStepname) !== Stepname::class || $this->validate($defaultStepname)->hasErrors()) {
|
||||||
|
$this->addError(
|
||||||
|
LocalizationUtility::translate('error.validator.stepname.defaultLang', 'ThRating'),
|
||||||
|
1382895097
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
79
Classes/Domain/Validator/VoteValidator.php
Normal file
79
Classes/Domain/Validator/VoteValidator.php
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Domain\Validator;
|
||||||
|
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Voter;
|
||||||
|
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||||
|
use TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A validator for Votes
|
||||||
|
*
|
||||||
|
* @copyright Copyright belongs to the respective authors
|
||||||
|
* @scope singleton
|
||||||
|
*/
|
||||||
|
class VoteValidator extends AbstractValidator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* This validator always needs to be executed even if the given value is empty.
|
||||||
|
* See AbstractValidator::validate()
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $acceptsEmptyValues = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the given Vote is valid
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote $vote The vote
|
||||||
|
*/
|
||||||
|
protected function isValid($vote)
|
||||||
|
{
|
||||||
|
/** @noinspection NotOptimalIfConditionsInspection */
|
||||||
|
if (!$this->isEmpty($vote) && $vote instanceof Vote) {
|
||||||
|
//a vote object must have a vote
|
||||||
|
if (!$vote->getVote() instanceof Stepconf) {
|
||||||
|
$this->addError(LocalizationUtility::translate('error.validator.vote.vote', 'ThRating'), 1283537235);
|
||||||
|
} else {
|
||||||
|
//a vote must have a valid voter
|
||||||
|
if (!$vote->getVoter() instanceof Voter) {
|
||||||
|
$this->addError(
|
||||||
|
LocalizationUtility::translate('error.validator.vote.voter', 'ThRating'),
|
||||||
|
1283540684
|
||||||
|
);
|
||||||
|
}
|
||||||
|
//check if the given vote is a valid step for this ratingobject
|
||||||
|
if (!$vote->getRating()->getRatingobject()->getStepconfs()->contains($vote->getVote())) {
|
||||||
|
$this->addError(
|
||||||
|
LocalizationUtility::translate('error.validator.vote.stepconf', 'ThRating'),
|
||||||
|
1283612492
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->addError(LocalizationUtility::translate('error.validator.vote.empty', 'ThRating'), 1568141014);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the given Vote is set
|
||||||
|
*
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote $vote The vote
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isObjSet($vote)
|
||||||
|
{
|
||||||
|
$result = !$this->isEmpty($vote) && $vote instanceof Vote;
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
53
Classes/Service/AbstractExtensionService.php
Normal file
53
Classes/Service/AbstractExtensionService.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types = 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\SingletonInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An access control service
|
||||||
|
*
|
||||||
|
* @version $Id:$
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GNU protected License, version 2
|
||||||
|
*/
|
||||||
|
class AbstractExtensionService implements SingletonInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
|
||||||
|
*/
|
||||||
|
protected $objectManager;
|
||||||
|
/**
|
||||||
|
* @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
|
||||||
|
*/
|
||||||
|
public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager)
|
||||||
|
{
|
||||||
|
$this->objectManager = $objectManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Service\LoggingService
|
||||||
|
*/
|
||||||
|
protected $loggingService;
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Core\Log\Logger
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Service\LoggingService $loggingService
|
||||||
|
*/
|
||||||
|
public function __construct(LoggingService $loggingService)
|
||||||
|
{
|
||||||
|
$this->loggingService = $loggingService;
|
||||||
|
$this->logger = $loggingService->getLogger(get_class($this));
|
||||||
|
}
|
||||||
|
}
|
187
Classes/Service/AccessControlService.php
Normal file
187
Classes/Service/AccessControlService.php
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @noinspection PhpFullyQualifiedNameUsageInspection */
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||||
|
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Voter;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Exception\FeUserNotFoundException;
|
||||||
|
use TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository;
|
||||||
|
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An access control service
|
||||||
|
*
|
||||||
|
* @version $Id:$
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GNU protected License, version 2
|
||||||
|
*/
|
||||||
|
class AccessControlService extends AbstractExtensionService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository $frontendUserRepository
|
||||||
|
*/
|
||||||
|
protected $frontendUserRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository $frontendUserRepository
|
||||||
|
* @noinspection PhpUnused
|
||||||
|
*/
|
||||||
|
public function injectFrontendUserRepository(FrontendUserRepository $frontendUserRepository): void
|
||||||
|
{
|
||||||
|
$this->frontendUserRepository = $frontendUserRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Repository\VoterRepository $voterRepository
|
||||||
|
*/
|
||||||
|
protected $voterRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Repository\VoterRepository $voterRepository
|
||||||
|
*/
|
||||||
|
public function injectVoterRepository(\WapplerSystems\BookmarksLikesRatings\Domain\Repository\VoterRepository $voterRepository): void
|
||||||
|
{
|
||||||
|
$this->voterRepository = $voterRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Core\Context\Context $context
|
||||||
|
*/
|
||||||
|
protected $context;
|
||||||
|
/**
|
||||||
|
* @param \TYPO3\CMS\Core\Context\Context $context
|
||||||
|
*/
|
||||||
|
public function injectContext(\TYPO3\CMS\Core\Context\Context $context): void
|
||||||
|
{
|
||||||
|
$this->context = $context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests, if the given person is logged into the frontend
|
||||||
|
*
|
||||||
|
* @param \TYPO3\CMS\Extbase\Domain\Model\FrontendUser|null $person The person
|
||||||
|
* @return bool The result; true if the given person is logged in; otherwise false
|
||||||
|
* @throws \TYPO3\CMS\Core\Context\Exception\AspectNotFoundException
|
||||||
|
*/
|
||||||
|
public function isLoggedIn(\TYPO3\CMS\Extbase\Domain\Model\FrontendUser $person = null): bool
|
||||||
|
{
|
||||||
|
if (is_object($person)) {
|
||||||
|
if ($person->getUid() &&
|
||||||
|
($person->getUid() === $this->getFrontendUserUid())) {
|
||||||
|
return true; //treat anonymous user also as logged in
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
* @throws \TYPO3\CMS\Core\Context\Exception\AspectNotFoundException
|
||||||
|
*/
|
||||||
|
public function backendAdminIsLoggedIn(): bool
|
||||||
|
{
|
||||||
|
return $this->context->getPropertyFromAspect('backend.user', 'isLoggedIn');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
* @throws \TYPO3\CMS\Core\Context\Exception\AspectNotFoundException
|
||||||
|
*/
|
||||||
|
public function hasLoggedInFrontendUser(): bool
|
||||||
|
{
|
||||||
|
return $this->context->getPropertyFromAspect('frontend.user', 'isLoggedIn');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
* @throws \TYPO3\CMS\Core\Context\Exception\AspectNotFoundException
|
||||||
|
*/
|
||||||
|
public function getFrontendUserGroups(): array
|
||||||
|
{
|
||||||
|
if ($this->hasLoggedInFrontendUser()) {
|
||||||
|
return $this->context->getPropertyFromAspect('frontend.user', 'groupIds');
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int|null
|
||||||
|
* @throws \TYPO3\CMS\Core\Context\Exception\AspectNotFoundException
|
||||||
|
*/
|
||||||
|
public function getFrontendUserUid(): ?int
|
||||||
|
{
|
||||||
|
if ($this->hasLoggedInFrontendUser()) {
|
||||||
|
return $this->context->getPropertyFromAspect('frontend.user', 'id');
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads objects from repositories
|
||||||
|
*
|
||||||
|
* @param mixed $voter
|
||||||
|
* @return \TYPO3\CMS\Extbase\Domain\Model\FrontendUser
|
||||||
|
* @throws \TYPO3\CMS\Core\Context\Exception\AspectNotFoundException
|
||||||
|
*/
|
||||||
|
public function getFrontendUser($voter = null): ?\TYPO3\CMS\Extbase\Domain\Model\FrontendUser
|
||||||
|
{
|
||||||
|
//set userobject
|
||||||
|
if (!$voter instanceof \TYPO3\CMS\Extbase\Domain\Model\FrontendUser) {
|
||||||
|
//TODO Errorhandling if no user is logged in
|
||||||
|
if ((int)$voter === 0) {
|
||||||
|
//get logged in fe-user
|
||||||
|
$voter = $this->frontendUserRepository->findByUid($this->getFrontendUserUid());
|
||||||
|
} else {
|
||||||
|
$voter = $this->frontendUserRepository->findByUid((int)$voter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $voter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads objects from repositories
|
||||||
|
*
|
||||||
|
* @param int|null $voter
|
||||||
|
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Voter
|
||||||
|
* @throws FeUserNotFoundException
|
||||||
|
* @throws \TYPO3\CMS\Core\Context\Exception\AspectNotFoundException
|
||||||
|
*/
|
||||||
|
public function getFrontendVoter(?int $voter = 0): Voter
|
||||||
|
{
|
||||||
|
$exceptionMessageArray = [];
|
||||||
|
|
||||||
|
/** @var Voter $voterObject */
|
||||||
|
$voterObject = null;
|
||||||
|
|
||||||
|
//TODO Errorhandling if no user is logged in
|
||||||
|
if ((int)$voter === 0) {
|
||||||
|
//get logged in fe-user
|
||||||
|
$voterObject = $this->voterRepository->findByUid($this->getFrontendUserUid());
|
||||||
|
$exceptionMessageArray = [$this->getFrontendUserUid()];
|
||||||
|
$exceptionMessageType = 'feUser';
|
||||||
|
} else {
|
||||||
|
$voterObject = $this->voterRepository->findByUid((int)$voter);
|
||||||
|
$exceptionMessageArray = [(int)$voter];
|
||||||
|
$exceptionMessageType = 'anonymousUser';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($voterObject)) {
|
||||||
|
throw new FeUserNotFoundException(
|
||||||
|
LocalizationUtility::translate(
|
||||||
|
'flash.pluginConfiguration.missing.' . $exceptionMessageType,
|
||||||
|
'ThRating',
|
||||||
|
$exceptionMessageArray
|
||||||
|
),
|
||||||
|
1602095329
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $voterObject;
|
||||||
|
}
|
||||||
|
}
|
21
Classes/Service/AccessException.php
Normal file
21
Classes/Service/AccessException.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Extbase\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An access exception
|
||||||
|
*
|
||||||
|
* @version $ID: $
|
||||||
|
*/
|
||||||
|
class AccessException extends Exception
|
||||||
|
{
|
||||||
|
}
|
139
Classes/Service/CookieService.php
Normal file
139
Classes/Service/CookieService.php
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\Log\LogLevel;
|
||||||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for setting cookies like Typo3 does
|
||||||
|
*
|
||||||
|
* @version $Id:$
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GNU protected License, version 2
|
||||||
|
*/
|
||||||
|
class CookieService extends AbstractExtensionService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Indicator for cookieProtection has been set
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $cookieProtection = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the domain to be used on setting cookies.
|
||||||
|
* The information is taken from the value in $GLOBALS['TYPO3_CONF_VARS']['SYS']['cookieDomain'].
|
||||||
|
* Protected function taken from t3lib_userAuth (t3 4.7.7)
|
||||||
|
*
|
||||||
|
* @return string The domain to be used on setting cookies
|
||||||
|
*/
|
||||||
|
protected function getCookieDomain()
|
||||||
|
{
|
||||||
|
$result = '';
|
||||||
|
$cookieDomain = $GLOBALS['TYPO3_CONF_VARS']['SYS']['cookieDomain'];
|
||||||
|
// If a specific cookie domain is defined for a given TYPO3_MODE,
|
||||||
|
// use that domain
|
||||||
|
if (!empty($GLOBALS['TYPO3_CONF_VARS']['FE']['cookieDomain'])) {
|
||||||
|
$cookieDomain = $GLOBALS['TYPO3_CONF_VARS']['FE']['cookieDomain'];
|
||||||
|
}
|
||||||
|
if ($cookieDomain) {
|
||||||
|
if ($cookieDomain[0] === '/') {
|
||||||
|
$match = [];
|
||||||
|
/** @noinspection PhpUsageOfSilenceOperatorInspection */
|
||||||
|
$matchCnt = @preg_match(
|
||||||
|
$cookieDomain,
|
||||||
|
GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY'),
|
||||||
|
$match
|
||||||
|
);
|
||||||
|
if ($matchCnt === false) {
|
||||||
|
$this->logger->log(
|
||||||
|
LogLevel::ERROR,
|
||||||
|
'getCookieDomain: The regular expression for the cookie domain contains errors.' .
|
||||||
|
'The session is not shared across sub-domains.',
|
||||||
|
['cookieDomain' => $cookieDomain, 'errorCode' => 1399137882]
|
||||||
|
);
|
||||||
|
} elseif ($matchCnt) {
|
||||||
|
$result = $match[0];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$result = $cookieDomain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the cookie
|
||||||
|
* Protected function taken from t3lib_userAuth (t3 4.7.7)
|
||||||
|
*
|
||||||
|
* @param string $cookieName identifier for the cookie
|
||||||
|
* @param string $cookieValue cookie value
|
||||||
|
* @param int $cookieExpire expire time for the cookie (UNIX timestamp)
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function setVoteCookie($cookieName, $cookieValue, $cookieExpire = 0): void
|
||||||
|
{
|
||||||
|
// do not set session cookies
|
||||||
|
if (!empty($cookieExpire)) {
|
||||||
|
$settings = $GLOBALS['TYPO3_CONF_VARS']['SYS'];
|
||||||
|
// Get the domain to be used for the cookie (if any):
|
||||||
|
$cookieDomain = $this->getCookieDomain();
|
||||||
|
// If no cookie domain is set, use the base path:
|
||||||
|
$cookiePath = ($cookieDomain ? '/' : GeneralUtility::getIndpEnv('TYPO3_SITE_PATH'));
|
||||||
|
// Use the secure option when the current request is served by a secure connection:
|
||||||
|
$cookieSecure = (bool)$settings['cookieSecure'] && GeneralUtility::getIndpEnv('TYPO3_SSL');
|
||||||
|
// Deliver cookies only via HTTP and prevent possible XSS by JavaScript:
|
||||||
|
$cookieHttpOnly = (bool)$settings['cookieHttpOnly'];
|
||||||
|
|
||||||
|
// Do not set cookie if cookieSecure is set to "1" (force HTTPS) and no secure channel is used:
|
||||||
|
if ((int)$settings['cookieSecure'] !== 1 || GeneralUtility::getIndpEnv('TYPO3_SSL')) {
|
||||||
|
setcookie(
|
||||||
|
$cookieName,
|
||||||
|
$cookieValue,
|
||||||
|
(int)$cookieExpire,
|
||||||
|
$cookiePath,
|
||||||
|
$cookieDomain,
|
||||||
|
$cookieSecure,
|
||||||
|
$cookieHttpOnly
|
||||||
|
);
|
||||||
|
$this->cookieProtection = true;
|
||||||
|
$this->logger->log(
|
||||||
|
LogLevel::INFO,
|
||||||
|
'setVoteCookie: Cookie set',
|
||||||
|
[
|
||||||
|
'cookieName' => $cookieName,
|
||||||
|
'cookieValue' => $cookieValue,
|
||||||
|
'cookieExpire' => $cookieExpire,
|
||||||
|
'cookiePath' => $cookiePath,
|
||||||
|
'cookieDomain' => $cookieDomain,
|
||||||
|
'cookieSecure' => $cookieSecure,
|
||||||
|
'cookieHttpOnly' => $cookieHttpOnly,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw new Exception(
|
||||||
|
"Cookie was not set since HTTPS was forced in \$GLOBALS['TYPO3_CONF_VARS'][SYS][cookieSecure].",
|
||||||
|
1254325546
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return if cookie protection has been set
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isProtected()
|
||||||
|
{
|
||||||
|
return $this->cookieProtection;
|
||||||
|
}
|
||||||
|
}
|
19
Classes/Service/Exception.php
Normal file
19
Classes/Service/Exception.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A ViewHelper Exception
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
class Exception extends \TYPO3Fluid\Fluid\Core\Exception
|
||||||
|
{
|
||||||
|
}
|
233
Classes/Service/ExtensionConfigurationService.php
Normal file
233
Classes/Service/ExtensionConfigurationService.php
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||||
|
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Exception\FeUserStoragePageException;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Exception\InvalidStoragePageException;
|
||||||
|
use TYPO3\CMS\Core\Log\Logger;
|
||||||
|
use TYPO3\CMS\Core\Log\LogLevel;
|
||||||
|
use TYPO3\CMS\Core\Utility\ArrayUtility;
|
||||||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface;
|
||||||
|
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for model objects
|
||||||
|
*
|
||||||
|
* @version $Id:$
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GNU protected License, version 2
|
||||||
|
*/
|
||||||
|
class ExtensionConfigurationService extends AbstractExtensionService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Contains configuration of the calling extension
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $originalConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calling extension query settings
|
||||||
|
*
|
||||||
|
* @var \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface
|
||||||
|
*/
|
||||||
|
protected $originalTypo3QuerySettings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $cookieLifetime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
|
||||||
|
*/
|
||||||
|
protected $configurationManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var QuerySettingsInterface
|
||||||
|
*/
|
||||||
|
private $extDefaultQuerySettings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
|
||||||
|
*/
|
||||||
|
public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager): void
|
||||||
|
{
|
||||||
|
$this->configurationManager = $configurationManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the settings of the current extension
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains configuration of th_rating
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $thRatingConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains configuration of the current extension
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $frameworkConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public function initializeObject(): void
|
||||||
|
{
|
||||||
|
// store calling extension configuration
|
||||||
|
$this->originalConfiguration = $this->configurationManager->getConfiguration(
|
||||||
|
ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->thRatingConfiguration = $this->configurationManager->getConfiguration(
|
||||||
|
ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK,
|
||||||
|
'thrating',
|
||||||
|
'pi1'
|
||||||
|
);
|
||||||
|
if (!empty($this->thRatingConfiguration['ratings'])) {
|
||||||
|
//Merge extension ratingConfigurations with customer added ones
|
||||||
|
ArrayUtility::mergeRecursiveWithOverrule(
|
||||||
|
$this->thRatingConfiguration['settings']['ratingConfigurations'],
|
||||||
|
$this->thRatingConfiguration['ratings']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->frameworkConfiguration = $this->configurationManager->getConfiguration(
|
||||||
|
ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT,
|
||||||
|
'thrating',
|
||||||
|
'pi1'
|
||||||
|
);
|
||||||
|
|
||||||
|
//\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($this->frameworkConfiguration,get_class($this).' frameworkConfiguration');
|
||||||
|
//\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($this->thRatingConfiguration,get_class($this).' thRatingConfiguration');
|
||||||
|
//\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($this->originalConfiguration,get_class($this).' originalConfiguration');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a logger instance
|
||||||
|
* The configuration of the logger is modified by extension typoscript config
|
||||||
|
*
|
||||||
|
* @param string|null $name the class name which this logger is for
|
||||||
|
* @return \TYPO3\CMS\Core\Log\Logger
|
||||||
|
*/
|
||||||
|
public function getLogger(string $name = null): Logger
|
||||||
|
{
|
||||||
|
if (empty($name)) {
|
||||||
|
return $this->loggingService->getLogger(__CLASS__);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->loggingService->getLogger($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default query settings to those of th_rating
|
||||||
|
* (could be different if services are called from other extensions
|
||||||
|
* @throws FeUserStoragePageException
|
||||||
|
* @throws InvalidStoragePageException
|
||||||
|
*/
|
||||||
|
public function setExtDefaultQuerySettings(): void
|
||||||
|
{
|
||||||
|
$this->mergeStoragePids();
|
||||||
|
$this->extDefaultQuerySettings = $this->objectManager->get(QuerySettingsInterface::class);
|
||||||
|
$this->extDefaultQuerySettings->setStoragePageIds(
|
||||||
|
explode(',', $this->thRatingConfiguration['persistence']['storagePid'])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function getCookieProtection(): bool
|
||||||
|
{
|
||||||
|
$this->cookieLifetime = abs((int)$this->thRatingConfiguration['settings']['cookieLifetime']);
|
||||||
|
$this->logger->log(
|
||||||
|
LogLevel::DEBUG,
|
||||||
|
'Cookielifetime set to ' . $this->cookieLifetime . ' days',
|
||||||
|
['errorCode' => 1465728751]
|
||||||
|
);
|
||||||
|
return empty($this->cookieLifetime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks storagePid settings of th_rating and tx_felogin_pi1 and
|
||||||
|
* concatenates them to the new storagePid setting
|
||||||
|
*
|
||||||
|
* @throws InvalidStoragePageException if plugin.tx_thrating.storagePid has not been set
|
||||||
|
* @throws FeUserStoragePageException if plugin.tx_felogin_pi1.storagePid has not been set
|
||||||
|
*/
|
||||||
|
private function mergeStoragePids(): void
|
||||||
|
{
|
||||||
|
$storagePids = GeneralUtility::intExplode(',', $this->thRatingConfiguration['storagePid'], true);
|
||||||
|
if (empty($storagePids[0])) {
|
||||||
|
throw new InvalidStoragePageException(
|
||||||
|
LocalizationUtility::translate('flash.vote.general.invalidStoragePid', 'ThRating'),
|
||||||
|
1403203519
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$storagePids[] = $this->getFeUserStoragePage();
|
||||||
|
$this->thRatingConfiguration['persistence.']['storagePid'] = implode(',', $storagePids);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check and return the first configured storage page for website users
|
||||||
|
* @return int
|
||||||
|
* @throws FeUserStoragePageException
|
||||||
|
*/
|
||||||
|
private function getFeUserStoragePage(): int
|
||||||
|
{
|
||||||
|
$feUserStoragePid = array_merge(
|
||||||
|
GeneralUtility::intExplode(
|
||||||
|
',',
|
||||||
|
$this->frameworkConfiguration['plugin.']['tx_felogin_pi1.']['storagePid'],
|
||||||
|
true
|
||||||
|
),
|
||||||
|
GeneralUtility::intExplode(',', $this->thRatingConfiguration['feUsersStoragePid'], true)
|
||||||
|
);
|
||||||
|
if (empty($feUserStoragePid[0])) {
|
||||||
|
throw new FeUserStoragePageException(
|
||||||
|
LocalizationUtility::translate('flash.pluginConfiguration.missing.feUserStoragePid', 'ThRating'),
|
||||||
|
1403190539
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $feUserStoragePid[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the current extbase configuration to the one of th_rating
|
||||||
|
*/
|
||||||
|
public function prepareExtensionConfiguration(): void
|
||||||
|
{
|
||||||
|
if ($this->originalConfiguration['extensionName'] !== 'ThRating') {
|
||||||
|
//Set default storage pids
|
||||||
|
$this->setExtDefaultQuerySettings();
|
||||||
|
}
|
||||||
|
$this->configurationManager->setConfiguration($this->thRatingConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the current extbase configuration to the one of th_rating
|
||||||
|
*/
|
||||||
|
public function restoreCallingExtensionConfiguration(): void
|
||||||
|
{
|
||||||
|
if ($this->originalConfiguration['extensionName'] !== 'ThRating') {
|
||||||
|
$this->configurationManager->setConfiguration($this->originalConfiguration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
720
Classes/Service/ExtensionHelperService.php
Normal file
720
Classes/Service/ExtensionHelperService.php
Normal file
@ -0,0 +1,720 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @noinspection PhpFullyQualifiedNameUsageInspection */
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||||
|
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\RatingImage;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepname;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Repository\RatingobjectRepository;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Repository\RatingRepository;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepnameRepository;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Repository\VoteRepository;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Validator\RatingobjectValidator;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Validator\RatingValidator;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Validator\StepconfValidator;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Validator\VoteValidator;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Evaluation\DynamicCssEvaluator;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Exception\LanguageNotFoundException;
|
||||||
|
use TYPO3\CMS\Core\Core\Environment;
|
||||||
|
use TYPO3\CMS\Core\Log\Logger;
|
||||||
|
use TYPO3\CMS\Core\Log\LogLevel;
|
||||||
|
use TYPO3\CMS\Core\Site\Entity\Site;
|
||||||
|
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
|
||||||
|
use TYPO3\CMS\Core\Site\SiteFinder;
|
||||||
|
use TYPO3\CMS\Core\Utility\ArrayUtility;
|
||||||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
|
||||||
|
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
|
||||||
|
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
|
||||||
|
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||||
|
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for model objects
|
||||||
|
*
|
||||||
|
* @version $Id:$
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GNU protected License, version 2
|
||||||
|
*/
|
||||||
|
class ExtensionHelperService extends AbstractExtensionService
|
||||||
|
{
|
||||||
|
protected const DYN_CSS_FILENAME = 'typo3temp/thratingDyn.css';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current request.
|
||||||
|
*
|
||||||
|
* @var \TYPO3\CMS\Extbase\Mvc\Request
|
||||||
|
*/
|
||||||
|
protected $request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Repository\RatingobjectRepository
|
||||||
|
*/
|
||||||
|
protected $ratingobjectRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Repository\RatingobjectRepository $ratingobjectRepository
|
||||||
|
*/
|
||||||
|
public function injectRatingobjectRepository(RatingobjectRepository $ratingobjectRepository): void
|
||||||
|
{
|
||||||
|
$this->ratingobjectRepository = $ratingobjectRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Repository\RatingRepository
|
||||||
|
*/
|
||||||
|
protected $ratingRepository;
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Repository\RatingRepository $ratingRepository
|
||||||
|
*/
|
||||||
|
public function injectRatingRepository(RatingRepository $ratingRepository): void
|
||||||
|
{
|
||||||
|
$this->ratingRepository = $ratingRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepnameRepository
|
||||||
|
*/
|
||||||
|
protected $stepnameRepository;
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepnameRepository $stepnameRepository
|
||||||
|
*/
|
||||||
|
public function injectStepnameRepository(StepnameRepository $stepnameRepository): void
|
||||||
|
{
|
||||||
|
$this->stepnameRepository = $stepnameRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Repository\VoteRepository
|
||||||
|
*/
|
||||||
|
protected $voteRepository;
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Repository\VoteRepository $voteRepository
|
||||||
|
*/
|
||||||
|
public function injectVoteRepository(VoteRepository $voteRepository): void
|
||||||
|
{
|
||||||
|
$this->voteRepository = $voteRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Service\AccessControlService
|
||||||
|
*/
|
||||||
|
protected $accessControllService;
|
||||||
|
/**
|
||||||
|
* @param AccessControlService $accessControllService
|
||||||
|
*/
|
||||||
|
public function injectAccessControlService(AccessControlService $accessControllService): void
|
||||||
|
{
|
||||||
|
$this->accessControllService = $accessControllService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Validator\StepconfValidator
|
||||||
|
*/
|
||||||
|
protected $stepconfValidator;
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Validator\StepconfValidator $stepconfValidator
|
||||||
|
*/
|
||||||
|
public function injectStepconfValidator(StepconfValidator $stepconfValidator): void
|
||||||
|
{
|
||||||
|
$this->stepconfValidator = $stepconfValidator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
|
||||||
|
*/
|
||||||
|
protected $configurationManager;
|
||||||
|
/**
|
||||||
|
* @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
|
||||||
|
*/
|
||||||
|
public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager): void
|
||||||
|
{
|
||||||
|
$this->configurationManager = $configurationManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the settings of the current extension
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $settings;
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\RatingImage
|
||||||
|
*/
|
||||||
|
protected $ratingImage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface
|
||||||
|
*/
|
||||||
|
protected $extDefaultQuerySettings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public function initializeObject(): void
|
||||||
|
{
|
||||||
|
$this->settings = $this->configurationManager->getConfiguration(
|
||||||
|
ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
|
||||||
|
'thrating',
|
||||||
|
'pi1'
|
||||||
|
);
|
||||||
|
|
||||||
|
$frameworkConfiguration = $this->configurationManager->getConfiguration(
|
||||||
|
ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK,
|
||||||
|
'thrating',
|
||||||
|
'pi1'
|
||||||
|
);
|
||||||
|
if (!empty($frameworkConfiguration['ratings'])) {
|
||||||
|
//Merge extension ratingConfigurations with customer added ones
|
||||||
|
ArrayUtility::mergeRecursiveWithOverrule(
|
||||||
|
$this->settings['ratingConfigurations'],
|
||||||
|
$frameworkConfiguration['ratings']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
|
||||||
|
*/
|
||||||
|
protected function getTypoScriptFrontendController(): TypoScriptFrontendController
|
||||||
|
{
|
||||||
|
global $TSFE;
|
||||||
|
|
||||||
|
return $TSFE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the completed settings array
|
||||||
|
*
|
||||||
|
* @param array $settings
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function completeConfigurationSettings(array $settings): array
|
||||||
|
{
|
||||||
|
$cObj = $this->configurationManager->getContentObject();
|
||||||
|
|
||||||
|
if (!empty($cObj->currentRecord)) {
|
||||||
|
/* build array [0=>cObj tablename, 1=> cObj uid] - initialize with content information
|
||||||
|
(usage as normal content) */
|
||||||
|
$currentRecord = explode(':', $cObj->currentRecord);
|
||||||
|
} else {
|
||||||
|
//build array [0=>cObj tablename, 1=> cObj uid] - initialize with page info if used by typoscript
|
||||||
|
$currentRecord = ['pages', $GLOBALS['TSFE']->page['uid']];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($settings['ratetable'])) {
|
||||||
|
$settings['ratetable'] = $currentRecord[0];
|
||||||
|
}
|
||||||
|
if (empty($settings['ratefield'])) {
|
||||||
|
$settings['ratefield'] = 'uid';
|
||||||
|
}
|
||||||
|
if (empty($settings['ratedobjectuid'])) {
|
||||||
|
$settings['ratedobjectuid'] = $currentRecord[1];
|
||||||
|
}
|
||||||
|
return $settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new or existing ratingobject
|
||||||
|
*
|
||||||
|
* @param array $settings
|
||||||
|
* @throws \WapplerSystems\BookmarksLikesRatings\Exception\RecordNotFoundException
|
||||||
|
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
|
||||||
|
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject
|
||||||
|
*/
|
||||||
|
public function getRatingobject(array $settings): Ratingobject
|
||||||
|
{
|
||||||
|
$ratingobject = null;
|
||||||
|
|
||||||
|
//check whether a dedicated ratingobject is configured
|
||||||
|
if (!empty($settings['ratingobject'])) {
|
||||||
|
$ratingobject = $this->ratingobjectRepository->findByUid($settings['ratingobject']);
|
||||||
|
} else {
|
||||||
|
if (empty($settings['ratetable']) || empty($settings['ratefield'])) {
|
||||||
|
//fallback to default configuration
|
||||||
|
$settings = $settings['defaultObject'] + $settings;
|
||||||
|
}
|
||||||
|
$settings = $this->completeConfigurationSettings($settings);
|
||||||
|
$ratingobject = $this->ratingobjectRepository->findMatchingTableAndField(
|
||||||
|
$settings['ratetable'],
|
||||||
|
$settings['ratefield'],
|
||||||
|
RatingobjectRepository::ADD_IF_NOT_FOUND
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $ratingobject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new or existing ratingobject
|
||||||
|
*
|
||||||
|
* @param array $stepconfArray
|
||||||
|
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf
|
||||||
|
*/
|
||||||
|
public function createStepconf(array $stepconfArray): Stepconf
|
||||||
|
{
|
||||||
|
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf $stepconf */
|
||||||
|
$stepconf = $this->objectManager->get(Stepconf::class);
|
||||||
|
$stepconf->setRatingobject($stepconfArray['ratingobject']);
|
||||||
|
$stepconf->setSteporder($stepconfArray['steporder']);
|
||||||
|
$stepconf->setStepweight($stepconfArray['stepweight']);
|
||||||
|
|
||||||
|
return $stepconf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new or existing ratingobject
|
||||||
|
*
|
||||||
|
* @param Stepconf $stepconf
|
||||||
|
* @param array $stepnameArray
|
||||||
|
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepname
|
||||||
|
* @throws LanguageNotFoundException
|
||||||
|
* @throws \TYPO3\CMS\Core\Exception\SiteNotFoundException
|
||||||
|
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
|
||||||
|
*/
|
||||||
|
public function createStepname(Stepconf $stepconf, array $stepnameArray): Stepname
|
||||||
|
{
|
||||||
|
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepname $stepname */
|
||||||
|
$stepname = $this->objectManager->get(Stepname::class);
|
||||||
|
$stepname->setStepconf($stepconf);
|
||||||
|
$stepname->setStepname($stepnameArray['stepname']);
|
||||||
|
$stepname->setPid($stepnameArray['pid']);
|
||||||
|
$stepname->setSysLanguageUid(
|
||||||
|
$this->getStaticLanguageByIsoCode(
|
||||||
|
$stepname->getPid(),
|
||||||
|
$stepnameArray['twoLetterIsoCode'] ?: null
|
||||||
|
)->getLanguageId()
|
||||||
|
);
|
||||||
|
|
||||||
|
$defaultStepname = $this->stepnameRepository->findDefaultStepname($stepname);
|
||||||
|
$l18nParent = is_null($defaultStepname) ? 0 : $defaultStepname->getUid();
|
||||||
|
$stepname->setL18nParent($l18nParent);
|
||||||
|
return $stepname;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new or existing rating
|
||||||
|
*
|
||||||
|
* @param array $settings
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject|null $ratingobject
|
||||||
|
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating
|
||||||
|
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
|
||||||
|
* @throws \WapplerSystems\BookmarksLikesRatings\Service\Exception
|
||||||
|
*/
|
||||||
|
public function getRating(array $settings, ?Ratingobject $ratingobject): Rating
|
||||||
|
{
|
||||||
|
$settings = $this->completeConfigurationSettings($settings);
|
||||||
|
if (!empty($settings['rating'])) {
|
||||||
|
//fetch rating when it is configured
|
||||||
|
$rating = $this->ratingRepository->findByUid($settings['rating']);
|
||||||
|
} elseif ($settings['ratedobjectuid'] && !$this->objectManager->get(RatingobjectValidator::class)
|
||||||
|
->validate($ratingobject)->hasErrors()) {
|
||||||
|
//get rating according to given row
|
||||||
|
/** @noinspection NullPointerExceptionInspection */
|
||||||
|
$rating = $this->ratingRepository->findMatchingObjectAndUid(
|
||||||
|
$ratingobject,
|
||||||
|
$settings['ratedobjectuid'],
|
||||||
|
RatingRepository::ADD_IF_NOT_FOUND
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw new \WapplerSystems\BookmarksLikesRatings\Service\Exception(
|
||||||
|
'Incomplete configuration setting. Either \'rating\' or \'ratedobjectuid\' are missing.',
|
||||||
|
1398351336
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $rating;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new or existing vote
|
||||||
|
*
|
||||||
|
* @param string $prefixId
|
||||||
|
* @param array $settings
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating $rating
|
||||||
|
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote
|
||||||
|
* @throws \WapplerSystems\BookmarksLikesRatings\Exception\FeUserNotFoundException
|
||||||
|
*/
|
||||||
|
public function getVote(string $prefixId, array $settings, Rating $rating): Vote
|
||||||
|
{
|
||||||
|
// initialize variables
|
||||||
|
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote $vote */
|
||||||
|
$vote = null;
|
||||||
|
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Voter $voter */
|
||||||
|
$voter = null;
|
||||||
|
|
||||||
|
//first fetch real voter or anonymous
|
||||||
|
/** @var int $frontendUserUid */
|
||||||
|
$frontendUserUid = $this->accessControllService->getFrontendUserUid();
|
||||||
|
if (!$frontendUserUid && !empty($settings['mapAnonymous'])) {
|
||||||
|
//set anonymous vote
|
||||||
|
$voter = $this->accessControllService->getFrontendVoter($settings['mapAnonymous']);
|
||||||
|
$anonymousRating = GeneralUtility::makeInstance(\WapplerSystems\BookmarksLikesRatings\Service\JsonService::class)
|
||||||
|
->decodeJsonToArray($_COOKIE[$prefixId . '_AnonymousRating_' . $rating->getUid()]);
|
||||||
|
if (!empty($anonymousRating['voteUid'])) {
|
||||||
|
$vote = $this->voteRepository->findByUid($anonymousRating['voteUid']);
|
||||||
|
}
|
||||||
|
} elseif ($frontendUserUid) {
|
||||||
|
//set FEUser if one is logged on
|
||||||
|
$voter = $this->accessControllService->getFrontendVoter($frontendUserUid);
|
||||||
|
if ($voter instanceof \WapplerSystems\BookmarksLikesRatings\Domain\Model\Voter) {
|
||||||
|
$vote = $this->voteRepository->findMatchingRatingAndVoter($rating, $voter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//voting not found in database or anonymous vote? - create new one
|
||||||
|
$voteValidator = $this->objectManager->get(VoteValidator::class);
|
||||||
|
if ($voteValidator->validate($vote)->hasErrors()) {
|
||||||
|
$vote = $this->objectManager->get(Vote::class);
|
||||||
|
$ratingValidator = $this->objectManager->get(RatingValidator::class);
|
||||||
|
if (!$ratingValidator->validate($rating)->hasErrors()) {
|
||||||
|
$vote->setRating($rating);
|
||||||
|
}
|
||||||
|
if ($voter instanceof \WapplerSystems\BookmarksLikesRatings\Domain\Model\Voter) {
|
||||||
|
$vote->setVoter($voter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $vote;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a logger instance
|
||||||
|
* The configuration of the logger is modified by extension typoscript config
|
||||||
|
*
|
||||||
|
* @param string|null $name the class name which this logger is for
|
||||||
|
* @return \TYPO3\CMS\Core\Log\Logger
|
||||||
|
*/
|
||||||
|
public function getLogger(?string $name): Logger
|
||||||
|
{
|
||||||
|
if (empty($name)) {
|
||||||
|
return $this->loggingService->getLogger(__CLASS__);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->loggingService->getLogger($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update and persist attached objects to the repository
|
||||||
|
*
|
||||||
|
* @param string $repository
|
||||||
|
* @param \TYPO3\CMS\Extbase\DomainObject\AbstractEntity $objectToPersist
|
||||||
|
*/
|
||||||
|
public function persistRepository(string $repository, AbstractEntity $objectToPersist): void
|
||||||
|
{
|
||||||
|
$objectUid = $objectToPersist->getUid();
|
||||||
|
if (!is_int($objectUid)) {
|
||||||
|
$this->objectManager->get($repository)->add($objectToPersist);
|
||||||
|
} else {
|
||||||
|
$this->objectManager->get($repository)->update($objectToPersist);
|
||||||
|
}
|
||||||
|
$this->objectManager->get(PersistenceManager::class)->persistAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the dynamic CSS file for recreation
|
||||||
|
*/
|
||||||
|
public function clearDynamicCssFile(): void
|
||||||
|
{
|
||||||
|
$this->objectManager->get(DynamicCssEvaluator::class)->clearCachePostProc([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render CSS-styles for ratings and ratingsteps
|
||||||
|
* Only called by singeltonAction to render styles once per page.
|
||||||
|
* The file self::DYN_CSS_FILENAME will be created if it doesn<EFBFBD>t exist
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function renderDynCSS(): array
|
||||||
|
{
|
||||||
|
$messageArray = [];
|
||||||
|
$cssFile = '';
|
||||||
|
|
||||||
|
//create file if it does not exist
|
||||||
|
if (file_exists(Environment::getPublicPath() . '/' . self::DYN_CSS_FILENAME)) {
|
||||||
|
$fstat = stat(Environment::getPublicPath() . '/' . self::DYN_CSS_FILENAME);
|
||||||
|
//do not recreate file if it has greater than zero length
|
||||||
|
if ($fstat[7] !== 0) {
|
||||||
|
$this->logger->log(LogLevel::DEBUG, 'Dynamic CSS file exists - exiting');
|
||||||
|
return $messageArray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//now walk through all ratingobjects to calculate stepwidths
|
||||||
|
$allRatingobjects = $this->ratingobjectRepository->findAll(true);
|
||||||
|
|
||||||
|
foreach ($allRatingobjects as $ratingobject) {
|
||||||
|
$ratingobjectUid = $ratingobject->getUid();
|
||||||
|
/** @var ObjectStorage<\WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf> $stepconfObjects */
|
||||||
|
$stepconfObjects = $ratingobject->getStepconfs();
|
||||||
|
$stepcount = count($stepconfObjects);
|
||||||
|
if (!$stepcount) {
|
||||||
|
if ($this->settings['showMissingStepconfError']) {
|
||||||
|
//show error message in GUI
|
||||||
|
$messageArray[] = [
|
||||||
|
'messageText' => LocalizationUtility::translate(
|
||||||
|
'flash.renderCSS.noStepconf',
|
||||||
|
'ThRating',
|
||||||
|
[
|
||||||
|
1 => $ratingobject->getUid(),
|
||||||
|
2 => $ratingobject->getPid()
|
||||||
|
]
|
||||||
|
),
|
||||||
|
'messageTitle' => LocalizationUtility::translate(
|
||||||
|
'flash.configuration.error',
|
||||||
|
'ThRating'
|
||||||
|
),
|
||||||
|
'severity' => 'ERROR',
|
||||||
|
'additionalInfo' => [
|
||||||
|
'errorCode' => 1384705470,
|
||||||
|
'ratingobject UID' => $ratingobject->getUid(),
|
||||||
|
'ratingobject PID' => $ratingobject->getPid(),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
//only log message
|
||||||
|
$this->logger->log(
|
||||||
|
LogLevel::ERROR,
|
||||||
|
LocalizationUtility::translate(
|
||||||
|
'flash.renderCSS.noStepconf',
|
||||||
|
'ThRating',
|
||||||
|
[
|
||||||
|
1 => $ratingobject->getUid(),
|
||||||
|
2 => $ratingobject->getPid()
|
||||||
|
]
|
||||||
|
),
|
||||||
|
[
|
||||||
|
'errorCode' => 1384705470,
|
||||||
|
'ratingobject UID' => $ratingobject->getUid(),
|
||||||
|
'ratingobject PID' => $ratingobject->getPid(),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$stepWeights = [];
|
||||||
|
$sumStepWeights = 0;
|
||||||
|
|
||||||
|
$stepconfs = $stepconfObjects->toArray();
|
||||||
|
foreach ($stepconfs as $stepconf) { //stepconfs are already sorted by steporder
|
||||||
|
//just do checks here that all steps are OK
|
||||||
|
if (!$this->stepconfValidator->validate($stepconf)->hasErrors()) {
|
||||||
|
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf $stepconf */
|
||||||
|
$stepWeights[] = $stepconf->getStepweight();
|
||||||
|
$sumStepWeights += $stepconf->getStepweight();
|
||||||
|
} else {
|
||||||
|
foreach ($this->stepconfValidator->validate($stepconf)->getErrors() as $errorMessage) {
|
||||||
|
$messageArray[] = [
|
||||||
|
'messageText' => $errorMessage->getMessage(),
|
||||||
|
'messageTitle' => LocalizationUtility::translate('flash.configuration.error', 'ThRating'),
|
||||||
|
'severity' => 'ERROR',
|
||||||
|
'additionalInfo' => ['errorCode' => $errorMessage->getCode(),
|
||||||
|
'errorMessage' => $errorMessage->getMessage(), ], ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->logger->log(
|
||||||
|
LogLevel::INFO,
|
||||||
|
'Ratingobject data',
|
||||||
|
[
|
||||||
|
'ratingobject UID' => $ratingobject->getUid(),
|
||||||
|
'ratingobject PID' => $ratingobject->getPid(),
|
||||||
|
'stepcount' => $stepcount,
|
||||||
|
'stepWeights' => $stepWeights,
|
||||||
|
'sumStepWeights' => $sumStepWeights,
|
||||||
|
'messageCount' => count($messageArray)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
//generate CSS for all ratings out of TSConfig
|
||||||
|
foreach ($this->settings['ratingConfigurations'] as $ratingName => $ratingConfig) {
|
||||||
|
if ($ratingName === 'default') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$subURI = substr(Environment::getPublicPath() . '/', strlen($_SERVER['DOCUMENT_ROOT']) + 1);
|
||||||
|
$basePath = $this->getTypoScriptFrontendController()->baseUrl ?: '//' .
|
||||||
|
$_SERVER['HTTP_HOST'] . '/' . $subURI;
|
||||||
|
|
||||||
|
$this->ratingImage = $this->objectManager->get(RatingImage::class);
|
||||||
|
$this->ratingImage->setConf($ratingConfig['imagefile']);
|
||||||
|
$filename = $this->ratingImage->getImageFile();
|
||||||
|
if (empty($filename)) {
|
||||||
|
$messageArray[] = [
|
||||||
|
'messageText' => LocalizationUtility::translate(
|
||||||
|
'flash.vote.renderCSS.defaultImage',
|
||||||
|
'ThRating'
|
||||||
|
),
|
||||||
|
'messageTitle' => LocalizationUtility::translate(
|
||||||
|
'flash.heading.warning',
|
||||||
|
'ThRating'
|
||||||
|
),
|
||||||
|
'severity' => 'WARNING',
|
||||||
|
'additionalInfo' => ['errorCode' => 1403192702,
|
||||||
|
'ratingName' => $ratingName,
|
||||||
|
'ratingConfig' => $ratingConfig, ], ];
|
||||||
|
$defaultRatingName = $this->settings['ratingConfigurations']['default'];
|
||||||
|
$ratingConfig = $this->settings['ratingConfigurations'][$defaultRatingName];
|
||||||
|
$this->ratingImage->setConf($ratingConfig['imagefile']);
|
||||||
|
$filename = $this->ratingImage->getImageFile();
|
||||||
|
}
|
||||||
|
$filenameUri = $basePath . '/' . $filename; //prepend host basepath if no URL is given
|
||||||
|
|
||||||
|
$imageDimensions = $this->ratingImage->getImageDimensions();
|
||||||
|
$height = $imageDimensions['height'];
|
||||||
|
$width = $imageDimensions['width'];
|
||||||
|
$mainId = '.thRating-RObj' . $ratingobjectUid . '-' . $ratingName;
|
||||||
|
$this->logger->log(
|
||||||
|
LogLevel::DEBUG,
|
||||||
|
'Main CSS info',
|
||||||
|
[
|
||||||
|
'mainId' => $mainId,
|
||||||
|
'filenameUri' => $filenameUri,
|
||||||
|
'image width' => $width,
|
||||||
|
'image height' => $height, ]
|
||||||
|
);
|
||||||
|
|
||||||
|
//calculate overall rating size depending on rating direction
|
||||||
|
if ($ratingConfig['tilt']) {
|
||||||
|
$width = round($width / 3, 1);
|
||||||
|
if (!$ratingConfig['barimage']) {
|
||||||
|
$height *= $sumStepWeights;
|
||||||
|
}
|
||||||
|
$cssFile .= $mainId . ' { width:' . $width . 'px; height:' . $height . 'px; }' . chr(10);
|
||||||
|
$cssFile .= $mainId . ', ' . $mainId . ' span:hover, ' . $mainId . ' span:active, ' . $mainId .
|
||||||
|
' span:focus, ' . $mainId . ' .current-rating { background:url(' . $filenameUri .
|
||||||
|
') right bottom repeat-y; }' . chr(10);
|
||||||
|
$cssFile .= $mainId . ' span, ' . $mainId . ' .current-rating { width:' . $width . 'px; }' .
|
||||||
|
chr(10);
|
||||||
|
} else {
|
||||||
|
$height = round($height / 3, 1);
|
||||||
|
if (!$ratingConfig['barimage']) {
|
||||||
|
$width *= $sumStepWeights;
|
||||||
|
}
|
||||||
|
$cssFile .= $mainId . ' { width:' . $width . 'px; height:' . $height . 'px; }' . chr(10);
|
||||||
|
$cssFile .= $mainId . ', ' . $mainId . ' span:hover, ' . $mainId . ' span:active, ' . $mainId .
|
||||||
|
' span:focus, ' . $mainId . ' .current-rating { background:url(' . $filenameUri .
|
||||||
|
') 0 0 repeat-x; }' . chr(10);
|
||||||
|
$cssFile .= $mainId . ' span, ' . $mainId . ' .current-rating { height:' . $height .
|
||||||
|
'px; line-height:' . $height . 'px; }' . chr(10);
|
||||||
|
//calculate widths/heights related to stepweights
|
||||||
|
}
|
||||||
|
$cssFile .= $mainId . ' .current-poll { background:url(' . $filenameUri . '); }' . chr(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
//calculate widths/heights related to stepweights
|
||||||
|
$i = 1;
|
||||||
|
$stepPart = 0;
|
||||||
|
$sumWeights = 0;
|
||||||
|
foreach ($stepWeights as $stepWeight) {
|
||||||
|
$sumWeights += $stepWeight;
|
||||||
|
$zIndex = $stepcount - $i + 2; //add 2 to override .current-poll and .currentPollText
|
||||||
|
//configure rating and polling styles for steps
|
||||||
|
$oneStepPart = round($stepWeight * 100 / $sumStepWeights, 1); //calculate single width of ratingstep
|
||||||
|
$cssFile .= 'span.RObj' . $ratingobjectUid . '-StpOdr' . $i . '-ratingpoll-normal { width:' .
|
||||||
|
$oneStepPart . '%; z-index:' . $zIndex . '; margin-left:' . $stepPart . '%;}' . chr(10);
|
||||||
|
$cssFile .= 'span.RObj' . $ratingobjectUid . '-StpOdr' . $i . '-ratingpoll-tilt { height:' .
|
||||||
|
$oneStepPart . '%; z-index:' . $zIndex . '; margin-bottom:' . $stepPart . '%; }' . chr(10);
|
||||||
|
$cssFile .= 'li.RObj' . $ratingobjectUid . '-StpOdr' . $i . '-currentpoll-normal { width:' .
|
||||||
|
$oneStepPart . '%; margin-left:' . $stepPart . '%; }' . chr(10);
|
||||||
|
$cssFile .= 'li.RObj' . $ratingobjectUid . '-StpOdr' . $i . '-currentpoll-normal span { width:100%; }' .
|
||||||
|
chr(10);
|
||||||
|
$cssFile .= 'li.RObj' . $ratingobjectUid . '-StpOdr' . $i . '-currentpoll-tilt { height:' .
|
||||||
|
$oneStepPart . '%; margin-bottom:' . $stepPart . '%; }' . chr(10);
|
||||||
|
$cssFile .= 'li.RObj' . $ratingobjectUid . '-StpOdr' . $i . '-currentpoll-tilt span { height:100%; }' .
|
||||||
|
chr(10);
|
||||||
|
$stepPart = round($sumWeights * 100 / $sumStepWeights, 1); //calculate sum of widths to this ratingstep
|
||||||
|
$cssFile .= 'span.RObj' . $ratingobjectUid . '-StpOdr' . $i . '-ratingstep-normal { width:' .
|
||||||
|
$stepPart . '%; z-index:' . $zIndex . '; }' . chr(10);
|
||||||
|
$cssFile .= 'span.RObj' . $ratingobjectUid . '-StpOdr' . $i . '-ratingstep-tilt { height:' .
|
||||||
|
$stepPart . '%; z-index:' . $zIndex . '; }' . chr(10);
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
//reset variables for next iteration
|
||||||
|
unset($stepWeights, $sumWeights, $sumStepWeights);
|
||||||
|
$this->logger->log(LogLevel::DEBUG, 'CSS finished for ratingobject');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logger->log(LogLevel::DEBUG, 'Saving CSS file', ['cssFile' => $cssFile]);
|
||||||
|
$fp = fopen(Environment::getPublicPath() . '/' . self::DYN_CSS_FILENAME, 'wb');
|
||||||
|
fwrite($fp, $cssFile);
|
||||||
|
fclose($fp);
|
||||||
|
|
||||||
|
return $messageArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the language object
|
||||||
|
* If not ISO code is provided the default language is returned
|
||||||
|
*
|
||||||
|
* @param int $pid page id to which is part of the site
|
||||||
|
* @param string|null $twoLetterIsoCode iso-639-1 string (e.g. en, de, us)
|
||||||
|
* @return \TYPO3\CMS\Core\Site\Entity\SiteLanguage
|
||||||
|
* @throws LanguageNotFoundException
|
||||||
|
*/
|
||||||
|
public function getStaticLanguageByIsoCode(int $pid, string $twoLetterIsoCode = null): SiteLanguage
|
||||||
|
{
|
||||||
|
/** @var Site $site */
|
||||||
|
$site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($pid);
|
||||||
|
|
||||||
|
if (!is_null($twoLetterIsoCode)) {
|
||||||
|
foreach ($site->getAllLanguages() as $language) {
|
||||||
|
if ($language->getTwoLetterIsoCode() === $twoLetterIsoCode) {
|
||||||
|
return $language;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new LanguageNotFoundException(LocalizationUtility::translate(
|
||||||
|
'flash.general.languageNotFound',
|
||||||
|
'ThRating'
|
||||||
|
), 1582980369);
|
||||||
|
}
|
||||||
|
return $site->getDefaultLanguage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the language object
|
||||||
|
* If not ISO code is provided the default language is returned
|
||||||
|
*
|
||||||
|
* @param int $pid page id to which is part of the site
|
||||||
|
* @param int|null $languageId iso-639-1 string (e.g. en, de, us)
|
||||||
|
* @return \TYPO3\CMS\Core\Site\Entity\SiteLanguage
|
||||||
|
* @throws \TYPO3\CMS\Core\Exception\SiteNotFoundException
|
||||||
|
*/
|
||||||
|
public function getStaticLanguageById(int $pid, int $languageId = null): ?SiteLanguage
|
||||||
|
{
|
||||||
|
/** @var Site $site */
|
||||||
|
$site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($pid);
|
||||||
|
|
||||||
|
if ($languageId) {
|
||||||
|
return $site->getLanguageById($languageId);
|
||||||
|
}
|
||||||
|
return $site->getDefaultLanguage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ServerRequestInterface
|
||||||
|
*/
|
||||||
|
public function getRequest(): ServerRequestInterface
|
||||||
|
{
|
||||||
|
return $GLOBALS['TYPO3_REQUEST'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current request object
|
||||||
|
*
|
||||||
|
* @param \TYPO3\CMS\Extbase\Mvc\Request $request
|
||||||
|
*/
|
||||||
|
public function setRequest(\TYPO3\CMS\Extbase\Mvc\Request $request): void
|
||||||
|
{
|
||||||
|
$this->request = $request;
|
||||||
|
}
|
||||||
|
}
|
185
Classes/Service/ExtensionManagementService.php
Normal file
185
Classes/Service/ExtensionManagementService.php
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types = 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||||
|
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf;
|
||||||
|
use TYPO3\CMS\Core\Log\LogLevel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for model objects
|
||||||
|
*
|
||||||
|
* @version $Id:$
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GNU protected License, version 2
|
||||||
|
*/
|
||||||
|
class ExtensionManagementService extends AbstractExtensionService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Service\ExtensionConfigurationService
|
||||||
|
*/
|
||||||
|
protected $extensionConfigurationService;
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Service\ExtensionConfigurationService $extensionConfigurationService
|
||||||
|
*/
|
||||||
|
public function injectExtensionConfigurationService(ExtensionConfigurationService $extensionConfigurationService): void
|
||||||
|
{
|
||||||
|
$this->extensionConfigurationService = $extensionConfigurationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService
|
||||||
|
*/
|
||||||
|
protected $extensionHelperService;
|
||||||
|
/**
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService $extensionHelperService
|
||||||
|
*/
|
||||||
|
public function injectExtensionHelperService(ExtensionHelperService $extensionHelperService)
|
||||||
|
{
|
||||||
|
$this->extensionHelperService = $extensionHelperService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares an object for ratings
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @param string $tablename
|
||||||
|
* @param string $fieldname
|
||||||
|
* @param int $stepcount
|
||||||
|
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject
|
||||||
|
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
|
||||||
|
* @throws \WapplerSystems\BookmarksLikesRatings\Exception\RecordNotFoundException
|
||||||
|
*/
|
||||||
|
public function makeRatable(string $tablename, string $fieldname, int $stepcount): Ratingobject
|
||||||
|
{
|
||||||
|
$this->logger->log(
|
||||||
|
LogLevel::INFO,
|
||||||
|
'makeRatable called',
|
||||||
|
['tablename' => $tablename, 'fieldname' => $fieldname, 'stepcount' => $stepcount]
|
||||||
|
);
|
||||||
|
$this->extensionConfigurationService->prepareExtensionConfiguration();
|
||||||
|
|
||||||
|
$ratingobject = $this->extensionHelperService->getRatingobject(
|
||||||
|
['ratetable' => $tablename, 'ratefield' => $fieldname]
|
||||||
|
);
|
||||||
|
|
||||||
|
//create a new default stepconf having stepweight 1 for each step
|
||||||
|
for ($i = 1; $i <= $stepcount; $i++) {
|
||||||
|
$stepconfArray = ['ratingobject' => $ratingobject, 'steporder' => $i, 'stepweight' => 1];
|
||||||
|
$stepconf = $this->extensionHelperService->createStepconf($stepconfArray);
|
||||||
|
$ratingobject->addStepconf($stepconf);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Full reload of newly created object
|
||||||
|
$ratingobject = $this->extensionHelperService->getRatingobject(
|
||||||
|
['ratetable' => $tablename, 'ratefield' => $fieldname]
|
||||||
|
);
|
||||||
|
|
||||||
|
// CREATE NEW DYNCSS FILE
|
||||||
|
$this->extensionHelperService->clearDynamicCssFile();
|
||||||
|
$this->extensionHelperService->renderDynCSS();
|
||||||
|
$this->extensionConfigurationService->restoreCallingExtensionConfiguration();
|
||||||
|
return $ratingobject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares an object for ratings
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf $stepconf
|
||||||
|
* @param string $stepname
|
||||||
|
* @param string|null $twoLetterIsoCode
|
||||||
|
* @param bool $allStepconfs Take stepname for all steps and add steporder number at the end
|
||||||
|
* @return bool
|
||||||
|
* @throws \TYPO3\CMS\Core\Exception\SiteNotFoundException
|
||||||
|
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
|
||||||
|
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
|
||||||
|
* @throws \WapplerSystems\BookmarksLikesRatings\Exception\Exception
|
||||||
|
*/
|
||||||
|
public function setStepname(
|
||||||
|
Stepconf $stepconf,
|
||||||
|
string $stepname,
|
||||||
|
string $twoLetterIsoCode=null,
|
||||||
|
bool $allStepconfs = false
|
||||||
|
): bool {
|
||||||
|
$this->logger->log(
|
||||||
|
LogLevel::INFO,
|
||||||
|
'setStepname called',
|
||||||
|
[
|
||||||
|
'stepconf' => $stepconf->getUid(),
|
||||||
|
'steporder' => $stepconf->getSteporder(),
|
||||||
|
'stepname' => $stepname,
|
||||||
|
'twoLetterIsoCode' => $twoLetterIsoCode,
|
||||||
|
'allStepconfs' => $allStepconfs
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->extensionConfigurationService->prepareExtensionConfiguration();
|
||||||
|
|
||||||
|
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject $ratingobject */
|
||||||
|
$ratingobject = $stepconf->getRatingobject();
|
||||||
|
|
||||||
|
$success = true;
|
||||||
|
if (!$allStepconfs) {
|
||||||
|
//only add the one specific stepname
|
||||||
|
$stepnameArray = [
|
||||||
|
'stepname' => $stepname,
|
||||||
|
'twoLetterIsoCode' => $twoLetterIsoCode,
|
||||||
|
'pid' => $stepconf->getPid()
|
||||||
|
];
|
||||||
|
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepname $stepname */
|
||||||
|
$stepnameObject = $this->extensionHelperService->createStepname($stepconf, $stepnameArray);
|
||||||
|
|
||||||
|
if (!$stepconf->addStepname($stepnameObject)) {
|
||||||
|
$this->logger->log(
|
||||||
|
LogLevel::WARNING,
|
||||||
|
'Stepname entry for language already exists',
|
||||||
|
[
|
||||||
|
'stepconf' => $stepconf->getUid(),
|
||||||
|
'steporder' => $stepconf->getSteporder(),
|
||||||
|
'stepname' => $stepnameObject,
|
||||||
|
'twoLetterIsoCode' => $twoLetterIsoCode,
|
||||||
|
'errorCode' => 1398972827
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
//add stepnames to every stepconf
|
||||||
|
foreach ($ratingobject->getStepconfs() as $loopStepConf) {
|
||||||
|
$stepnameArray = [
|
||||||
|
'stepname' => $stepname . $loopStepConf->getSteporder(),
|
||||||
|
'twoLetterIsoCode' => $twoLetterIsoCode,
|
||||||
|
'pid' => $ratingobject->getPid()
|
||||||
|
];
|
||||||
|
|
||||||
|
$stepnameObject = $this->extensionHelperService->createStepname($loopStepConf, $stepnameArray);
|
||||||
|
if ($success && !$loopStepConf->addStepname($stepnameObject)) {
|
||||||
|
$this->logger->log(
|
||||||
|
LogLevel::WARNING,
|
||||||
|
'Stepname entry for language already exists',
|
||||||
|
[
|
||||||
|
'stepconf' => $stepconf->getUid(),
|
||||||
|
'steporder' => $stepconf->getSteporder(),
|
||||||
|
'stepname' => $stepname,
|
||||||
|
'twoLetterIsoCode' => $twoLetterIsoCode,
|
||||||
|
'errorCode' => 1398972331
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->extensionConfigurationService->restoreCallingExtensionConfiguration();
|
||||||
|
return $success;
|
||||||
|
}
|
||||||
|
}
|
81
Classes/Service/JsonService.php
Normal file
81
Classes/Service/JsonService.php
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\Log\LogLevel;
|
||||||
|
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for setting cookies like Typo3 does
|
||||||
|
*
|
||||||
|
* @version $Id:$
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GNU protected License, version 2
|
||||||
|
*/
|
||||||
|
class JsonService extends AbstractExtensionService
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a string to JSON
|
||||||
|
* Log a warning on error
|
||||||
|
*
|
||||||
|
* @param mixed $content
|
||||||
|
* @return string|false The domain to be used on setting cookies
|
||||||
|
*/
|
||||||
|
public function encodeToJson($content)
|
||||||
|
{
|
||||||
|
if (!empty($content)) {
|
||||||
|
try {
|
||||||
|
return json_encode($content, JSON_THROW_ON_ERROR);
|
||||||
|
} catch (\JsonException $e) {
|
||||||
|
$this->logger->log(
|
||||||
|
LogLevel::WARNING,
|
||||||
|
LocalizationUtility::translate('system.warning.json.encode', 'ThRating', [
|
||||||
|
1 => $content,
|
||||||
|
]),
|
||||||
|
[
|
||||||
|
'errorCode' => 1615051494,
|
||||||
|
'JSON' => $content,
|
||||||
|
'Exception' => $e,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a string to JSON
|
||||||
|
* Log a warning on error
|
||||||
|
*
|
||||||
|
* @param string|null $content
|
||||||
|
* @return array|false The domain to be used on setting cookies
|
||||||
|
*/
|
||||||
|
public function decodeJsonToArray(string $content=null)
|
||||||
|
{
|
||||||
|
if (!empty($content)) {
|
||||||
|
try {
|
||||||
|
return json_decode($content, true, 512, JSON_THROW_ON_ERROR);
|
||||||
|
} catch (\JsonException $e) {
|
||||||
|
$this->logger->log(
|
||||||
|
LogLevel::WARNING,
|
||||||
|
LocalizationUtility::translate('system.warning.json.encode', 'ThRating', [
|
||||||
|
1 => $content,
|
||||||
|
]),
|
||||||
|
[
|
||||||
|
'errorCode' => 1615051494,
|
||||||
|
'JSON' => $content,
|
||||||
|
'Exception' => $e,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
83
Classes/Service/LoggingService.php
Normal file
83
Classes/Service/LoggingService.php
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\Log\Logger;
|
||||||
|
use TYPO3\CMS\Core\Log\LogManager;
|
||||||
|
use TYPO3\CMS\Core\Log\Writer\DatabaseWriter;
|
||||||
|
use TYPO3\CMS\Core\Log\Writer\FileWriter;
|
||||||
|
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
|
||||||
|
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for model objects
|
||||||
|
*
|
||||||
|
* @version $Id:$
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GNU protected License, version 2
|
||||||
|
*/
|
||||||
|
class LoggingService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
|
||||||
|
*/
|
||||||
|
protected $objectManager;
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
|
||||||
|
*/
|
||||||
|
protected $configurationManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* Must overrule the abstract class method to avoid self referencing
|
||||||
|
* @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
|
||||||
|
* @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager,
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
ObjectManagerInterface $objectManager,
|
||||||
|
ConfigurationManagerInterface $configurationManager
|
||||||
|
) {
|
||||||
|
$this->objectManager = $objectManager;
|
||||||
|
$this->configurationManager = $configurationManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a logger instance
|
||||||
|
* The configuration of the logger is modified by extension typoscript config
|
||||||
|
*
|
||||||
|
* @param string $name the class name which this logger is for
|
||||||
|
* @return \TYPO3\CMS\Core\Log\Logger
|
||||||
|
*/
|
||||||
|
public function getLogger(string $name): Logger
|
||||||
|
{
|
||||||
|
/** @var array $writerConfiguration */
|
||||||
|
$writerConfiguration = $GLOBALS['TYPO3_CONF_VARS']['LOG']['Thucke']['ThRating']['writerConfiguration'];
|
||||||
|
$settings = $this->configurationManager->getConfiguration(
|
||||||
|
ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
|
||||||
|
'thRating',
|
||||||
|
'pi1'
|
||||||
|
);
|
||||||
|
if (is_array($settings['logging'])) {
|
||||||
|
foreach ($settings['logging'] as $logLevel => $logConfig) {
|
||||||
|
$levelUppercase = strtoupper($logLevel);
|
||||||
|
if (!empty($logConfig['file'])) {
|
||||||
|
$writerConfiguration[constant('\TYPO3\CMS\Core\Log\LogLevel::' . $levelUppercase)][FileWriter::class] = ['logFile' => $logConfig['file']];
|
||||||
|
}
|
||||||
|
if (!empty($logConfig['database'])) {
|
||||||
|
$writerConfiguration[constant('\TYPO3\CMS\Core\Log\LogLevel::' . $levelUppercase)][DatabaseWriter::class] = ['table' => $logConfig['table']];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($writerConfiguration)) {
|
||||||
|
$GLOBALS['TYPO3_CONF_VARS']['LOG']['Thucke']['ThRating']['writerConfiguration'] = $writerConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->objectManager->get(LogManager::class)->getLogger($name);
|
||||||
|
}
|
||||||
|
}
|
442
Classes/Service/RichSnippetService.php
Normal file
442
Classes/Service/RichSnippetService.php
Normal file
@ -0,0 +1,442 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||||
|
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
|
||||||
|
use TYPO3\CMS\Core\Log\LogLevel;
|
||||||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||||
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The voter
|
||||||
|
*/
|
||||||
|
class RichSnippetService extends AbstractExtensionService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Instances of AggregateRating may appear as properties of the following types
|
||||||
|
* This list derives from Google's information about supported types in aggregateRating (20 May 2021)
|
||||||
|
* (see https://developers.google.com/search/docs/data-types/review-snippet#aggregated-rating-type-definition)
|
||||||
|
* @const array
|
||||||
|
*/
|
||||||
|
protected const VALID_AGGREGATE_RATING_SCHEMA_TYPES = [
|
||||||
|
'Book',
|
||||||
|
'Audiobook',
|
||||||
|
'Course',
|
||||||
|
'CreativeWorkSeason',
|
||||||
|
'PodcastSeason',
|
||||||
|
'RadioSeason',
|
||||||
|
'TVSeason',
|
||||||
|
'CreativeWorkSeries',
|
||||||
|
'BookSeries',
|
||||||
|
'MovieSeries',
|
||||||
|
'Periodical',
|
||||||
|
'ComicSeries',
|
||||||
|
'Newspaper',
|
||||||
|
'PodcastSeries',
|
||||||
|
'RadioSeries',
|
||||||
|
'TVSeries',
|
||||||
|
'VideoGameSeries',
|
||||||
|
'Episode',
|
||||||
|
'PodcastEpisode',
|
||||||
|
'RadioEpisode',
|
||||||
|
'TVEpisode',
|
||||||
|
'Event',
|
||||||
|
'BusinessEvent',
|
||||||
|
'ChildrensEvent',
|
||||||
|
'ComedyEvent',
|
||||||
|
'CourseInstance',
|
||||||
|
'DanceEvent',
|
||||||
|
'DeliveryEvent',
|
||||||
|
'EducationEvent',
|
||||||
|
'EventSeries',
|
||||||
|
'ExhibitionEvent',
|
||||||
|
'Festival',
|
||||||
|
'FoodEvent',
|
||||||
|
'Hackathon',
|
||||||
|
'LiteraryEvent',
|
||||||
|
'MusicEvent',
|
||||||
|
'PublicationEvent',
|
||||||
|
'BroadcastEvent',
|
||||||
|
'OnDemandEvent',
|
||||||
|
'SaleEvent',
|
||||||
|
'ScreeningEvent',
|
||||||
|
'SocialEvent',
|
||||||
|
'SportsEvent',
|
||||||
|
'TheaterEvent',
|
||||||
|
'VisualArtsEvent',
|
||||||
|
'Game',
|
||||||
|
'VideoGame',
|
||||||
|
'HowTo',
|
||||||
|
'Recipe',
|
||||||
|
'AnimalShelter',
|
||||||
|
'ArchiveOrganization',
|
||||||
|
'AutomotiveBusiness',
|
||||||
|
'AutoBodyShop',
|
||||||
|
'AutoDealer',
|
||||||
|
'AutoRental',
|
||||||
|
'AutoRepair',
|
||||||
|
'AutoWash',
|
||||||
|
'GasStation',
|
||||||
|
'MotorcycleDealer',
|
||||||
|
'MotorcycleRepair',
|
||||||
|
'ChildCare',
|
||||||
|
'DryCleaningOrLaundry',
|
||||||
|
'EmergencyService',
|
||||||
|
'FireStation',
|
||||||
|
'Hospital',
|
||||||
|
'PoliceStation',
|
||||||
|
'EmploymentAgency',
|
||||||
|
'EntertainmentBusiness',
|
||||||
|
'AdultEntertainment',
|
||||||
|
'AmusementPark',
|
||||||
|
'ArtGallery',
|
||||||
|
'Casino',
|
||||||
|
'ComedyClub',
|
||||||
|
'MovieTheater',
|
||||||
|
'NightClub',
|
||||||
|
'FinancialService',
|
||||||
|
'AccountingService',
|
||||||
|
'AutomatedTeller',
|
||||||
|
'BankOrCreditUnion',
|
||||||
|
'InsuranceAgency',
|
||||||
|
'FoodEstablishment',
|
||||||
|
'Bakery',
|
||||||
|
'BarOrPub',
|
||||||
|
'Brewery',
|
||||||
|
'CafeOrCoffeeShop',
|
||||||
|
'Distillery',
|
||||||
|
'FastFoodRestaurant',
|
||||||
|
'IceCreamShop',
|
||||||
|
'Restaurant',
|
||||||
|
'Winery',
|
||||||
|
'GovernmentOffice',
|
||||||
|
'PostOffice',
|
||||||
|
'HealthAndBeautyBusiness',
|
||||||
|
'BeautySalon',
|
||||||
|
'DaySpa',
|
||||||
|
'HairSalon',
|
||||||
|
'NailSalon',
|
||||||
|
'TattooParlor',
|
||||||
|
'HomeAndConstructionBusiness',
|
||||||
|
'Electrician',
|
||||||
|
'GeneralContractor',
|
||||||
|
'HVACBusiness',
|
||||||
|
'HousePainter',
|
||||||
|
'Locksmith',
|
||||||
|
'MovingCompany',
|
||||||
|
'Plumber',
|
||||||
|
'RoofingContractor',
|
||||||
|
'InternetCafe',
|
||||||
|
'LegalService',
|
||||||
|
'Attorney',
|
||||||
|
'Notary',
|
||||||
|
'Library',
|
||||||
|
'LodgingBusiness',
|
||||||
|
'BedAndBreakfast',
|
||||||
|
'Campground',
|
||||||
|
'Hostel',
|
||||||
|
'Hotel',
|
||||||
|
'Motel',
|
||||||
|
'Resort',
|
||||||
|
'MedicalBusiness',
|
||||||
|
'CovidTestingFacility',
|
||||||
|
'Optician',
|
||||||
|
'Pharmacy',
|
||||||
|
'Physician',
|
||||||
|
'ProfessionalService',
|
||||||
|
'RadioStation',
|
||||||
|
'RealEstateAgent',
|
||||||
|
'RecyclingCenter',
|
||||||
|
'SelfStorage',
|
||||||
|
'ShoppingCenter',
|
||||||
|
'SportsActivityLocation',
|
||||||
|
'BowlingAlley',
|
||||||
|
'ExerciseGym',
|
||||||
|
'GolfCourse',
|
||||||
|
'HealthClub',
|
||||||
|
'PublicSwimmingPool',
|
||||||
|
'SkiResort',
|
||||||
|
'SportsClub',
|
||||||
|
'StadiumOrArena',
|
||||||
|
'TennisComplex',
|
||||||
|
'Store',
|
||||||
|
'AutoPartsStore',
|
||||||
|
'BikeStore',
|
||||||
|
'BookStore',
|
||||||
|
'ClothingStore',
|
||||||
|
'ComputerStore',
|
||||||
|
'ConvenienceStore',
|
||||||
|
'DepartmentStore',
|
||||||
|
'ElectronicsStore',
|
||||||
|
'Florist',
|
||||||
|
'FurnitureStore',
|
||||||
|
'GardenStore',
|
||||||
|
'GroceryStore',
|
||||||
|
'HardwareStore',
|
||||||
|
'HobbyShop',
|
||||||
|
'HomeGoodsStore',
|
||||||
|
'JewelryStore',
|
||||||
|
'LiquorStore',
|
||||||
|
'MensClothingStore',
|
||||||
|
'MobilePhoneStore',
|
||||||
|
'MovieRentalStore',
|
||||||
|
'MusicStore',
|
||||||
|
'OfficeEquipmentStore',
|
||||||
|
'OutletStore',
|
||||||
|
'PawnShop',
|
||||||
|
'PetStore',
|
||||||
|
'ShoeStore',
|
||||||
|
'SportingGoodsStore',
|
||||||
|
'TireShop',
|
||||||
|
'ToyStore',
|
||||||
|
'WholesaleStore',
|
||||||
|
'TelevisionStation',
|
||||||
|
'TouristInformationCenter',
|
||||||
|
'TravelAgency',
|
||||||
|
'MediaObject',
|
||||||
|
'3DModel',
|
||||||
|
'AudioObject',
|
||||||
|
'DataDownload',
|
||||||
|
'ImageObject',
|
||||||
|
'Barcode',
|
||||||
|
'LegislationObject',
|
||||||
|
'MusicVideoObject',
|
||||||
|
'VideoObject',
|
||||||
|
'Movie',
|
||||||
|
'MusicPlaylist',
|
||||||
|
'MusicAlbum',
|
||||||
|
'MusicRelease',
|
||||||
|
'MusicRecording',
|
||||||
|
'Organization',
|
||||||
|
'Airline',
|
||||||
|
'Consortium',
|
||||||
|
'Corporation',
|
||||||
|
'EducationalOrganization',
|
||||||
|
'CollegeOrUniversity',
|
||||||
|
'ElementarySchool',
|
||||||
|
'HighSchool',
|
||||||
|
'MiddleSchool',
|
||||||
|
'Preschool',
|
||||||
|
'School',
|
||||||
|
'FundingScheme',
|
||||||
|
'GovernmentOrganization',
|
||||||
|
'LibrarySystem',
|
||||||
|
'LocalBusiness',
|
||||||
|
'MedicalOrganization',
|
||||||
|
'NGO',
|
||||||
|
'NewsMediaOrganization',
|
||||||
|
'Dentist',
|
||||||
|
'DiagnosticLab',
|
||||||
|
'MedicalClinic',
|
||||||
|
'VeterinaryCare',
|
||||||
|
'PerformingGroup',
|
||||||
|
'DanceGroup',
|
||||||
|
'MusicGroup',
|
||||||
|
'TheaterGroup',
|
||||||
|
'Project',
|
||||||
|
'FundingAgency',
|
||||||
|
'ResearchProject',
|
||||||
|
'SportsOrganization',
|
||||||
|
'SportsTeam',
|
||||||
|
'WorkersUnion',
|
||||||
|
'Product',
|
||||||
|
'IndividualProduct',
|
||||||
|
'ProductCollection',
|
||||||
|
'ProductGroup',
|
||||||
|
'ProductModel',
|
||||||
|
'SomeProducts',
|
||||||
|
'Vehicle',
|
||||||
|
'BusOrCoach',
|
||||||
|
'Car',
|
||||||
|
'Motorcycle',
|
||||||
|
'MotorizedBicycle',
|
||||||
|
'SoftwareApplication',
|
||||||
|
'MobileApplication',
|
||||||
|
'WebApplication'
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $schema = 'Product';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $anchor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $richSnippetConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $settings
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function setRichSnippetConfig(array $settings): bool
|
||||||
|
{
|
||||||
|
$this->logger->log(LogLevel::DEBUG, 'setRichSnippetConfig Entry point', $settings);
|
||||||
|
$this->richSnippetConfig['tablename'] = $settings['ratetable'];
|
||||||
|
$this->richSnippetConfig['richSnippetFields'] = $settings['richSnippetFields'];
|
||||||
|
|
||||||
|
if (is_array($this->richSnippetConfig['richSnippetFields'])) {
|
||||||
|
$this->logger->log(
|
||||||
|
LogLevel::DEBUG,
|
||||||
|
'setRichSnippetConfig Exit point',
|
||||||
|
$this->richSnippetConfig['richSnippetFields']
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logger->log(LogLevel::DEBUG, 'setRichSnippetConfig Exit point');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
|
public function getRichSnippetConfig()
|
||||||
|
{
|
||||||
|
return GeneralUtility::makeInstance(\WapplerSystems\BookmarksLikesRatings\Service\JsonService::class)
|
||||||
|
->encodeToJson($this->richSnippetConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getSchema(): string
|
||||||
|
{
|
||||||
|
return $this->schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|null $schema
|
||||||
|
* @throws \WapplerSystems\BookmarksLikesRatings\Exception\InvalidAggregateRatingSchemaTypeException if parameter is invalid
|
||||||
|
*/
|
||||||
|
public function setSchema(?string $schema): void
|
||||||
|
{
|
||||||
|
if (!empty($schema)) {
|
||||||
|
if (in_array($schema, self::VALID_AGGREGATE_RATING_SCHEMA_TYPES, true)) {
|
||||||
|
$this->schema = $schema;
|
||||||
|
} else {
|
||||||
|
throw new \WapplerSystems\BookmarksLikesRatings\Exception\InvalidAggregateRatingSchemaTypeException(
|
||||||
|
LocalizationUtility::translate(
|
||||||
|
'error.richSnippetConfiguration.AggregateRatingPropertySchema',
|
||||||
|
'ThRating'
|
||||||
|
),
|
||||||
|
1521487362
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getAnchor(): string
|
||||||
|
{
|
||||||
|
return $this->anchor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $anchor
|
||||||
|
*/
|
||||||
|
public function setAnchor(string $anchor): void
|
||||||
|
{
|
||||||
|
$this->anchor = $anchor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|null $name
|
||||||
|
*/
|
||||||
|
public function setName(?string $name): void
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getName(): ?string
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getDescription(): ?string
|
||||||
|
{
|
||||||
|
return $this->description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|null $description
|
||||||
|
*/
|
||||||
|
public function setDescription(?string $description): void
|
||||||
|
{
|
||||||
|
$this->description = $description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $uid
|
||||||
|
* @return RichSnippetService
|
||||||
|
*@throws \WapplerSystems\BookmarksLikesRatings\Exception\InvalidAggregateRatingSchemaTypeException
|
||||||
|
*/
|
||||||
|
public function getRichSnippetObject(int $uid): self
|
||||||
|
{
|
||||||
|
$this->logger->log(LogLevel::DEBUG, 'getRichSnippetObject Entry point');
|
||||||
|
$this->setSchema($this->richSnippetConfig['richSnippetFields']['aggregateRatingSchemaType']);
|
||||||
|
if (empty($this->richSnippetConfig['richSnippetFields']['name'])) {
|
||||||
|
$this->logger->log(LogLevel::INFO, 'No name field defined - skipping database access');
|
||||||
|
unset($this->name, $this->description);
|
||||||
|
throw new \TYPO3\CMS\Core\Exception();
|
||||||
|
} else {
|
||||||
|
/** @var QueryBuilder $queryBuilder */
|
||||||
|
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
|
||||||
|
->getQueryBuilderForTable($this->richSnippetConfig['tablename']);
|
||||||
|
|
||||||
|
//fetch whole row from database
|
||||||
|
/** @var array $row */
|
||||||
|
$row = $queryBuilder
|
||||||
|
->select('*')
|
||||||
|
->from($this->richSnippetConfig['tablename'])
|
||||||
|
->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid)))
|
||||||
|
->execute()
|
||||||
|
->fetch();
|
||||||
|
|
||||||
|
$this->logger->log(LogLevel::DEBUG, 'Data fetched', $row);
|
||||||
|
$this->setName($row[$this->richSnippetConfig['richSnippetFields']['name']]);
|
||||||
|
|
||||||
|
$contentObjectRenderer = GeneralUtility::makeInstance(ContentObjectRenderer::class);
|
||||||
|
$this->setDescription($row[$this->richSnippetConfig['richSnippetFields']['description']]);
|
||||||
|
//$this->setDescription($contentObjectRenderer->cObjGetSingle('TEXT', $this->richSnippetConfig['richSnippetFields']['description']));
|
||||||
|
//$this->setDescription($contentObjectRenderer->render($this->richSnippetConfig['richSnippetFields']['description']));
|
||||||
|
}
|
||||||
|
$this->logger->log(LogLevel::DEBUG, 'getRichSnippetObject Exit point', (array)$this);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
245
Classes/ViewHelpers/BookmarkViewHelper.php
Normal file
245
Classes/ViewHelpers/BookmarkViewHelper.php
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\ViewHelpers;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\Log\LogLevel;
|
||||||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
|
||||||
|
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||||
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||||
|
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
|
||||||
|
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
|
||||||
|
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||||
|
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class BookmarkViewHelper extends AbstractViewHelper
|
||||||
|
{
|
||||||
|
use CompileWithRenderStatic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable escaping of this node's output
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $escapeOutput = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @noinspection PhpUnnecessaryFullyQualifiedNameInspection
|
||||||
|
* @var \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
|
||||||
|
* contains a backup of the current['TSFE'] if used in BE mode
|
||||||
|
*/
|
||||||
|
protected static $tsfeBackup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @noinspection PhpFullyQualifiedNameUsageInspection
|
||||||
|
* @var \TYPO3\CMS\Core\Log\Logger $logger
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $typoScriptSetup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @noinspection PhpUnnecessaryFullyQualifiedNameInspection
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService
|
||||||
|
*/
|
||||||
|
protected $extensionHelperService;
|
||||||
|
|
||||||
|
public function initializeArguments(): void
|
||||||
|
{
|
||||||
|
$this->registerArgument('action', 'string', 'The rating action');
|
||||||
|
$this->registerArgument('ratetable', 'string', 'The rating tablename');
|
||||||
|
$this->registerArgument('ratefield', 'string', 'The rating fieldname');
|
||||||
|
$this->registerArgument('ratedobjectuid', 'integer', 'The ratingobject uid', true);
|
||||||
|
$this->registerArgument('ratingobject', 'integer', 'The ratingobject');
|
||||||
|
$this->registerArgument('display', 'string', 'The display configuration');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the ratingView
|
||||||
|
*
|
||||||
|
* @param array $arguments
|
||||||
|
* @param \Closure $renderChildrenClosure
|
||||||
|
* @param RenderingContextInterface $renderingContext
|
||||||
|
* @return mixed
|
||||||
|
* @throws \TYPO3Fluid\Fluid\Core\ViewHelper\Exception
|
||||||
|
* @noinspection PhpFullyQualifiedNameUsageInspection
|
||||||
|
*/
|
||||||
|
public static function renderStatic(
|
||||||
|
array $arguments,
|
||||||
|
\Closure $renderChildrenClosure,
|
||||||
|
RenderingContextInterface $renderingContext
|
||||||
|
) {
|
||||||
|
$typoscriptObjectPath = 'plugin.tx_thrating';
|
||||||
|
$ratedobjectuid = $arguments['ratedobjectuid'];
|
||||||
|
$action = $arguments['action'];
|
||||||
|
$ratingobject = $arguments['ratingobject'];
|
||||||
|
$ratetable = $arguments['ratetable'];
|
||||||
|
$ratefield = $arguments['ratefield'];
|
||||||
|
$display = $arguments['display'];
|
||||||
|
$extensionHelperService = static::getExtensionHelperService();
|
||||||
|
$contentObjectRenderer = static::getContentObjectRenderer();
|
||||||
|
|
||||||
|
//instantiate the logger
|
||||||
|
$logger = $extensionHelperService->getLogger(__CLASS__);
|
||||||
|
$logger->log(
|
||||||
|
LogLevel::DEBUG,
|
||||||
|
'Entry point',
|
||||||
|
[
|
||||||
|
'Viewhelper parameters' => [
|
||||||
|
'action' => $action,
|
||||||
|
'ratingobject' => $ratingobject,
|
||||||
|
'ratetable' => $ratetable,
|
||||||
|
'ratefield' => $ratefield,
|
||||||
|
'ratedobjectuid' => $ratedobjectuid,
|
||||||
|
'display' => $display, ],
|
||||||
|
'typoscript' => static::getConfigurationManager()
|
||||||
|
->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (TYPO3_MODE === 'BE') {
|
||||||
|
static::simulateFrontendEnvironment();
|
||||||
|
}
|
||||||
|
$contentObjectRenderer->start([]);
|
||||||
|
|
||||||
|
$pathSegments = GeneralUtility::trimExplode('.', $typoscriptObjectPath);
|
||||||
|
$lastSegment = array_pop($pathSegments);
|
||||||
|
$setup = static::getConfigurationManager()
|
||||||
|
->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT);
|
||||||
|
foreach ($pathSegments as $segment) {
|
||||||
|
if (!array_key_exists($segment . '.', $setup)) {
|
||||||
|
$logger->log(
|
||||||
|
LogLevel::CRITICAL,
|
||||||
|
'TypoScript object path does not exist',
|
||||||
|
[
|
||||||
|
'Typoscript object path' => htmlspecialchars($typoscriptObjectPath),
|
||||||
|
'Setup' => $setup,
|
||||||
|
'errorCode' => 1253191023, ]
|
||||||
|
);
|
||||||
|
|
||||||
|
throw new \TYPO3Fluid\Fluid\Core\ViewHelper\Exception(
|
||||||
|
'TypoScript object path "' . $typoscriptObjectPath . '" does not exist',
|
||||||
|
1549388144
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$setup = $setup[$segment . '.'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($setup[$lastSegment])) {
|
||||||
|
throw new \TYPO3Fluid\Fluid\Core\ViewHelper\Exception(
|
||||||
|
'No Content Object definition found at TypoScript object path "' . $typoscriptObjectPath . '"',
|
||||||
|
1549388123
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($action)) {
|
||||||
|
$setup[$lastSegment . '.']['action'] = $action;
|
||||||
|
$setup[$lastSegment . '.']['switchableControllerActions.']['Vote.']['1'] = $action;
|
||||||
|
}
|
||||||
|
if (!empty($ratingobject)) {
|
||||||
|
$setup[$lastSegment . '.']['settings.']['ratingobject'] = $ratingobject;
|
||||||
|
} elseif (!empty($ratetable) && !empty($ratefield)) {
|
||||||
|
$setup[$lastSegment . '.']['settings.']['ratetable'] = $ratetable;
|
||||||
|
$setup[$lastSegment . '.']['settings.']['ratefield'] = $ratefield;
|
||||||
|
} else {
|
||||||
|
$logger->log(
|
||||||
|
LogLevel::CRITICAL,
|
||||||
|
'ratingobject not specified or ratetable/ratfield not set',
|
||||||
|
['errorCode' => 1399727698]
|
||||||
|
);
|
||||||
|
throw new Exception('ratingobject not specified or ratetable/ratfield not set', 1399727698);
|
||||||
|
}
|
||||||
|
if (!empty($ratedobjectuid)) {
|
||||||
|
$setup[$lastSegment . '.']['settings.']['ratedobjectuid'] = $ratedobjectuid;
|
||||||
|
} else {
|
||||||
|
$logger->log(LogLevel::CRITICAL, 'ratedobjectuid not set', ['errorCode' => 1304624408]);
|
||||||
|
throw new Exception('ratedobjectuid not set', 1304624408);
|
||||||
|
}
|
||||||
|
if (!empty($display)) {
|
||||||
|
$setup[$lastSegment . '.']['settings.']['display'] = $display;
|
||||||
|
}
|
||||||
|
|
||||||
|
$logger->log(
|
||||||
|
LogLevel::DEBUG,
|
||||||
|
'Single contentObjectRenderer to get',
|
||||||
|
[
|
||||||
|
'contentObjectRenderer type' => $setup[$lastSegment],
|
||||||
|
'cOjb config' => $setup[$lastSegment . '.'], ]
|
||||||
|
);
|
||||||
|
|
||||||
|
$content = $contentObjectRenderer->cObjGetSingle($setup[$lastSegment], $setup[$lastSegment . '.'] ?? []);
|
||||||
|
if (TYPO3_MODE === 'BE') {
|
||||||
|
static::resetFrontendEnvironment();
|
||||||
|
}
|
||||||
|
|
||||||
|
$logger->log(LogLevel::INFO, 'Generated content', ['content' => $content]);
|
||||||
|
$logger->log(LogLevel::DEBUG, 'Exit point');
|
||||||
|
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService
|
||||||
|
*/
|
||||||
|
protected static function getExtensionHelperService(): ExtensionHelperService
|
||||||
|
{
|
||||||
|
return GeneralUtility::makeInstance(ObjectManager::class)->get(ExtensionHelperService::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return object|\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
|
||||||
|
*/
|
||||||
|
protected static function getConfigurationManager()
|
||||||
|
{
|
||||||
|
return GeneralUtility::makeInstance(ObjectManager::class)->get(ConfigurationManagerInterface::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
|
||||||
|
*/
|
||||||
|
protected static function getContentObjectRenderer(): ContentObjectRenderer
|
||||||
|
{
|
||||||
|
return GeneralUtility::makeInstance(
|
||||||
|
ContentObjectRenderer::class,
|
||||||
|
$GLOBALS['TSFE'] ?? GeneralUtility::makeInstance(TypoScriptFrontendController::class, null, 0, 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the $TSFE->cObjectDepthCounter in Backend mode
|
||||||
|
* This somewhat hacky work around is currently needed because the cObjGetSingle() function
|
||||||
|
* of \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer relies on this setting
|
||||||
|
*/
|
||||||
|
protected static function simulateFrontendEnvironment(): void
|
||||||
|
{
|
||||||
|
static::$tsfeBackup = $GLOBALS['TSFE'] ?? null;
|
||||||
|
/** @noinspection PhpFullyQualifiedNameUsageInspection */
|
||||||
|
$GLOBALS['TSFE'] = new \stdClass();
|
||||||
|
$GLOBALS['TSFE']->cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
|
||||||
|
$GLOBALS['TSFE']->cObjectDepthCounter = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets $GLOBALS['TSFE'] if it was previously changed by simulateFrontendEnvironment()
|
||||||
|
*
|
||||||
|
* @see simulateFrontendEnvironment()
|
||||||
|
*/
|
||||||
|
protected static function resetFrontendEnvironment(): void
|
||||||
|
{
|
||||||
|
$GLOBALS['TSFE'] = static::$tsfeBackup;
|
||||||
|
}
|
||||||
|
}
|
245
Classes/ViewHelpers/LikeViewHelper.php
Normal file
245
Classes/ViewHelpers/LikeViewHelper.php
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\ViewHelpers;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\Log\LogLevel;
|
||||||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
|
||||||
|
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||||
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||||
|
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
|
||||||
|
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
|
||||||
|
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||||
|
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class LikeViewHelper extends AbstractViewHelper
|
||||||
|
{
|
||||||
|
use CompileWithRenderStatic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable escaping of this node's output
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $escapeOutput = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @noinspection PhpUnnecessaryFullyQualifiedNameInspection
|
||||||
|
* @var \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
|
||||||
|
* contains a backup of the current['TSFE'] if used in BE mode
|
||||||
|
*/
|
||||||
|
protected static $tsfeBackup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @noinspection PhpFullyQualifiedNameUsageInspection
|
||||||
|
* @var \TYPO3\CMS\Core\Log\Logger $logger
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $typoScriptSetup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @noinspection PhpUnnecessaryFullyQualifiedNameInspection
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService
|
||||||
|
*/
|
||||||
|
protected $extensionHelperService;
|
||||||
|
|
||||||
|
public function initializeArguments(): void
|
||||||
|
{
|
||||||
|
$this->registerArgument('action', 'string', 'The rating action');
|
||||||
|
$this->registerArgument('ratetable', 'string', 'The rating tablename');
|
||||||
|
$this->registerArgument('ratefield', 'string', 'The rating fieldname');
|
||||||
|
$this->registerArgument('ratedobjectuid', 'integer', 'The ratingobject uid', true);
|
||||||
|
$this->registerArgument('ratingobject', 'integer', 'The ratingobject');
|
||||||
|
$this->registerArgument('display', 'string', 'The display configuration');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the ratingView
|
||||||
|
*
|
||||||
|
* @param array $arguments
|
||||||
|
* @param \Closure $renderChildrenClosure
|
||||||
|
* @param RenderingContextInterface $renderingContext
|
||||||
|
* @return mixed
|
||||||
|
* @throws \TYPO3Fluid\Fluid\Core\ViewHelper\Exception
|
||||||
|
* @noinspection PhpFullyQualifiedNameUsageInspection
|
||||||
|
*/
|
||||||
|
public static function renderStatic(
|
||||||
|
array $arguments,
|
||||||
|
\Closure $renderChildrenClosure,
|
||||||
|
RenderingContextInterface $renderingContext
|
||||||
|
) {
|
||||||
|
$typoscriptObjectPath = 'plugin.tx_thrating';
|
||||||
|
$ratedobjectuid = $arguments['ratedobjectuid'];
|
||||||
|
$action = $arguments['action'];
|
||||||
|
$ratingobject = $arguments['ratingobject'];
|
||||||
|
$ratetable = $arguments['ratetable'];
|
||||||
|
$ratefield = $arguments['ratefield'];
|
||||||
|
$display = $arguments['display'];
|
||||||
|
$extensionHelperService = static::getExtensionHelperService();
|
||||||
|
$contentObjectRenderer = static::getContentObjectRenderer();
|
||||||
|
|
||||||
|
//instantiate the logger
|
||||||
|
$logger = $extensionHelperService->getLogger(__CLASS__);
|
||||||
|
$logger->log(
|
||||||
|
LogLevel::DEBUG,
|
||||||
|
'Entry point',
|
||||||
|
[
|
||||||
|
'Viewhelper parameters' => [
|
||||||
|
'action' => $action,
|
||||||
|
'ratingobject' => $ratingobject,
|
||||||
|
'ratetable' => $ratetable,
|
||||||
|
'ratefield' => $ratefield,
|
||||||
|
'ratedobjectuid' => $ratedobjectuid,
|
||||||
|
'display' => $display, ],
|
||||||
|
'typoscript' => static::getConfigurationManager()
|
||||||
|
->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (TYPO3_MODE === 'BE') {
|
||||||
|
static::simulateFrontendEnvironment();
|
||||||
|
}
|
||||||
|
$contentObjectRenderer->start([]);
|
||||||
|
|
||||||
|
$pathSegments = GeneralUtility::trimExplode('.', $typoscriptObjectPath);
|
||||||
|
$lastSegment = array_pop($pathSegments);
|
||||||
|
$setup = static::getConfigurationManager()
|
||||||
|
->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT);
|
||||||
|
foreach ($pathSegments as $segment) {
|
||||||
|
if (!array_key_exists($segment . '.', $setup)) {
|
||||||
|
$logger->log(
|
||||||
|
LogLevel::CRITICAL,
|
||||||
|
'TypoScript object path does not exist',
|
||||||
|
[
|
||||||
|
'Typoscript object path' => htmlspecialchars($typoscriptObjectPath),
|
||||||
|
'Setup' => $setup,
|
||||||
|
'errorCode' => 1253191023, ]
|
||||||
|
);
|
||||||
|
|
||||||
|
throw new \TYPO3Fluid\Fluid\Core\ViewHelper\Exception(
|
||||||
|
'TypoScript object path "' . $typoscriptObjectPath . '" does not exist',
|
||||||
|
1549388144
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$setup = $setup[$segment . '.'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($setup[$lastSegment])) {
|
||||||
|
throw new \TYPO3Fluid\Fluid\Core\ViewHelper\Exception(
|
||||||
|
'No Content Object definition found at TypoScript object path "' . $typoscriptObjectPath . '"',
|
||||||
|
1549388123
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($action)) {
|
||||||
|
$setup[$lastSegment . '.']['action'] = $action;
|
||||||
|
$setup[$lastSegment . '.']['switchableControllerActions.']['Vote.']['1'] = $action;
|
||||||
|
}
|
||||||
|
if (!empty($ratingobject)) {
|
||||||
|
$setup[$lastSegment . '.']['settings.']['ratingobject'] = $ratingobject;
|
||||||
|
} elseif (!empty($ratetable) && !empty($ratefield)) {
|
||||||
|
$setup[$lastSegment . '.']['settings.']['ratetable'] = $ratetable;
|
||||||
|
$setup[$lastSegment . '.']['settings.']['ratefield'] = $ratefield;
|
||||||
|
} else {
|
||||||
|
$logger->log(
|
||||||
|
LogLevel::CRITICAL,
|
||||||
|
'ratingobject not specified or ratetable/ratfield not set',
|
||||||
|
['errorCode' => 1399727698]
|
||||||
|
);
|
||||||
|
throw new Exception('ratingobject not specified or ratetable/ratfield not set', 1399727698);
|
||||||
|
}
|
||||||
|
if (!empty($ratedobjectuid)) {
|
||||||
|
$setup[$lastSegment . '.']['settings.']['ratedobjectuid'] = $ratedobjectuid;
|
||||||
|
} else {
|
||||||
|
$logger->log(LogLevel::CRITICAL, 'ratedobjectuid not set', ['errorCode' => 1304624408]);
|
||||||
|
throw new Exception('ratedobjectuid not set', 1304624408);
|
||||||
|
}
|
||||||
|
if (!empty($display)) {
|
||||||
|
$setup[$lastSegment . '.']['settings.']['display'] = $display;
|
||||||
|
}
|
||||||
|
|
||||||
|
$logger->log(
|
||||||
|
LogLevel::DEBUG,
|
||||||
|
'Single contentObjectRenderer to get',
|
||||||
|
[
|
||||||
|
'contentObjectRenderer type' => $setup[$lastSegment],
|
||||||
|
'cOjb config' => $setup[$lastSegment . '.'], ]
|
||||||
|
);
|
||||||
|
|
||||||
|
$content = $contentObjectRenderer->cObjGetSingle($setup[$lastSegment], $setup[$lastSegment . '.'] ?? []);
|
||||||
|
if (TYPO3_MODE === 'BE') {
|
||||||
|
static::resetFrontendEnvironment();
|
||||||
|
}
|
||||||
|
|
||||||
|
$logger->log(LogLevel::INFO, 'Generated content', ['content' => $content]);
|
||||||
|
$logger->log(LogLevel::DEBUG, 'Exit point');
|
||||||
|
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService
|
||||||
|
*/
|
||||||
|
protected static function getExtensionHelperService(): ExtensionHelperService
|
||||||
|
{
|
||||||
|
return GeneralUtility::makeInstance(ObjectManager::class)->get(ExtensionHelperService::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return object|\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
|
||||||
|
*/
|
||||||
|
protected static function getConfigurationManager()
|
||||||
|
{
|
||||||
|
return GeneralUtility::makeInstance(ObjectManager::class)->get(ConfigurationManagerInterface::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
|
||||||
|
*/
|
||||||
|
protected static function getContentObjectRenderer(): ContentObjectRenderer
|
||||||
|
{
|
||||||
|
return GeneralUtility::makeInstance(
|
||||||
|
ContentObjectRenderer::class,
|
||||||
|
$GLOBALS['TSFE'] ?? GeneralUtility::makeInstance(TypoScriptFrontendController::class, null, 0, 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the $TSFE->cObjectDepthCounter in Backend mode
|
||||||
|
* This somewhat hacky work around is currently needed because the cObjGetSingle() function
|
||||||
|
* of \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer relies on this setting
|
||||||
|
*/
|
||||||
|
protected static function simulateFrontendEnvironment(): void
|
||||||
|
{
|
||||||
|
static::$tsfeBackup = $GLOBALS['TSFE'] ?? null;
|
||||||
|
/** @noinspection PhpFullyQualifiedNameUsageInspection */
|
||||||
|
$GLOBALS['TSFE'] = new \stdClass();
|
||||||
|
$GLOBALS['TSFE']->cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
|
||||||
|
$GLOBALS['TSFE']->cObjectDepthCounter = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets $GLOBALS['TSFE'] if it was previously changed by simulateFrontendEnvironment()
|
||||||
|
*
|
||||||
|
* @see simulateFrontendEnvironment()
|
||||||
|
*/
|
||||||
|
protected static function resetFrontendEnvironment(): void
|
||||||
|
{
|
||||||
|
$GLOBALS['TSFE'] = static::$tsfeBackup;
|
||||||
|
}
|
||||||
|
}
|
257
Classes/ViewHelpers/RatingViewHelper.php
Normal file
257
Classes/ViewHelpers/RatingViewHelper.php
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the package thucke/th-rating.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please read the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\ViewHelpers;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\Log\LogLevel;
|
||||||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
|
||||||
|
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||||
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||||
|
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
|
||||||
|
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
|
||||||
|
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||||
|
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Rating Viewhelper
|
||||||
|
*
|
||||||
|
* Renders the rating view based upon plugin.tx_thrating
|
||||||
|
* Only the argument ratedobjectuid is required.
|
||||||
|
* Others could be used to configure the output
|
||||||
|
*
|
||||||
|
* = Example =
|
||||||
|
*
|
||||||
|
* <code title="Render rating view">
|
||||||
|
* <thr:rating ratetable="some_tablename" ratefield="one_field_of_the_table" ratedobjectuid="UID integer" ></thr:rating>
|
||||||
|
* </code>
|
||||||
|
* <output>
|
||||||
|
* rendered rating
|
||||||
|
* </output>
|
||||||
|
*/
|
||||||
|
class RatingViewHelper extends AbstractViewHelper
|
||||||
|
{
|
||||||
|
use CompileWithRenderStatic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable escaping of this node's output
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $escapeOutput = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @noinspection PhpUnnecessaryFullyQualifiedNameInspection
|
||||||
|
* @var \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
|
||||||
|
* contains a backup of the current['TSFE'] if used in BE mode
|
||||||
|
*/
|
||||||
|
protected static $tsfeBackup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @noinspection PhpFullyQualifiedNameUsageInspection
|
||||||
|
* @var \TYPO3\CMS\Core\Log\Logger $logger
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $typoScriptSetup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @noinspection PhpUnnecessaryFullyQualifiedNameInspection
|
||||||
|
* @var \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService
|
||||||
|
*/
|
||||||
|
protected $extensionHelperService;
|
||||||
|
|
||||||
|
public function initializeArguments(): void
|
||||||
|
{
|
||||||
|
$this->registerArgument('action', 'string', 'The rating action');
|
||||||
|
$this->registerArgument('ratetable', 'string', 'The rating tablename');
|
||||||
|
$this->registerArgument('ratefield', 'string', 'The rating fieldname');
|
||||||
|
$this->registerArgument('ratedobjectuid', 'integer', 'The ratingobject uid', true);
|
||||||
|
$this->registerArgument('ratingobject', 'integer', 'The ratingobject');
|
||||||
|
$this->registerArgument('display', 'string', 'The display configuration');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the ratingView
|
||||||
|
*
|
||||||
|
* @param array $arguments
|
||||||
|
* @param \Closure $renderChildrenClosure
|
||||||
|
* @param RenderingContextInterface $renderingContext
|
||||||
|
* @return mixed
|
||||||
|
* @throws \TYPO3Fluid\Fluid\Core\ViewHelper\Exception
|
||||||
|
* @noinspection PhpFullyQualifiedNameUsageInspection
|
||||||
|
*/
|
||||||
|
public static function renderStatic(
|
||||||
|
array $arguments,
|
||||||
|
\Closure $renderChildrenClosure,
|
||||||
|
RenderingContextInterface $renderingContext
|
||||||
|
) {
|
||||||
|
$typoscriptObjectPath = 'plugin.tx_thrating';
|
||||||
|
$ratedobjectuid = $arguments['ratedobjectuid'];
|
||||||
|
$action = $arguments['action'];
|
||||||
|
$ratingobject = $arguments['ratingobject'];
|
||||||
|
$ratetable = $arguments['ratetable'];
|
||||||
|
$ratefield = $arguments['ratefield'];
|
||||||
|
$display = $arguments['display'];
|
||||||
|
$extensionHelperService = static::getExtensionHelperService();
|
||||||
|
$contentObjectRenderer = static::getContentObjectRenderer();
|
||||||
|
|
||||||
|
//instantiate the logger
|
||||||
|
$logger = $extensionHelperService->getLogger(__CLASS__);
|
||||||
|
$logger->log(
|
||||||
|
LogLevel::DEBUG,
|
||||||
|
'Entry point',
|
||||||
|
[
|
||||||
|
'Viewhelper parameters' => [
|
||||||
|
'action' => $action,
|
||||||
|
'ratingobject' => $ratingobject,
|
||||||
|
'ratetable' => $ratetable,
|
||||||
|
'ratefield' => $ratefield,
|
||||||
|
'ratedobjectuid' => $ratedobjectuid,
|
||||||
|
'display' => $display, ],
|
||||||
|
'typoscript' => static::getConfigurationManager()
|
||||||
|
->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (TYPO3_MODE === 'BE') {
|
||||||
|
static::simulateFrontendEnvironment();
|
||||||
|
}
|
||||||
|
$contentObjectRenderer->start([]);
|
||||||
|
|
||||||
|
$pathSegments = GeneralUtility::trimExplode('.', $typoscriptObjectPath);
|
||||||
|
$lastSegment = array_pop($pathSegments);
|
||||||
|
$setup = static::getConfigurationManager()
|
||||||
|
->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT);
|
||||||
|
foreach ($pathSegments as $segment) {
|
||||||
|
if (!array_key_exists($segment . '.', $setup)) {
|
||||||
|
$logger->log(
|
||||||
|
LogLevel::CRITICAL,
|
||||||
|
'TypoScript object path does not exist',
|
||||||
|
[
|
||||||
|
'Typoscript object path' => htmlspecialchars($typoscriptObjectPath),
|
||||||
|
'Setup' => $setup,
|
||||||
|
'errorCode' => 1253191023, ]
|
||||||
|
);
|
||||||
|
|
||||||
|
throw new \TYPO3Fluid\Fluid\Core\ViewHelper\Exception(
|
||||||
|
'TypoScript object path "' . $typoscriptObjectPath . '" does not exist',
|
||||||
|
1549388144
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$setup = $setup[$segment . '.'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($setup[$lastSegment])) {
|
||||||
|
throw new \TYPO3Fluid\Fluid\Core\ViewHelper\Exception(
|
||||||
|
'No Content Object definition found at TypoScript object path "' . $typoscriptObjectPath . '"',
|
||||||
|
1549388123
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($action)) {
|
||||||
|
$setup[$lastSegment . '.']['action'] = $action;
|
||||||
|
$setup[$lastSegment . '.']['switchableControllerActions.']['Vote.']['1'] = $action;
|
||||||
|
}
|
||||||
|
if (!empty($ratingobject)) {
|
||||||
|
$setup[$lastSegment . '.']['settings.']['ratingobject'] = $ratingobject;
|
||||||
|
} elseif (!empty($ratetable) && !empty($ratefield)) {
|
||||||
|
$setup[$lastSegment . '.']['settings.']['ratetable'] = $ratetable;
|
||||||
|
$setup[$lastSegment . '.']['settings.']['ratefield'] = $ratefield;
|
||||||
|
} else {
|
||||||
|
$logger->log(
|
||||||
|
LogLevel::CRITICAL,
|
||||||
|
'ratingobject not specified or ratetable/ratfield not set',
|
||||||
|
['errorCode' => 1399727698]
|
||||||
|
);
|
||||||
|
throw new Exception('ratingobject not specified or ratetable/ratfield not set', 1399727698);
|
||||||
|
}
|
||||||
|
if (!empty($ratedobjectuid)) {
|
||||||
|
$setup[$lastSegment . '.']['settings.']['ratedobjectuid'] = $ratedobjectuid;
|
||||||
|
} else {
|
||||||
|
$logger->log(LogLevel::CRITICAL, 'ratedobjectuid not set', ['errorCode' => 1304624408]);
|
||||||
|
throw new Exception('ratedobjectuid not set', 1304624408);
|
||||||
|
}
|
||||||
|
if (!empty($display)) {
|
||||||
|
$setup[$lastSegment . '.']['settings.']['display'] = $display;
|
||||||
|
}
|
||||||
|
|
||||||
|
$logger->log(
|
||||||
|
LogLevel::DEBUG,
|
||||||
|
'Single contentObjectRenderer to get',
|
||||||
|
[
|
||||||
|
'contentObjectRenderer type' => $setup[$lastSegment],
|
||||||
|
'cOjb config' => $setup[$lastSegment . '.'], ]
|
||||||
|
);
|
||||||
|
|
||||||
|
$content = $contentObjectRenderer->cObjGetSingle($setup[$lastSegment], $setup[$lastSegment . '.'] ?? []);
|
||||||
|
if (TYPO3_MODE === 'BE') {
|
||||||
|
static::resetFrontendEnvironment();
|
||||||
|
}
|
||||||
|
|
||||||
|
$logger->log(LogLevel::INFO, 'Generated content', ['content' => $content]);
|
||||||
|
$logger->log(LogLevel::DEBUG, 'Exit point');
|
||||||
|
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService
|
||||||
|
*/
|
||||||
|
protected static function getExtensionHelperService(): ExtensionHelperService
|
||||||
|
{
|
||||||
|
return GeneralUtility::makeInstance(ObjectManager::class)->get(ExtensionHelperService::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return object|\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
|
||||||
|
*/
|
||||||
|
protected static function getConfigurationManager()
|
||||||
|
{
|
||||||
|
return GeneralUtility::makeInstance(ObjectManager::class)->get(ConfigurationManagerInterface::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
|
||||||
|
*/
|
||||||
|
protected static function getContentObjectRenderer(): ContentObjectRenderer
|
||||||
|
{
|
||||||
|
return GeneralUtility::makeInstance(
|
||||||
|
ContentObjectRenderer::class,
|
||||||
|
$GLOBALS['TSFE'] ?? GeneralUtility::makeInstance(TypoScriptFrontendController::class, null, 0, 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the $TSFE->cObjectDepthCounter in Backend mode
|
||||||
|
* This somewhat hacky work around is currently needed because the cObjGetSingle() function
|
||||||
|
* of \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer relies on this setting
|
||||||
|
*/
|
||||||
|
protected static function simulateFrontendEnvironment(): void
|
||||||
|
{
|
||||||
|
static::$tsfeBackup = $GLOBALS['TSFE'] ?? null;
|
||||||
|
/** @noinspection PhpFullyQualifiedNameUsageInspection */
|
||||||
|
$GLOBALS['TSFE'] = new \stdClass();
|
||||||
|
$GLOBALS['TSFE']->cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
|
||||||
|
$GLOBALS['TSFE']->cObjectDepthCounter = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets $GLOBALS['TSFE'] if it was previously changed by simulateFrontendEnvironment()
|
||||||
|
*
|
||||||
|
* @see simulateFrontendEnvironment()
|
||||||
|
*/
|
||||||
|
protected static function resetFrontendEnvironment(): void
|
||||||
|
{
|
||||||
|
$GLOBALS['TSFE'] = static::$tsfeBackup;
|
||||||
|
}
|
||||||
|
}
|
38
Classes/Widgets/Provider/TopLikesDataProvider.php
Normal file
38
Classes/Widgets/Provider/TopLikesDataProvider.php
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Widgets\Provider;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\Database\Connection;
|
||||||
|
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||||
|
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
|
||||||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use TYPO3\CMS\Dashboard\Widgets\ListDataProviderInterface;
|
||||||
|
|
||||||
|
class TopLikesDataProvider implements ListDataProviderInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getItems(): array
|
||||||
|
{
|
||||||
|
/** @var QueryBuilder $queryBuilder */
|
||||||
|
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('be_users');
|
||||||
|
return $queryBuilder
|
||||||
|
->count('*')
|
||||||
|
->from('be_users')
|
||||||
|
->where(
|
||||||
|
$queryBuilder->expr()->eq(
|
||||||
|
'admin',
|
||||||
|
$queryBuilder->createNamedParameter(0, Connection::PARAM_INT)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
}
|
70
Classes/Widgets/TopLikesWidget.php
Normal file
70
Classes/Widgets/TopLikesWidget.php
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace WapplerSystems\BookmarksLikesRatings\Widgets;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Dashboard\Widgets\ButtonProviderInterface;
|
||||||
|
use TYPO3\CMS\Dashboard\Widgets\ListDataProviderInterface;
|
||||||
|
use TYPO3\CMS\Dashboard\Widgets\WidgetConfigurationInterface;
|
||||||
|
use TYPO3\CMS\Dashboard\Widgets\WidgetInterface;
|
||||||
|
use TYPO3\CMS\Fluid\View\StandaloneView;
|
||||||
|
use WapplerSystems\BookmarksLikesRatings\Widgets\Provider\TopLikesDataProvider;
|
||||||
|
|
||||||
|
class TopLikesWidget implements WidgetInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var WidgetConfigurationInterface
|
||||||
|
*/
|
||||||
|
private $configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var StandaloneView
|
||||||
|
*/
|
||||||
|
private $view;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $options;
|
||||||
|
/**
|
||||||
|
* @var ButtonProviderInterface|null
|
||||||
|
*/
|
||||||
|
private $buttonProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var TopLikesDataProvider
|
||||||
|
*/
|
||||||
|
private $dataProvider;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
WidgetConfigurationInterface $configuration,
|
||||||
|
TopLikesDataProvider $dataProvider,
|
||||||
|
StandaloneView $view,
|
||||||
|
$buttonProvider = null,
|
||||||
|
array $options = []
|
||||||
|
)
|
||||||
|
{
|
||||||
|
$this->configuration = $configuration;
|
||||||
|
$this->view = $view;
|
||||||
|
$this->options = $options;
|
||||||
|
$this->buttonProvider = $buttonProvider;
|
||||||
|
$this->dataProvider = $dataProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderWidgetContent(): string
|
||||||
|
{
|
||||||
|
$this->view->setTemplate('Widget/ListWidget');
|
||||||
|
$this->view->assignMultiple([
|
||||||
|
'items' => $this->getItems(),
|
||||||
|
'options' => $this->options,
|
||||||
|
'button' => $this->buttonProvider,
|
||||||
|
'configuration' => $this->configuration,
|
||||||
|
]);
|
||||||
|
return $this->view->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getItems(): array
|
||||||
|
{
|
||||||
|
return $this->dataProvider->getTopLikes();
|
||||||
|
}
|
||||||
|
}
|
7
Configuration/Backend/DashboardWidgetGroups.php
Normal file
7
Configuration/Backend/DashboardWidgetGroups.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'ratings' => [
|
||||||
|
'title' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:widget_group.ratings',
|
||||||
|
],
|
||||||
|
];
|
16
Configuration/Backend/DashboardWidgets.yaml
Normal file
16
Configuration/Backend/DashboardWidgets.yaml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
services:
|
||||||
|
dashboard.widget.bookmarkslikesratingsToplikes:
|
||||||
|
class: 'WapplerSystems\BookmarksLikesRatings\Widgets\TopLikesWidget'
|
||||||
|
arguments:
|
||||||
|
$view: '@dashboard.views.widget'
|
||||||
|
$dataProvider: '@WapplerSystems\BookmarksLikesRatings\Widgets\Provider\TopLikesDataProvider'
|
||||||
|
tags:
|
||||||
|
- name: dashboard.widget
|
||||||
|
identifier: 'bookmarks_likes_ratings'
|
||||||
|
groupNames: 'ratings'
|
||||||
|
title: 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:widgets.bookmarks_likes_ratings.topLikes.title'
|
||||||
|
description: 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:widgets.bookmarks_likes_ratings.topLikes.description'
|
||||||
|
iconIdentifier: 'content-widget-ratings'
|
||||||
|
height: 'large'
|
||||||
|
width: 'medium'
|
@ -13,18 +13,18 @@
|
|||||||
<el type="array">
|
<el type="array">
|
||||||
<settings.listType>
|
<settings.listType>
|
||||||
<TCEforms>
|
<TCEforms>
|
||||||
<label>LLL:EXT:ws_bookmark_pages/Resources/Private/Language/locallang.xlf:ff.listType</label>
|
<label>LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:ff.listType</label>
|
||||||
<config type="array">
|
<config type="array">
|
||||||
<type>select</type>
|
<type>select</type>
|
||||||
<renderType>selectSingle</renderType>
|
<renderType>selectSingle</renderType>
|
||||||
<default>default</default>
|
<default>default</default>
|
||||||
<items type="array">
|
<items type="array">
|
||||||
<numIndex index="0" type="array">
|
<numIndex index="0" type="array">
|
||||||
<numIndex index="0">LLL:EXT:ws_bookmark_pages/Resources/Private/Language/locallang.xlf:default</numIndex>
|
<numIndex index="0">LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:default</numIndex>
|
||||||
<numIndex index="1">default</numIndex>
|
<numIndex index="1">default</numIndex>
|
||||||
</numIndex>
|
</numIndex>
|
||||||
<numIndex index="1" type="array">
|
<numIndex index="1" type="array">
|
||||||
<numIndex index="0">LLL:EXT:ws_bookmark_pages/Resources/Private/Language/locallang.xlf:alternative</numIndex>
|
<numIndex index="0">LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:alternative</numIndex>
|
||||||
<numIndex index="1">alternative</numIndex>
|
<numIndex index="1">alternative</numIndex>
|
||||||
</numIndex>
|
</numIndex>
|
||||||
</items>
|
</items>
|
||||||
@ -33,14 +33,14 @@
|
|||||||
</settings.listType>
|
</settings.listType>
|
||||||
<settings.isComplementary>
|
<settings.isComplementary>
|
||||||
<TCEforms>
|
<TCEforms>
|
||||||
<label>LLL:EXT:ws_bookmark_pages/Resources/Private/Language/locallang.xlf:ff.isComplementary</label>
|
<label>LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:ff.isComplementary</label>
|
||||||
<description>LLL:EXT:ws_bookmark_pages/Resources/Private/Language/locallang.xlf:ff.isComplementary.description</description>
|
<description>LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:ff.isComplementary.description</description>
|
||||||
<config>
|
<config>
|
||||||
<type>check</type>
|
<type>check</type>
|
||||||
<default>0</default>
|
<default>0</default>
|
||||||
<items>
|
<items>
|
||||||
<numIndex index="0" type="array">
|
<numIndex index="0" type="array">
|
||||||
<numIndex index="0">LLL:EXT:ws_bookmark_pages/Resources/Private/Language/locallang.xlf:yes</numIndex>
|
<numIndex index="0">LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:yes</numIndex>
|
||||||
<numIndex index="1"></numIndex>
|
<numIndex index="1"></numIndex>
|
||||||
</numIndex>
|
</numIndex>
|
||||||
</items>
|
</items>
|
||||||
|
12
Configuration/Services.yaml
Normal file
12
Configuration/Services.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
imports:
|
||||||
|
- { resource: Backend/DashboardWidgets.yaml }
|
||||||
|
|
||||||
|
services:
|
||||||
|
_defaults:
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
public: false
|
||||||
|
|
||||||
|
WapplerSystems\BookmarksLikesRatings\:
|
||||||
|
resource: '../Classes/*'
|
||||||
|
|
@ -12,4 +12,4 @@ defined('TYPO3') || die('Access denied.');
|
|||||||
/**
|
/**
|
||||||
* add TypoScript to template record
|
* add TypoScript to template record
|
||||||
*/
|
*/
|
||||||
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile('ws_bookmark_pages', 'Configuration/TypoScript/', 'Bookmark Pages');
|
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile('bookmarks_likes_ratings', 'Configuration/TypoScript/', 'Bookmark Pages');
|
||||||
|
@ -10,36 +10,19 @@
|
|||||||
defined('TYPO3') || die('Access denied.');
|
defined('TYPO3') || die('Access denied.');
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
$version = \TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version();
|
|
||||||
$version = \TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionNumberToInteger($version);
|
|
||||||
/**
|
|
||||||
* Register Plugin
|
|
||||||
*/
|
|
||||||
if ($version < 10000000) {
|
|
||||||
// For TYPO3 < V10
|
|
||||||
// @extensionScannerIgnoreLine
|
|
||||||
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
|
|
||||||
'WapplerSystems.BookmarkPages',
|
|
||||||
'Bookmarks',
|
|
||||||
'Bookmark Pages'
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
|
|
||||||
'BookmarkPages',
|
|
||||||
'Bookmarks',
|
|
||||||
'Bookmark Pages'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
|
||||||
* Add flexForm
|
'BookmarksLikesRatings',
|
||||||
*/
|
'Bookmarks',
|
||||||
$pluginSignature = 'bookmarkpages_bookmarks';
|
'Bookmark Pages'
|
||||||
$GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist'][$pluginSignature] = 'pi_flexform';
|
|
||||||
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue(
|
|
||||||
$pluginSignature,
|
|
||||||
'FILE:EXT:ws_bookmark_pages/Configuration/FlexForms/Bookmarks.xml'
|
|
||||||
);
|
);
|
||||||
|
|
||||||
$GLOBALS['TCA']['tt_content']['types']['list']['subtypes_excludelist'][$pluginSignature] = 'recursive,select_key,pages';
|
|
||||||
|
$GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist']['bookmarkpages_bookmarks'] = 'pi_flexform';
|
||||||
|
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue(
|
||||||
|
'bookmarkpages_bookmarks',
|
||||||
|
'FILE:EXT:bookmarks_likes_ratings/Configuration/FlexForms/Bookmarks.xml'
|
||||||
|
);
|
||||||
|
|
||||||
|
$GLOBALS['TCA']['tt_content']['types']['list']['subtypes_excludelist']['bookmarkpages_bookmarks'] = 'recursive,select_key,pages';
|
||||||
})();
|
})();
|
||||||
|
@ -0,0 +1,100 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'ctrl' => [
|
||||||
|
'title' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.rating.title',
|
||||||
|
'label' => 'uid',
|
||||||
|
'label_alt' => 'ratingobject,ratedobjectuid,votes',
|
||||||
|
'label_userFunc' => 'Thucke\\ThRating\\Userfuncs\\Tca->getRatingRecordTitle',
|
||||||
|
'tstamp' => 'tstamp',
|
||||||
|
'crdate' => 'crdate',
|
||||||
|
'cruser_id' => 'cruser_id',
|
||||||
|
'delete' => 'deleted',
|
||||||
|
'adminOnly' => true,
|
||||||
|
'hideTable' => true,
|
||||||
|
'editlock' => 'ratedobjectuid',
|
||||||
|
'enablecolumns' => [
|
||||||
|
'disabled' => 'hidden',
|
||||||
|
],
|
||||||
|
'iconfile' => 'EXT:bookmarks_likes_ratings/Resources/Public/Icons/tx_bookmarkslikesratings_domain_model_rating.gif',
|
||||||
|
],
|
||||||
|
'interface' => [
|
||||||
|
'showRecordFieldList' => 'hidden, ratedobjectuid, votes',
|
||||||
|
],
|
||||||
|
'columns' => [
|
||||||
|
'pid' => [
|
||||||
|
'exclude' => 1,
|
||||||
|
'config' => [
|
||||||
|
'type' => 'none',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'hidden' => [
|
||||||
|
'exclude' => 1,
|
||||||
|
'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.hidden',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'check',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'ratingobject' => [
|
||||||
|
'exclude' => 1,
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.rating.ratingobject',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'select',
|
||||||
|
'renderType' => 'selectSingle',
|
||||||
|
'foreign_table' => 'tx_bookmarkslikesratings_domain_model_ratingobject',
|
||||||
|
'maxitems' => 1,
|
||||||
|
'minitems' => 1,
|
||||||
|
'disableNoMatchingValueElement' => 1,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'ratedobjectuid' => [
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.rating.ratedobjectuid',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'input',
|
||||||
|
'size' => '8',
|
||||||
|
'max' => '12',
|
||||||
|
'eval' => 'int',
|
||||||
|
'default' => 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'votes' => [
|
||||||
|
'exclude' => 1,
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.rating.votes',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'inline',
|
||||||
|
'foreign_table' => 'tx_bookmarkslikesratings_domain_model_vote',
|
||||||
|
'foreign_field' => 'rating',
|
||||||
|
'foreign_default_sortby' => 'uid',
|
||||||
|
'appearance' => [
|
||||||
|
'levelLinksPosition' => 'bottom',
|
||||||
|
'collapseAll' => 1,
|
||||||
|
'expandSingle' => 1,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'currentrates' => [
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.rating.currentrates',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'none',
|
||||||
|
'size' => '30',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'uid' => [
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.rating.uid',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'none'
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'types' => [
|
||||||
|
'1' => [
|
||||||
|
'showitem' => 'hidden, ratedobjectuid, votes'
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'palettes' => [
|
||||||
|
'1' => [
|
||||||
|
'showitem' => ''
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
@ -0,0 +1,111 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'ctrl' => [
|
||||||
|
'title' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.ratingobject.title',
|
||||||
|
'label' => 'uid',
|
||||||
|
'label_alt' => 'ratetable,ratefield',
|
||||||
|
'label_userFunc' => 'Thucke\\ThRating\\Userfuncs\\Tca->getRatingObjectRecordTitle',
|
||||||
|
'tstamp' => 'tstamp',
|
||||||
|
'crdate' => 'crdate',
|
||||||
|
'cruser_id' => 'cruser_id',
|
||||||
|
'delete' => 'deleted',
|
||||||
|
'enablecolumns' => [
|
||||||
|
'disabled' => 'hidden',
|
||||||
|
],
|
||||||
|
'iconfile' => 'EXT:bookmarks_likes_ratings/Resources/Public/Icons/tx_bookmarkslikesratings_domain_model_ratingobject.gif',
|
||||||
|
],
|
||||||
|
'interface' => [
|
||||||
|
'showRecordFieldList' => 'hidden, ratetable, ratefield',
|
||||||
|
],
|
||||||
|
'columns' => [
|
||||||
|
'pid' => [
|
||||||
|
'exclude' => 1,
|
||||||
|
'config' => [
|
||||||
|
'type' => 'none',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'hidden' => [
|
||||||
|
'exclude' => 1,
|
||||||
|
'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.hidden',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'check',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'ratetable' => [
|
||||||
|
'exclude' => 0,
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.ratingobject.ratetable',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'input',
|
||||||
|
'size' => 20,
|
||||||
|
'eval' => 'trim,required',
|
||||||
|
'max' => 64,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'ratefield' => [
|
||||||
|
'exclude' => 0,
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.ratingobject.ratefield',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'input',
|
||||||
|
'size' => 20,
|
||||||
|
'eval' => 'trim,required',
|
||||||
|
'max' => 64,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'uid' => [
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.ratingobject.uid',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'none'
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'stepconfs' => [
|
||||||
|
'exclude' => 1,
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.ratingobject.stepconfs',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'inline',
|
||||||
|
'foreign_table' => 'tx_bookmarkslikesratings_domain_model_stepconf',
|
||||||
|
'foreign_field' => 'ratingobject',
|
||||||
|
'foreign_default_sortby' => 'steporder',
|
||||||
|
'appearance' => [
|
||||||
|
'levelLinksPosition' => 'bottom',
|
||||||
|
'collapseAll' => true,
|
||||||
|
'expandSingle' => true,
|
||||||
|
'newRecordLinkAddTitle' => true,
|
||||||
|
//'newRecordLinkPosition' => 'both',
|
||||||
|
//'showSynchronizationLink' => true,
|
||||||
|
//'showAllLocalizationLink' => true,
|
||||||
|
//'showPossibleLocalizationRecords' => 1,
|
||||||
|
//'showRemovedLocalizationRecords' => 1,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'ratings' => [
|
||||||
|
'exclude' => 1,
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.ratingobject.ratings',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'inline',
|
||||||
|
'foreign_table' => 'tx_bookmarkslikesratings_domain_model_rating',
|
||||||
|
'foreign_field' => 'ratingobject',
|
||||||
|
'foreign_default_sortby' => 'uid',
|
||||||
|
'appearance' => [
|
||||||
|
'levelLinksPosition' => 'bottom',
|
||||||
|
'collapseAll' => 1,
|
||||||
|
'expandSingle' => 1,
|
||||||
|
'newRecordLinkAddTitle' => 1,
|
||||||
|
'newRecordLinkPosition' => 'both',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'types' => [
|
||||||
|
'1' => [
|
||||||
|
'showitem' => 'hidden, ratetable, ratefield, stepconfs, ratings'
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'palettes' => [
|
||||||
|
'1' => [
|
||||||
|
'showitem' => ''
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
@ -0,0 +1,142 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'ctrl' => [
|
||||||
|
'title' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.stepconf.title',
|
||||||
|
'label' => 'uid',
|
||||||
|
'label_alt' => 'ratingobject,steporder',
|
||||||
|
'label_userFunc' => 'Thucke\\ThRating\\Userfuncs\\Tca->getStepconfRecordTitle',
|
||||||
|
'tstamp' => 'tstamp',
|
||||||
|
'crdate' => 'crdate',
|
||||||
|
'cruser_id' => 'cruser_id',
|
||||||
|
'delete' => 'deleted',
|
||||||
|
'adminOnly' => true,
|
||||||
|
'hideTable' => true,
|
||||||
|
'editlock' => 'steporder,stepweight',
|
||||||
|
'dividers2tabs' => true,
|
||||||
|
'enablecolumns' => [
|
||||||
|
'disabled' => 'hidden'
|
||||||
|
],
|
||||||
|
'iconfile' => 'EXT:bookmarks_likes_ratings/Resources/Public/Icons/tx_bookmarkslikesratings_domain_model_stepconf.gif',
|
||||||
|
],
|
||||||
|
'interface' => [
|
||||||
|
'showRecordFieldList' => 'hidden, ratingobject, steporder, stepweight, stepname',
|
||||||
|
],
|
||||||
|
'columns' => [
|
||||||
|
'pid' => [
|
||||||
|
'exclude' => 1,
|
||||||
|
'config' => [
|
||||||
|
'type' => 'none',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'hidden' => [
|
||||||
|
'exclude' => 1,
|
||||||
|
'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.hidden',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'check',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'ratingobject' => [
|
||||||
|
'exclude' => 1,
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.stepconf.ratingobject',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'passthrough',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'steporder' => [
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.stepconf.steporder',
|
||||||
|
'l10n_display' => 'defaultAsReadonly',
|
||||||
|
//'l10n_cat' => 'media',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'input',
|
||||||
|
'size' => '8',
|
||||||
|
'max' => '12',
|
||||||
|
'eval' => 'Thucke\\ThRating\\Evaluation\\DynamicCssEvaluator,int,required',
|
||||||
|
'default' => '1',
|
||||||
|
'range' => [
|
||||||
|
'lower' => 1
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'stepweight' => [
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.stepconf.stepweight',
|
||||||
|
'l10n_display' => 'defaultAsReadonly',
|
||||||
|
//'l10n_cat' => 'media',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'input',
|
||||||
|
'size' => '8',
|
||||||
|
'max' => '12',
|
||||||
|
'eval' => 'Thucke\\ThRating\\Evaluation\\DynamicCssEvaluator,int',
|
||||||
|
'default' => '1',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'stepname' => [
|
||||||
|
'exclude' => 1,
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.stepconf.stepname',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'inline',
|
||||||
|
'foreign_table' => 'tx_bookmarkslikesratings_domain_model_stepname',
|
||||||
|
'foreign_field' => 'stepconf',
|
||||||
|
'foreign_unique' => 'sys_language_uid',
|
||||||
|
'foreign_default_sortby' => 'sys_language_uid',
|
||||||
|
'appearance' => [
|
||||||
|
'levelLinksPosition' => 'bottom',
|
||||||
|
'collapseAll' => true,
|
||||||
|
'expandSingle' => true,
|
||||||
|
'newRecordLinkAddTitle' => true,
|
||||||
|
'enabledControls' => [
|
||||||
|
'info' => true,
|
||||||
|
'delete' => true,
|
||||||
|
'localize' => true,
|
||||||
|
],
|
||||||
|
'showPossibleLocalizationRecords' => true,
|
||||||
|
'showSynchronizationLink' => true,
|
||||||
|
'newRecordLinkPosition' => 'both',
|
||||||
|
'showAllLocalizationLink' => true,
|
||||||
|
'showRemovedLocalizationRecords' => 1,
|
||||||
|
],
|
||||||
|
'behaviour' => [
|
||||||
|
'allowLanguageSynchronization' => true,
|
||||||
|
'enableCascadingDelete' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'votes' => [
|
||||||
|
'exclude' => 1,
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.stepconf.votes',
|
||||||
|
'l10n_mode' => 'eclude',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'inline',
|
||||||
|
'behaviour' => [
|
||||||
|
'allowLanguageSynchronization' => true,
|
||||||
|
],
|
||||||
|
'foreign_table' => 'tx_bookmarkslikesratings_domain_model_vote',
|
||||||
|
'foreign_field' => 'vote',
|
||||||
|
'foreign_default_sortby' => 'uid',
|
||||||
|
'appearance' => [
|
||||||
|
'levelLinksPosition' => 'bottom',
|
||||||
|
'collapseAll' => 1,
|
||||||
|
'expandSingle' => 1,
|
||||||
|
'newRecordLinkAddTitle' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'uid' => [
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.stepconf.uid',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'passthrough',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'types' => [
|
||||||
|
'0' => [
|
||||||
|
'showitem' => 'hidden, steporder, stepweight, stepname, votes'
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'palettes' => [
|
||||||
|
'1' => [
|
||||||
|
'showitem' => ''
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
@ -0,0 +1,131 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'ctrl' => [
|
||||||
|
'title' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.stepname.title',
|
||||||
|
'label' => 'uid',
|
||||||
|
'label_alt' => 'stepconf,sys_language_uid',
|
||||||
|
'label_userFunc' => 'Thucke\\ThRating\\Userfuncs\\Tca->getStepnameRecordTitle',
|
||||||
|
'tstamp' => 'tstamp',
|
||||||
|
'crdate' => 'crdate',
|
||||||
|
'cruser_id' => 'cruser_id',
|
||||||
|
'origUid' => 't3_origuid',
|
||||||
|
'languageField' => 'sys_language_uid',
|
||||||
|
'transOrigPointerField' => 'l18n_parent',
|
||||||
|
'transOrigDiffSourceField' => 'l18n_diffsource',
|
||||||
|
'delete' => 'deleted',
|
||||||
|
'adminOnly' => false,
|
||||||
|
'hideTable' => false,
|
||||||
|
'editlock' => 'sys_language_uid,stepconf',
|
||||||
|
'dividers2tabs' => true,
|
||||||
|
'enablecolumns' => [
|
||||||
|
'disabled' => 'hidden'
|
||||||
|
],
|
||||||
|
'iconfile' => 'EXT:bookmarks_likes_ratings/Resources/Public/Icons/tx_bookmarkslikesratings_domain_model_stepname.gif',
|
||||||
|
],
|
||||||
|
'interface' => [
|
||||||
|
'showRecordFieldList' => 'hidden, stepconf, stepname, sys_language_uid',
|
||||||
|
],
|
||||||
|
'columns' => [
|
||||||
|
'pid' => [
|
||||||
|
'exclude' => 1,
|
||||||
|
'config' => [
|
||||||
|
'type' => 'none',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'hidden' => [
|
||||||
|
'exclude' => 1,
|
||||||
|
'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.hidden',
|
||||||
|
'l10n_display' => 'hideDiff',
|
||||||
|
'l10n_mode' => 'exclude',
|
||||||
|
'displayCond' => [
|
||||||
|
'AND' => [
|
||||||
|
'FIELD:sys_language_uid:=:0',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'config' => [
|
||||||
|
'type' => 'check',
|
||||||
|
'default' => 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'stepconf' => [
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.stepname.stepconf',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'passthrough',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'stepname' => [
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.stepname.stepname',
|
||||||
|
'l10n_mode' => 'prefixLangTitle',
|
||||||
|
'l10n_display' => 'hideDiff',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'input',
|
||||||
|
'size' => '15',
|
||||||
|
'max' => '64',
|
||||||
|
'eval' => 'Thucke\\ThRating\\Evaluation\\DynamicCssEvaluator,trim',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'uid' => [
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.stepname.uid',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'none',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'sys_language_uid' => [
|
||||||
|
'exclude' => true,
|
||||||
|
'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.language',
|
||||||
|
'config' => [
|
||||||
|
'readOnly' => true,
|
||||||
|
'type' => 'select',
|
||||||
|
'renderType' => 'selectSingle',
|
||||||
|
'special' => 'languages',
|
||||||
|
'foreign_table' => 'sys_language',
|
||||||
|
'foreign_table_where' => 'ORDER BY sys_language.title',
|
||||||
|
'items' => [
|
||||||
|
[
|
||||||
|
'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages',
|
||||||
|
-1,
|
||||||
|
'flags-multiple'
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'default' => 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'l18n_parent' => [
|
||||||
|
'displayCond' => 'FIELD:sys_language_uid:>:0',
|
||||||
|
'exclude' => true,
|
||||||
|
'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'select',
|
||||||
|
'renderType' => 'selectSingle',
|
||||||
|
'items' => [
|
||||||
|
[
|
||||||
|
'',
|
||||||
|
0
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'foreign_table' => 'tx_bookmarkslikesratings_domain_model_stepname',
|
||||||
|
'foreign_table_where' => 'AND {#tx_bookmarkslikesratings_domain_model_stepname}.{#uid}=###REC_FIELD_l18n_parent###' .
|
||||||
|
'AND {#tx_bookmarkslikesratings_domain_model_stepname}.{#sys_language_uid} IN (-1,0)',
|
||||||
|
'fieldWizard' => [
|
||||||
|
'selectIcons' => [
|
||||||
|
'disabled' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'default' => 0
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'l18n_diffsource' => [
|
||||||
|
'config' => [
|
||||||
|
'type' => 'passthrough',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'types' => [
|
||||||
|
'0' => ['showitem' => 'hidden, stepname, stepconf, sys_language_uid'],
|
||||||
|
],
|
||||||
|
'palettes' => [
|
||||||
|
'1' => ['showitem' => ''],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
108
Configuration/TCA/tx_bookmarkslikesratings_domain_model_vote.php
Normal file
108
Configuration/TCA/tx_bookmarkslikesratings_domain_model_vote.php
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'ctrl' => [
|
||||||
|
'title' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.vote.title',
|
||||||
|
'label' => 'uid',
|
||||||
|
'label_alt' => 'rating,fe_user,vote',
|
||||||
|
'label_userFunc' => 'WapplerSystems\\BookmarksLikesRatings\\Userfuncs\\Tca->getVoteRecordTitle',
|
||||||
|
'tstamp' => 'tstamp',
|
||||||
|
'crdate' => 'crdate',
|
||||||
|
'cruser_id' => 'cruser_id',
|
||||||
|
'delete' => 'deleted',
|
||||||
|
'adminOnly' => true,
|
||||||
|
'hideTable' => true,
|
||||||
|
'editlock' => 'rating',
|
||||||
|
'enablecolumns' => [
|
||||||
|
'disabled' => 'hidden',
|
||||||
|
],
|
||||||
|
'iconfile' => 'EXT:bookmarks_likes_ratings/Resources/Public/Icons/tx_bookmarkslikesratings_domain_model_vote.gif',
|
||||||
|
],
|
||||||
|
'interface' => [
|
||||||
|
'showRecordFieldList' => 'hidden, rating, voter, vote',
|
||||||
|
],
|
||||||
|
'columns' => [
|
||||||
|
'pid' => [
|
||||||
|
'exclude' => 1,
|
||||||
|
'config' => [
|
||||||
|
'type' => 'none',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'hidden' => [
|
||||||
|
'exclude' => 1,
|
||||||
|
'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.hidden',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'check',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'rating' => [
|
||||||
|
'exclude' => 1,
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.vote.rating',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'select',
|
||||||
|
'renderType' => 'selectSingle',
|
||||||
|
'foreign_table' => 'tx_bookmarkslikesratings_domain_model_rating',
|
||||||
|
'maxitems' => 1,
|
||||||
|
'minitems' => 1,
|
||||||
|
'disableNoMatchingValueElement' => 1,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'voter' => [
|
||||||
|
'exclude' => 1,
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.vote.voter',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'select',
|
||||||
|
'renderType' => 'selectSingle',
|
||||||
|
'foreign_table' => 'fe_users',
|
||||||
|
'foreign_table_where' => 'ORDER BY fe_users.username',
|
||||||
|
'items' => [
|
||||||
|
[
|
||||||
|
'--div--', 0
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'fieldControl' => [
|
||||||
|
'editPopup' => [
|
||||||
|
'disabled' => false,
|
||||||
|
],
|
||||||
|
'addRecord' => [
|
||||||
|
'disabled' => false,
|
||||||
|
'options' => [
|
||||||
|
'setValue' => 'prepend',
|
||||||
|
],
|
||||||
|
'listModule' => [
|
||||||
|
'disabled' => false,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
//TODO Prio 3: only provide valid references from foreign table
|
||||||
|
'vote' => [
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.vote.vote',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'select',
|
||||||
|
'renderType' => 'selectSingle',
|
||||||
|
'foreign_table' => 'tx_bookmarkslikesratings_domain_model_stepconf',
|
||||||
|
'maxitems' => 1,
|
||||||
|
'minitems' => 1,
|
||||||
|
'disableNoMatchingValueElement' => 1,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'uid' => [
|
||||||
|
'label' => 'LLL:EXT:bookmarks_likes_ratings/Resources/Private/Language/locallang.xlf:tca.model.vote.uid',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'none'
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'types' => [
|
||||||
|
'1' => [
|
||||||
|
'showitem' => 'hidden, rating, voter, vote'
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'palettes' => [
|
||||||
|
'1' => [
|
||||||
|
'showitem' => ''
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
@ -1,11 +1,11 @@
|
|||||||
plugin.tx_wsbookmarkpages {
|
plugin.tx_wsbookmarkpages {
|
||||||
view {
|
view {
|
||||||
# cat=plugin.tx_wsbookmarkpages/file; type=string; label=Path to template root (FE)
|
# cat=plugin.tx_wsbookmarkpages/file; type=string; label=Path to template root (FE)
|
||||||
templateRootPath = EXT:ws_bookmark_pages/Resources/Private/Templates/
|
templateRootPath = EXT:bookmarks_likes_ratings/Resources/Private/Templates/
|
||||||
# cat=plugin.tx_wsbookmarkpages/file; type=string; label=Path to template partials (FE)
|
# cat=plugin.tx_wsbookmarkpages/file; type=string; label=Path to template partials (FE)
|
||||||
partialRootPath = EXT:ws_bookmark_pages/Resources/Private/Partials/
|
partialRootPath = EXT:bookmarks_likes_ratings/Resources/Private/Partials/
|
||||||
# cat=plugin.tx_wsbookmarkpages/file; type=string; label=Path to template layouts (FE)
|
# cat=plugin.tx_wsbookmarkpages/file; type=string; label=Path to template layouts (FE)
|
||||||
layoutRootPath = EXT:ws_bookmark_pages/Resources/Private/Layouts/
|
layoutRootPath = EXT:bookmarks_likes_ratings/Resources/Private/Layouts/
|
||||||
}
|
}
|
||||||
settings {
|
settings {
|
||||||
# cat=plugin.tx_wsbookmarkpages/general; type=boolean; label=Store bookmarks local:If set the bookmarks will be stored in the local storage from the clients browser.
|
# cat=plugin.tx_wsbookmarkpages/general; type=boolean; label=Store bookmarks local:If set the bookmarks will be stored in the local storage from the clients browser.
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
.. include:: ../Includes.txt
|
|
||||||
|
|
||||||
|
|
||||||
.. _admin-manual:
|
|
||||||
|
|
||||||
Administrator Manual
|
|
||||||
====================
|
|
||||||
|
|
||||||
Installation
|
|
||||||
------------
|
|
||||||
|
|
||||||
There are two ways to properly install the extension.
|
|
||||||
|
|
||||||
1. Composer installation
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
In case you use Composer to manage dependencies of your TYPO3 project,
|
|
||||||
you can just issue the following Composer command in your project root directory.
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
composer require wapplersystems/bookmark-pages
|
|
||||||
|
|
||||||
2. Installation with Extension Manager
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Download and install the extension with the extension manager module.
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
|||||||
.. include:: ../Includes.txt
|
|
||||||
|
|
||||||
.. highlight:: none
|
|
||||||
|
|
||||||
====================================
|
|
||||||
Changelog for release 2.0.0
|
|
||||||
====================================
|
|
||||||
|
|
||||||
Features
|
|
||||||
========
|
|
||||||
* [FEATURE] Enable multiple plugin use per page (22.04.2021, f335afc by roman)
|
|
||||||
* [FEATURE] Load bookmarks from browsers local storage (16.04.2021, 1c7511d by roman)
|
|
||||||
* [FEATURE] Cache main action, load list asynchronous (15.04.2021, d4e04e5 by roman)
|
|
||||||
|
|
||||||
Bugfixes
|
|
||||||
========
|
|
||||||
* [BUGFIX] Correct issue with empty list (22.04.2021, 1f87412 by Roman)
|
|
||||||
* [BUGFIX] Fix issue updating links (20.04.2021, 0a6e47e by roman)
|
|
||||||
* [BUGFIX] Fix issue with empty accessible bookmarks (20.04.2021, 1b169ab by roman)
|
|
||||||
|
|
||||||
Breaking changes
|
|
||||||
================
|
|
||||||
* [!!!][TASK] Enable local storage per default (27.04.2021, 2e460ca by roman)
|
|
||||||
* [!!!][TASK] Remove access restriction (18.04.2021, 28c0248 by roman)
|
|
||||||
* [!!!][TASK] Refactor js (16.04.2021, 9a09b96 by roman)
|
|
||||||
|
|
||||||
Reference
|
|
||||||
=========
|
|
||||||
|
|
||||||
.. highlight:: shell
|
|
||||||
|
|
||||||
Generated by:
|
|
||||||
|
|
||||||
git log 1.2.2..2e460cac --pretty="* %s (%cd, %h by %an)" --date=format:%d.%m.%Y --abbrev-commit --grep
|
|
||||||
|
|
||||||
**Note:** The above list contains just commits marked with [FEATURE], [BUGFIX] and [!!!]. Complementary commits are
|
|
||||||
available at `Github <https://github.com/buepro/typo3-pizpalue/commits/master)>`__.
|
|
||||||
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
|||||||
.. include:: ../Includes.txt
|
|
||||||
|
|
||||||
|
|
||||||
==============================
|
|
||||||
Configuration
|
|
||||||
==============================
|
|
||||||
|
|
||||||
The plugin output doesn't look very cute after install. It is necessary to adopt it to your needs. Nevertheless it shouldn't be too hard.
|
|
||||||
|
|
||||||
.. tip::
|
|
||||||
|
|
||||||
Have a look at the comments in the example template.
|
|
||||||
|
|
||||||
|
|
||||||
Make it work
|
|
||||||
============
|
|
||||||
|
|
||||||
Here are the needed steps described to make the plugin work.
|
|
||||||
|
|
||||||
Additional work might be needed to adapt is to your needs. Usually this is limited to template work.
|
|
||||||
|
|
||||||
|
|
||||||
1. Include TypoScript
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
Include the TypoScript in your template record or your site package.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
2. Include Plugin
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
Include the `Bookmark Pages` plugin as content element. This is just for testing and not usually what you want.
|
|
||||||
|
|
||||||
Login and you should see some output. On the introduction package it looks like this:
|
|
||||||
|
|
||||||
|
|
||||||
.. figure:: ../Images/screenshot-fe.png
|
|
||||||
|
|
||||||
The login box is not part of this extension.
|
|
||||||
|
|
||||||
The plugin might be inserted more than once on a page. In that case mark `Is complementary` under `Plugin Options`
|
|
||||||
for all plugins except the first one.
|
|
||||||
|
|
||||||
|
|
||||||
Customization
|
|
||||||
=============
|
|
||||||
|
|
||||||
|
|
||||||
1. TypoScript and Templates
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
You may just copy the needed parts to your site package.
|
|
||||||
|
|
||||||
The fluid template paths can be configured as usual using TypoScript. Have a look into the TypoScript template
|
|
||||||
(look for plugin.tx_wsbookmarkpages.view)
|
|
||||||
|
|
||||||
The bookmarks might be stored in the browsers local storage allowing users to bookmark pages without being registered
|
|
||||||
on the site. Storing the bookmarks locally as well safes unnecessary server requests. The feature can be enabled
|
|
||||||
through the constants editor.
|
|
||||||
|
|
||||||
|
|
||||||
2. JavaScript and JQuery
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
The provided example uses JQuery for ajax requests. JQuery is included by TypoScript. You might want to remove that with:
|
|
||||||
|
|
||||||
.. code-block:: typoscript
|
|
||||||
|
|
||||||
page.includeJSFooterlibs.bookmark_pages_jquery >
|
|
||||||
|
|
||||||
If you don't use JQuery you have to adapt the JavaScript.
|
|
||||||
Have a look into Resources/Public/Scripts/JavaScript/bookmark_pages.js
|
|
||||||
|
|
||||||
|
|
||||||
3. Include in your page template
|
|
||||||
--------------------------------
|
|
||||||
|
|
||||||
The rendering of the bookmarks list might be something you want to include into your page template. This could be done
|
|
||||||
in a fluid template like this:
|
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: html
|
|
||||||
|
|
||||||
<f:cObject typoscriptObjectPath="tt_content.list.20.bookmarkpages_bookmarks"/>
|
|
||||||
|
|
||||||
|
|
||||||
Of course you want a bookmark button on every page. This can be done in fluid like this:
|
|
||||||
|
|
||||||
.. code-block:: html
|
|
||||||
|
|
||||||
<div class="bookmark-pages">
|
|
||||||
<p><a class="bookmark-ajax-submit bookmark-this-page" href="javascript:void(0);">Bookmark page in templates</a></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
You can place the snippet in any template not just the plugin templates.
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 16 KiB |
Binary file not shown.
Before Width: | Height: | Size: 13 KiB |
@ -1,14 +0,0 @@
|
|||||||
.. This is 'Includes.txt'. It is included at the very top of each and
|
|
||||||
every ReST source file in THIS documentation project (= manual).
|
|
||||||
|
|
||||||
.. role:: aspect (emphasis)
|
|
||||||
.. role:: html(code)
|
|
||||||
.. role:: js(code)
|
|
||||||
.. role:: php(code)
|
|
||||||
.. role:: typoscript(code)
|
|
||||||
|
|
||||||
.. role:: ts(typoscript)
|
|
||||||
:class: typoscript
|
|
||||||
|
|
||||||
.. default-role:: code
|
|
||||||
.. highlight:: php
|
|
@ -1,57 +0,0 @@
|
|||||||
.. ==================================================
|
|
||||||
.. FOR YOUR INFORMATION
|
|
||||||
.. --------------------------------------------------
|
|
||||||
.. -*- coding: utf-8 -*- with BOM.
|
|
||||||
|
|
||||||
.. include:: Includes.txt
|
|
||||||
|
|
||||||
|
|
||||||
.. _start:
|
|
||||||
|
|
||||||
=============================================================
|
|
||||||
Bookmark Pages
|
|
||||||
=============================================================
|
|
||||||
|
|
||||||
.. only:: html
|
|
||||||
|
|
||||||
:Classification:
|
|
||||||
bookmark_pages
|
|
||||||
|
|
||||||
:Version:
|
|
||||||
|release|
|
|
||||||
|
|
||||||
:Language:
|
|
||||||
en
|
|
||||||
|
|
||||||
:Description:
|
|
||||||
Provides bookmarks functionality of local pages for logged in frontend users
|
|
||||||
|
|
||||||
:Keywords:
|
|
||||||
bookmark page
|
|
||||||
|
|
||||||
:Copyright:
|
|
||||||
2016-2020
|
|
||||||
|
|
||||||
:Author:
|
|
||||||
René Fritz
|
|
||||||
|
|
||||||
:License:
|
|
||||||
This document is published under the Open Publication License
|
|
||||||
available from http://www.opencontent.org/openpub/
|
|
||||||
|
|
||||||
:Rendered:
|
|
||||||
|today|
|
|
||||||
|
|
||||||
The content of this document is related to TYPO3,
|
|
||||||
a GNU/GPL CMS/Framework available from `www.typo3.org <https://www.typo3.org/>`_.
|
|
||||||
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
|
|
||||||
Sitemap/Index
|
|
||||||
Introduction/Index
|
|
||||||
Configuration/Index
|
|
||||||
AdministratorManual/Index
|
|
||||||
Support/Index
|
|
||||||
Links
|
|
@ -1,33 +0,0 @@
|
|||||||
.. include:: ../Includes.txt
|
|
||||||
|
|
||||||
|
|
||||||
Introduction
|
|
||||||
============
|
|
||||||
|
|
||||||
What does it do?
|
|
||||||
----------------
|
|
||||||
|
|
||||||
This is a TYPO3 plugin that provides bookmarks functionality of local pages.
|
|
||||||
For example this is very helpful for intranet websites.
|
|
||||||
|
|
||||||
The plugin can be configured to use the browsers local storage allowing non registered users to use the feature too.
|
|
||||||
In case a website user likes to have the bookmarks available on different devices a frontend account might be used.
|
|
||||||
After logging in the bookmarks are saved to the server hence might be accessed from within any device.
|
|
||||||
|
|
||||||
TypoScript and fluid templates are just examples. Adapt it to your needs.
|
|
||||||
|
|
||||||
The extension was created by `René Fritz <https://github.com/colorcube>`__. The ownership has been transferred in
|
|
||||||
april 2021.
|
|
||||||
|
|
||||||
|
|
||||||
Screenshots
|
|
||||||
-----------
|
|
||||||
|
|
||||||
|
|
||||||
.. figure:: ../Images/screenshot-styled-fe.png
|
|
||||||
|
|
||||||
The screenshot shows the functionality, the styling is not included.
|
|
||||||
|
|
||||||
|
|
||||||
You have a list with bookmarks which can be deleted and you can place a 'bookmark' button anywhere on the page.
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
|||||||
# coding: utf-8
|
|
||||||
|
|
||||||
[general]
|
|
||||||
project = bookmark_pages
|
|
||||||
release = 2.0.1
|
|
||||||
version = 2.0.1
|
|
||||||
|
|
||||||
[html_theme_options]
|
|
||||||
github_branch = master
|
|
||||||
github_repository = buepro/typo-bookmark_pages
|
|
||||||
project_contact = rb@buechler.pro
|
|
||||||
project_home = https://github.com/buepro/typo3-bookmark_pages
|
|
||||||
project_issues = https://github.com/buepro/typo3-bookmark_pages/issues
|
|
||||||
project_repository = https://github.com/buepro/typo3-bookmark_pages
|
|
||||||
|
|
||||||
[extensions]
|
|
||||||
issue = https://github.com/buepro/typo3-bookmark_pages/issues/%s | Issue #
|
|
@ -1,12 +0,0 @@
|
|||||||
|
|
||||||
:template: sitemap.html
|
|
||||||
|
|
||||||
|
|
||||||
.. _Sitemap:
|
|
||||||
|
|
||||||
=======
|
|
||||||
Sitemap
|
|
||||||
=======
|
|
||||||
|
|
||||||
.. template 'sitemap.html' will insert the toctree as a sitemap here
|
|
||||||
below normal contents
|
|
@ -1,28 +0,0 @@
|
|||||||
.. include:: ../Includes.txt
|
|
||||||
|
|
||||||
|
|
||||||
Support and Feedback
|
|
||||||
====================
|
|
||||||
|
|
||||||
The extension is provided as is. Please understand that I can't give an extensive amount of support time for free.
|
|
||||||
|
|
||||||
Any feedback is always appreciated.
|
|
||||||
|
|
||||||
So if you have questions or feedback there are several options:
|
|
||||||
|
|
||||||
Bug Tracker
|
|
||||||
-----------
|
|
||||||
|
|
||||||
For bug reports and feature requests: https://github.com/buepro/typo3-bookmark_pages/issues
|
|
||||||
|
|
||||||
Commercial support
|
|
||||||
------------------
|
|
||||||
|
|
||||||
If you need commercial support, get in touch.
|
|
||||||
|
|
||||||
Nice mails
|
|
||||||
----------
|
|
||||||
|
|
||||||
Some nice words fit every time - just drop me some kind words by mail to make me happy :-)
|
|
||||||
|
|
||||||
|
|
339
LICENSE.txt
339
LICENSE.txt
@ -1,339 +0,0 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
Version 2, June 1991
|
|
||||||
|
|
||||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The licenses for most software are designed to take away your
|
|
||||||
freedom to share and change it. By contrast, the GNU General Public
|
|
||||||
License is intended to guarantee your freedom to share and change free
|
|
||||||
software--to make sure the software is free for all its users. This
|
|
||||||
General Public License applies to most of the Free Software
|
|
||||||
Foundation's software and to any other program whose authors commit to
|
|
||||||
using it. (Some other Free Software Foundation software is covered by
|
|
||||||
the GNU Lesser General Public License instead.) You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
this service if you wish), that you receive source code or can get it
|
|
||||||
if you want it, that you can change the software or use pieces of it
|
|
||||||
in new free programs; and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to make restrictions that forbid
|
|
||||||
anyone to deny you these rights or to ask you to surrender the rights.
|
|
||||||
These restrictions translate to certain responsibilities for you if you
|
|
||||||
distribute copies of the software, or if you modify it.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
|
||||||
gratis or for a fee, you must give the recipients all the rights that
|
|
||||||
you have. You must make sure that they, too, receive or can get the
|
|
||||||
source code. And you must show them these terms so they know their
|
|
||||||
rights.
|
|
||||||
|
|
||||||
We protect your rights with two steps: (1) copyright the software, and
|
|
||||||
(2) offer you this license which gives you legal permission to copy,
|
|
||||||
distribute and/or modify the software.
|
|
||||||
|
|
||||||
Also, for each author's protection and ours, we want to make certain
|
|
||||||
that everyone understands that there is no warranty for this free
|
|
||||||
software. If the software is modified by someone else and passed on, we
|
|
||||||
want its recipients to know that what they have is not the original, so
|
|
||||||
that any problems introduced by others will not reflect on the original
|
|
||||||
authors' reputations.
|
|
||||||
|
|
||||||
Finally, any free program is threatened constantly by software
|
|
||||||
patents. We wish to avoid the danger that redistributors of a free
|
|
||||||
program will individually obtain patent licenses, in effect making the
|
|
||||||
program proprietary. To prevent this, we have made it clear that any
|
|
||||||
patent must be licensed for everyone's free use or not licensed at all.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. This License applies to any program or other work which contains
|
|
||||||
a notice placed by the copyright holder saying it may be distributed
|
|
||||||
under the terms of this General Public License. The "Program", below,
|
|
||||||
refers to any such program or work, and a "work based on the Program"
|
|
||||||
means either the Program or any derivative work under copyright law:
|
|
||||||
that is to say, a work containing the Program or a portion of it,
|
|
||||||
either verbatim or with modifications and/or translated into another
|
|
||||||
language. (Hereinafter, translation is included without limitation in
|
|
||||||
the term "modification".) Each licensee is addressed as "you".
|
|
||||||
|
|
||||||
Activities other than copying, distribution and modification are not
|
|
||||||
covered by this License; they are outside its scope. The act of
|
|
||||||
running the Program is not restricted, and the output from the Program
|
|
||||||
is covered only if its contents constitute a work based on the
|
|
||||||
Program (independent of having been made by running the Program).
|
|
||||||
Whether that is true depends on what the Program does.
|
|
||||||
|
|
||||||
1. You may copy and distribute verbatim copies of the Program's
|
|
||||||
source code as you receive it, in any medium, provided that you
|
|
||||||
conspicuously and appropriately publish on each copy an appropriate
|
|
||||||
copyright notice and disclaimer of warranty; keep intact all the
|
|
||||||
notices that refer to this License and to the absence of any warranty;
|
|
||||||
and give any other recipients of the Program a copy of this License
|
|
||||||
along with the Program.
|
|
||||||
|
|
||||||
You may charge a fee for the physical act of transferring a copy, and
|
|
||||||
you may at your option offer warranty protection in exchange for a fee.
|
|
||||||
|
|
||||||
2. You may modify your copy or copies of the Program or any portion
|
|
||||||
of it, thus forming a work based on the Program, and copy and
|
|
||||||
distribute such modifications or work under the terms of Section 1
|
|
||||||
above, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) You must cause the modified files to carry prominent notices
|
|
||||||
stating that you changed the files and the date of any change.
|
|
||||||
|
|
||||||
b) You must cause any work that you distribute or publish, that in
|
|
||||||
whole or in part contains or is derived from the Program or any
|
|
||||||
part thereof, to be licensed as a whole at no charge to all third
|
|
||||||
parties under the terms of this License.
|
|
||||||
|
|
||||||
c) If the modified program normally reads commands interactively
|
|
||||||
when run, you must cause it, when started running for such
|
|
||||||
interactive use in the most ordinary way, to print or display an
|
|
||||||
announcement including an appropriate copyright notice and a
|
|
||||||
notice that there is no warranty (or else, saying that you provide
|
|
||||||
a warranty) and that users may redistribute the program under
|
|
||||||
these conditions, and telling the user how to view a copy of this
|
|
||||||
License. (Exception: if the Program itself is interactive but
|
|
||||||
does not normally print such an announcement, your work based on
|
|
||||||
the Program is not required to print an announcement.)
|
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
|
||||||
identifiable sections of that work are not derived from the Program,
|
|
||||||
and can be reasonably considered independent and separate works in
|
|
||||||
themselves, then this License, and its terms, do not apply to those
|
|
||||||
sections when you distribute them as separate works. But when you
|
|
||||||
distribute the same sections as part of a whole which is a work based
|
|
||||||
on the Program, the distribution of the whole must be on the terms of
|
|
||||||
this License, whose permissions for other licensees extend to the
|
|
||||||
entire whole, and thus to each and every part regardless of who wrote it.
|
|
||||||
|
|
||||||
Thus, it is not the intent of this section to claim rights or contest
|
|
||||||
your rights to work written entirely by you; rather, the intent is to
|
|
||||||
exercise the right to control the distribution of derivative or
|
|
||||||
collective works based on the Program.
|
|
||||||
|
|
||||||
In addition, mere aggregation of another work not based on the Program
|
|
||||||
with the Program (or with a work based on the Program) on a volume of
|
|
||||||
a storage or distribution medium does not bring the other work under
|
|
||||||
the scope of this License.
|
|
||||||
|
|
||||||
3. You may copy and distribute the Program (or a work based on it,
|
|
||||||
under Section 2) in object code or executable form under the terms of
|
|
||||||
Sections 1 and 2 above provided that you also do one of the following:
|
|
||||||
|
|
||||||
a) Accompany it with the complete corresponding machine-readable
|
|
||||||
source code, which must be distributed under the terms of Sections
|
|
||||||
1 and 2 above on a medium customarily used for software interchange; or,
|
|
||||||
|
|
||||||
b) Accompany it with a written offer, valid for at least three
|
|
||||||
years, to give any third party, for a charge no more than your
|
|
||||||
cost of physically performing source distribution, a complete
|
|
||||||
machine-readable copy of the corresponding source code, to be
|
|
||||||
distributed under the terms of Sections 1 and 2 above on a medium
|
|
||||||
customarily used for software interchange; or,
|
|
||||||
|
|
||||||
c) Accompany it with the information you received as to the offer
|
|
||||||
to distribute corresponding source code. (This alternative is
|
|
||||||
allowed only for noncommercial distribution and only if you
|
|
||||||
received the program in object code or executable form with such
|
|
||||||
an offer, in accord with Subsection b above.)
|
|
||||||
|
|
||||||
The source code for a work means the preferred form of the work for
|
|
||||||
making modifications to it. For an executable work, complete source
|
|
||||||
code means all the source code for all modules it contains, plus any
|
|
||||||
associated interface definition files, plus the scripts used to
|
|
||||||
control compilation and installation of the executable. However, as a
|
|
||||||
special exception, the source code distributed need not include
|
|
||||||
anything that is normally distributed (in either source or binary
|
|
||||||
form) with the major components (compiler, kernel, and so on) of the
|
|
||||||
operating system on which the executable runs, unless that component
|
|
||||||
itself accompanies the executable.
|
|
||||||
|
|
||||||
If distribution of executable or object code is made by offering
|
|
||||||
access to copy from a designated place, then offering equivalent
|
|
||||||
access to copy the source code from the same place counts as
|
|
||||||
distribution of the source code, even though third parties are not
|
|
||||||
compelled to copy the source along with the object code.
|
|
||||||
|
|
||||||
4. You may not copy, modify, sublicense, or distribute the Program
|
|
||||||
except as expressly provided under this License. Any attempt
|
|
||||||
otherwise to copy, modify, sublicense or distribute the Program is
|
|
||||||
void, and will automatically terminate your rights under this License.
|
|
||||||
However, parties who have received copies, or rights, from you under
|
|
||||||
this License will not have their licenses terminated so long as such
|
|
||||||
parties remain in full compliance.
|
|
||||||
|
|
||||||
5. You are not required to accept this License, since you have not
|
|
||||||
signed it. However, nothing else grants you permission to modify or
|
|
||||||
distribute the Program or its derivative works. These actions are
|
|
||||||
prohibited by law if you do not accept this License. Therefore, by
|
|
||||||
modifying or distributing the Program (or any work based on the
|
|
||||||
Program), you indicate your acceptance of this License to do so, and
|
|
||||||
all its terms and conditions for copying, distributing or modifying
|
|
||||||
the Program or works based on it.
|
|
||||||
|
|
||||||
6. Each time you redistribute the Program (or any work based on the
|
|
||||||
Program), the recipient automatically receives a license from the
|
|
||||||
original licensor to copy, distribute or modify the Program subject to
|
|
||||||
these terms and conditions. You may not impose any further
|
|
||||||
restrictions on the recipients' exercise of the rights granted herein.
|
|
||||||
You are not responsible for enforcing compliance by third parties to
|
|
||||||
this License.
|
|
||||||
|
|
||||||
7. If, as a consequence of a court judgment or allegation of patent
|
|
||||||
infringement or for any other reason (not limited to patent issues),
|
|
||||||
conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot
|
|
||||||
distribute so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you
|
|
||||||
may not distribute the Program at all. For example, if a patent
|
|
||||||
license would not permit royalty-free redistribution of the Program by
|
|
||||||
all those who receive copies directly or indirectly through you, then
|
|
||||||
the only way you could satisfy both it and this License would be to
|
|
||||||
refrain entirely from distribution of the Program.
|
|
||||||
|
|
||||||
If any portion of this section is held invalid or unenforceable under
|
|
||||||
any particular circumstance, the balance of the section is intended to
|
|
||||||
apply and the section as a whole is intended to apply in other
|
|
||||||
circumstances.
|
|
||||||
|
|
||||||
It is not the purpose of this section to induce you to infringe any
|
|
||||||
patents or other property right claims or to contest validity of any
|
|
||||||
such claims; this section has the sole purpose of protecting the
|
|
||||||
integrity of the free software distribution system, which is
|
|
||||||
implemented by public license practices. Many people have made
|
|
||||||
generous contributions to the wide range of software distributed
|
|
||||||
through that system in reliance on consistent application of that
|
|
||||||
system; it is up to the author/donor to decide if he or she is willing
|
|
||||||
to distribute software through any other system and a licensee cannot
|
|
||||||
impose that choice.
|
|
||||||
|
|
||||||
This section is intended to make thoroughly clear what is believed to
|
|
||||||
be a consequence of the rest of this License.
|
|
||||||
|
|
||||||
8. If the distribution and/or use of the Program is restricted in
|
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
|
||||||
original copyright holder who places the Program under this License
|
|
||||||
may add an explicit geographical distribution limitation excluding
|
|
||||||
those countries, so that distribution is permitted only in or among
|
|
||||||
countries not thus excluded. In such case, this License incorporates
|
|
||||||
the limitation as if written in the body of this License.
|
|
||||||
|
|
||||||
9. The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the Program
|
|
||||||
specifies a version number of this License which applies to it and "any
|
|
||||||
later version", you have the option of following the terms and conditions
|
|
||||||
either of that version or of any later version published by the Free
|
|
||||||
Software Foundation. If the Program does not specify a version number of
|
|
||||||
this License, you may choose any version ever published by the Free Software
|
|
||||||
Foundation.
|
|
||||||
|
|
||||||
10. If you wish to incorporate parts of the Program into other free
|
|
||||||
programs whose distribution conditions are different, write to the author
|
|
||||||
to ask for permission. For software which is copyrighted by the Free
|
|
||||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
|
||||||
make exceptions for this. Our decision will be guided by the two goals
|
|
||||||
of preserving the free status of all derivatives of our free software and
|
|
||||||
of promoting the sharing and reuse of software generally.
|
|
||||||
|
|
||||||
NO WARRANTY
|
|
||||||
|
|
||||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
|
||||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
|
||||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
|
||||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
|
||||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
|
||||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
|
||||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
|
||||||
REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
|
||||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
|
||||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
|
||||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
|
||||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
|
||||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
|
||||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGES.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
convey the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
{description}
|
|
||||||
Copyright (C) {year} {fullname}
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If the program is interactive, make it output a short notice like this
|
|
||||||
when it starts in an interactive mode:
|
|
||||||
|
|
||||||
Gnomovision version 69, Copyright (C) year name of author
|
|
||||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
||||||
This is free software, and you are welcome to redistribute it
|
|
||||||
under certain conditions; type `show c' for details.
|
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, the commands you use may
|
|
||||||
be called something other than `show w' and `show c'; they could even be
|
|
||||||
mouse-clicks or menu items--whatever suits your program.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or your
|
|
||||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
|
||||||
necessary. Here is a sample; alter the names:
|
|
||||||
|
|
||||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
|
||||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
|
||||||
|
|
||||||
{signature of Ty Coon}, 1 April 1989
|
|
||||||
Ty Coon, President of Vice
|
|
||||||
|
|
||||||
This General Public License does not permit incorporating your program into
|
|
||||||
proprietary programs. If your program is a subroutine library, you may
|
|
||||||
consider it more useful to permit linking proprietary applications with the
|
|
||||||
library. If this is what you want to do, use the GNU Lesser General
|
|
||||||
Public License instead of this License.
|
|
28
README.md
28
README.md
@ -1,28 +0,0 @@
|
|||||||
# Bookmark Pages TYPO3 Extension
|
|
||||||
|
|
||||||
This is a TYPO3 extension that provides bookmarks functionality. In case the use from the browsers local storage is
|
|
||||||
disabled just logged in frontend users can bookmark pages.
|
|
||||||
|
|
||||||
The extension was created by [René Fritz](https://github.com/colorcube). The ownership has been transferred in
|
|
||||||
april 2021.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
TypoScript and fluid templates are just examples. Adapt it to your needs.
|
|
||||||
|
|
||||||
Further information: https://docs.typo3.org/p/wapplersystems/bookmark-pages/master/en-us/
|
|
||||||
|
|
||||||
### Dependencies
|
|
||||||
|
|
||||||
* TYPO3 10.4
|
|
||||||
|
|
||||||
### Installation
|
|
||||||
|
|
||||||
#### Installation using Composer
|
|
||||||
|
|
||||||
In your Composer based TYPO3 project root, just do `composer require wapplersystems/bookmark-pages`.
|
|
||||||
|
|
||||||
#### Installation as extension from TYPO3 Extension Repository (TER)
|
|
||||||
|
|
||||||
Download and install the extension with the extension manager module.
|
|
||||||
|
|
@ -1,29 +1,17 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||||
<xliff version="1.0">
|
<xliff version="1.0">
|
||||||
<file source-language="en" datatype="plaintext" original="messages" date="2021-04-21T09:11:39Z"
|
<file source-language="en" datatype="plaintext" original="messages" date="2021-04-21T09:11:39Z"
|
||||||
product-name="ws_bookmark_pages">
|
product-name="bookmarks_likes_ratings">
|
||||||
<header/>
|
<header/>
|
||||||
<body>
|
<body>
|
||||||
<trans-unit id="yes">
|
|
||||||
<source>Yes</source>
|
|
||||||
|
|
||||||
|
<trans-unit id="widget_group.ratings">
|
||||||
|
<source>Ratings</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="default">
|
<trans-unit id="widgets.bookmarks_likes_ratings.topLikes.title">
|
||||||
<source>Default</source>
|
<source>Top likes</source>
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="alternative">
|
|
||||||
<source>Alternative</source>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="bookmarkThisPage">
|
|
||||||
<source>Bookmark this page</source>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="ff.isComplementary">
|
|
||||||
<source>Is complementary</source>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="ff.isComplementary.description">
|
|
||||||
<source>In case the plugin is rendered more times on a page this option should be set for all instances except the first one.</source>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="ff.listType">
|
|
||||||
<source>List type</source>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
</body>
|
</body>
|
||||||
</file>
|
</file>
|
||||||
|
@ -20,4 +20,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</f:else>
|
</f:else>
|
||||||
</f:if>
|
</f:if>
|
||||||
<f:asset.script identifier="bookmarkPages" src="EXT:ws_bookmark_pages/Resources/Public/Scripts/JavaScript/ws_bookmark_pages.js" />
|
<f:asset.script identifier="bookmarkPages" src="EXT:bookmarks_likes_ratings/Resources/Public/Scripts/JavaScript/bookmarks_likes_ratings.js" />
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
<html data-namespace-typo3-fluid="true"
|
<html data-namespace-typo3-fluid="true"
|
||||||
xmlns="http://www.w3.org/1999/xhtml"
|
xmlns="http://www.w3.org/1999/xhtml"
|
||||||
xmlns:f="http://xsd.helmut-hummel.de/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
xmlns:f="http://xsd.helmut-hummel.de/ns/TYPO3/CMS/Fluid/ViewHelpers">
|
||||||
xmlns:t="http://typo3.org/ns/Helhum/TyposcriptRendering/ViewHelpers">
|
|
||||||
|
|
||||||
<f:layout name="Default"/>
|
<f:layout name="Default"/>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "wapplersystems/bookmark-pages",
|
"name": "wapplersystems/bookmarks-likes-ratings",
|
||||||
"type": "typo3-cms-extension",
|
"type": "typo3-cms-extension",
|
||||||
"description": "A TYPO3 extension that provides bookmarks functionality of local pages.",
|
"description": "A TYPO3 extension that provides bookmarks functionality of local pages.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@ -21,17 +21,14 @@
|
|||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"WapplerSystems\\WsBookmarkPages\\": "Classes/"
|
"WapplerSystems\\BookmarksLikesRatings\\": "Classes/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"replace": {
|
"replace": {
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"typo3/cms": {
|
"typo3/cms": {
|
||||||
"extension-key": "ws_bookmark_pages"
|
"extension-key": "bookmarks_likes_ratings"
|
||||||
},
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "2.x-dev"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,13 +8,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
$EM_CONF[$_EXTKEY] = [
|
$EM_CONF[$_EXTKEY] = [
|
||||||
'title' => 'Bookmark Pages',
|
'title' => 'Bookmarks/Likes/Ratings',
|
||||||
'description' => 'Provides bookmarks functionality of local pages for logged in frontend users.',
|
'description' => 'Provides bookmarks/likes/ratings functionality of frontend pages and articles for logged in frontend users.',
|
||||||
'category' => 'plugin',
|
'category' => 'plugin',
|
||||||
'author' => 'René Fritz, Roman Büchler',
|
'author' => 'Sven Wappler',
|
||||||
'author_email' => 'r.fritz@colorcube.de, rb@buechler.pro',
|
'author_email' => 'typo3@wappler.systems',
|
||||||
'author_company' => 'Colorcube, buechler.pro gmbh',
|
'author_company' => 'WapplerSystems',
|
||||||
'version' => '2.0.1',
|
'version' => '0.0.0',
|
||||||
'state' => 'stable',
|
'state' => 'stable',
|
||||||
'uploadfolder' => 0,
|
'uploadfolder' => 0,
|
||||||
'createDirs' => '',
|
'createDirs' => '',
|
||||||
@ -22,17 +22,13 @@ $EM_CONF[$_EXTKEY] = [
|
|||||||
'clearCacheOnLoad' => 1,
|
'clearCacheOnLoad' => 1,
|
||||||
'constraints' => [
|
'constraints' => [
|
||||||
'depends' => [
|
'depends' => [
|
||||||
'typo3' => '10.4.14-10.4.99',
|
'typo3' => '10.4.0-10.4.99'
|
||||||
'typoscript_rendering' => '2.3.1-2.99.99',
|
|
||||||
],
|
|
||||||
'conflicts' => [],
|
|
||||||
'suggests' => [
|
|
||||||
'news' => '*'
|
|
||||||
],
|
],
|
||||||
|
'conflicts' => []
|
||||||
],
|
],
|
||||||
'autoload' => [
|
'autoload' => [
|
||||||
'psr-4' => [
|
'psr-4' => [
|
||||||
'WapplerSystems\\BookmarkPages\\' => 'Classes'
|
'WapplerSystems\\BookmarksLikesRatings\\' => 'Classes'
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
@ -10,32 +10,16 @@
|
|||||||
defined('TYPO3') or die('Access denied.');
|
defined('TYPO3') or die('Access denied.');
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
$version = \TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version();
|
|
||||||
$version = \TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionNumberToInteger($version);
|
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
|
||||||
if ($version < 10000000) {
|
'BookmarkPages',
|
||||||
// For TYPO3 < V10
|
'Bookmarks',
|
||||||
// @extensionScannerIgnoreLine
|
[
|
||||||
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
|
\WapplerSystems\BookmarksLikesRatings\Controller\BookmarksController::class => 'index, bookmark, delete, listEntries'
|
||||||
'WapplerSystems.BookmarkPages',
|
],
|
||||||
'Bookmarks',
|
[
|
||||||
[
|
\WapplerSystems\BookmarksLikesRatings\Controller\BookmarksController::class => 'bookmark, delete, listEntries'
|
||||||
'Bookmarks' => 'index, bookmark, delete, listEntries',
|
]
|
||||||
],
|
);
|
||||||
// non-cacheable actions
|
|
||||||
[
|
|
||||||
'Bookmarks' => 'bookmark, delete, listEntries',
|
|
||||||
]
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
|
|
||||||
'BookmarkPages',
|
|
||||||
'Bookmarks',
|
|
||||||
[
|
|
||||||
\WapplerSystems\BookmarkPages\Controller\BookmarksController::class => 'index, bookmark, delete, listEntries'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
\WapplerSystems\BookmarkPages\Controller\BookmarksController::class => 'bookmark, delete, listEntries'
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})();
|
})();
|
||||||
|
139
ext_tables.sql
139
ext_tables.sql
@ -1,7 +1,144 @@
|
|||||||
#
|
#
|
||||||
# Add field to table 'fe_users'
|
# Add field to table 'fe_users'
|
||||||
#
|
#
|
||||||
CREATE TABLE fe_users (
|
CREATE TABLE fe_users
|
||||||
|
(
|
||||||
tx_bookmarks_pages blob
|
tx_bookmarks_pages blob
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE tx_bookmarkslikesratings_model_bookmark
|
||||||
|
(
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Table structure for table 'tx_bookmarkslikesratings_domain_model_ratingobject'
|
||||||
|
#
|
||||||
|
CREATE TABLE tx_bookmarkslikesratings_domain_model_ratingobject
|
||||||
|
(
|
||||||
|
uid int(11) unsigned DEFAULT '0' NOT NULL auto_increment,
|
||||||
|
pid int(11) DEFAULT '0' NOT NULL,
|
||||||
|
|
||||||
|
ratetable varchar(64) DEFAULT '' NOT NULL,
|
||||||
|
ratefield varchar(64) DEFAULT '' NOT NULL,
|
||||||
|
stepconfs int(11) DEFAULT '0' NOT NULL,
|
||||||
|
ratings int(11) DEFAULT '0' NOT NULL,
|
||||||
|
|
||||||
|
tstamp int(11) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
crdate int(11) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
cruser_id int(11) DEFAULT '0' NOT NULL,
|
||||||
|
deleted tinyint(4) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
hidden tinyint(4) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
is_dummy_record tinyint(1) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (uid),
|
||||||
|
KEY parent (pid),
|
||||||
|
KEY phpunit_dummy (is_dummy_record),
|
||||||
|
INDEX tx_bookmarkslikesratings_domain_model_ratingobject_i1 (ratetable, ratefield)
|
||||||
|
);
|
||||||
|
|
||||||
|
#
|
||||||
|
# Table structure for table 'tx_bookmarkslikesratings_domain_model_stepconf'
|
||||||
|
#
|
||||||
|
CREATE TABLE tx_bookmarkslikesratings_domain_model_stepconf
|
||||||
|
(
|
||||||
|
uid int(11) unsigned DEFAULT '0' NOT NULL auto_increment,
|
||||||
|
pid int(11) DEFAULT '0' NOT NULL,
|
||||||
|
|
||||||
|
ratingobject int(11) DEFAULT '0' NOT NULL,
|
||||||
|
steporder int(11) DEFAULT '1' NOT NULL,
|
||||||
|
stepweight int(11) DEFAULT '1' NOT NULL,
|
||||||
|
stepname int(11) DEFAULT '0' NOT NULL,
|
||||||
|
votes int(11) DEFAULT '0' NOT NULL,
|
||||||
|
|
||||||
|
tstamp int(11) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
crdate int(11) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
cruser_id int(11) DEFAULT '0' NOT NULL,
|
||||||
|
deleted tinyint(4) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
hidden tinyint(4) DEFAULT '0' NOT NULL,
|
||||||
|
is_dummy_record tinyint(1) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (uid),
|
||||||
|
KEY parent (pid),
|
||||||
|
KEY phpunit_dummy (is_dummy_record),
|
||||||
|
INDEX tx_bookmarkslikesratings_domain_model_stepconf_i1 (ratingobject, steporder)
|
||||||
|
);
|
||||||
|
|
||||||
|
#
|
||||||
|
# Table structure for table 'tx_bookmarkslikesratings_domain_model_stepname'
|
||||||
|
#
|
||||||
|
CREATE TABLE tx_bookmarkslikesratings_domain_model_stepname
|
||||||
|
(
|
||||||
|
uid int(11) unsigned DEFAULT '0' NOT NULL auto_increment,
|
||||||
|
pid int(11) DEFAULT '0' NOT NULL,
|
||||||
|
|
||||||
|
stepconf int(11) DEFAULT '0' NOT NULL,
|
||||||
|
stepname varchar(64) DEFAULT '' NOT NULL,
|
||||||
|
|
||||||
|
tstamp int(11) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
crdate int(11) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
cruser_id int(11) DEFAULT '0' NOT NULL,
|
||||||
|
t3_origuid int(11) DEFAULT '0' NOT NULL,
|
||||||
|
deleted tinyint(4) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
hidden tinyint(4) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
sys_language_uid int(11) DEFAULT '0' NOT NULL,
|
||||||
|
l18n_parent int(11) DEFAULT '0' NOT NULL,
|
||||||
|
l18n_diffsource mediumblob NOT NULL,
|
||||||
|
is_dummy_record tinyint(1) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (uid),
|
||||||
|
KEY parent (pid),
|
||||||
|
KEY phpunit_dummy (is_dummy_record),
|
||||||
|
);
|
||||||
|
|
||||||
|
#
|
||||||
|
# Table structure for table 'tx_bookmarkslikesratings_domain_model_rating'
|
||||||
|
#
|
||||||
|
CREATE TABLE tx_bookmarkslikesratings_domain_model_rating
|
||||||
|
(
|
||||||
|
uid int(11) unsigned DEFAULT '0' NOT NULL auto_increment,
|
||||||
|
pid int(11) DEFAULT '0' NOT NULL,
|
||||||
|
|
||||||
|
ratingobject int(11) DEFAULT '0' NOT NULL,
|
||||||
|
ratedobjectuid int(11) DEFAULT '0' NOT NULL,
|
||||||
|
votes int(11) DEFAULT '0' NOT NULL,
|
||||||
|
currentrates varchar(255) DEFAULT '0' NOT NULL,
|
||||||
|
|
||||||
|
tstamp int(11) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
crdate int(11) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
cruser_id int(11) DEFAULT '0' NOT NULL,
|
||||||
|
deleted tinyint(4) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
hidden tinyint(4) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
is_dummy_record tinyint(1) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (uid),
|
||||||
|
KEY parent (pid),
|
||||||
|
KEY phpunit_dummy (is_dummy_record),
|
||||||
|
INDEX tx_bookmarkslikesratings_domain_model_rating_i1 (ratingobject, ratedobjectuid)
|
||||||
|
);
|
||||||
|
|
||||||
|
#
|
||||||
|
# Table structure for table 'tx_bookmarkslikesratings_domain_model_vote'
|
||||||
|
#
|
||||||
|
CREATE TABLE tx_bookmarkslikesratings_domain_model_vote
|
||||||
|
(
|
||||||
|
uid int(11) unsigned DEFAULT '0' NOT NULL auto_increment,
|
||||||
|
pid int(11) DEFAULT '0' NOT NULL,
|
||||||
|
|
||||||
|
rating int(11) DEFAULT '0' NOT NULL,
|
||||||
|
voter int(11) DEFAULT '0' NOT NULL,
|
||||||
|
vote int(11) DEFAULT '0' NOT NULL,
|
||||||
|
|
||||||
|
tstamp int(11) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
crdate int(11) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
cruser_id int(11) DEFAULT '0' NOT NULL,
|
||||||
|
deleted tinyint(4) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
hidden tinyint(4) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
is_dummy_record tinyint(1) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (uid),
|
||||||
|
KEY parent (pid),
|
||||||
|
KEY phpunit_dummy (is_dummy_record),
|
||||||
|
INDEX tx_bookmarkslikesratings_domain_model_vote_i1 (rating, voter)
|
||||||
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user