Zwischenstand

This commit is contained in:
Sven Wappler 2021-08-20 13:33:13 +02:00
parent ce6b9e38dc
commit 508d3d2759
32 changed files with 2807 additions and 602 deletions

View File

@ -0,0 +1,41 @@
<?php
namespace WapplerSystems\BookmarksLikesRatings\Controller;
use TYPO3\CMS\Frontend\Exception;
use WapplerSystems\BookmarksLikesRatings\Domain\Repository\BookmarkRepository;
use WapplerSystems\BookmarksLikesRatings\Domain\Repository\LikeRepository;
class AbstractController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {
/** @var BookmarkRepository */
protected $bookmarkRepository;
/**
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Repository\BookmarkRepository $bookmarkRepository
*/
public function injectBookmarkRepository(BookmarkRepository $bookmarkRepository) {
$this->bookmarkRepository = $bookmarkRepository;
}
/** @var LikeRepository */
protected $likeRepository;
/**
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Repository\LikeRepository $bookmarkRepository
*/
public function injectLikeRepository(LikeRepository $likeRepository) {
$this->likeRepository = $likeRepository;
}
protected function getCurrentUser() : array {
if (!$GLOBALS['TSFE']->fe_user) {
throw new Exception('no access');
}
return $GLOBALS['TSFE']->fe_user->user;
}
}

View File

@ -0,0 +1,132 @@
<?php
namespace WapplerSystems\BookmarksLikesRatings\Controller;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Utility\DebugUtility;
use TYPO3\CMS\Extbase\Mvc\View\JsonView;
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Bookmark;
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Bookmarks;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Plugin controller
*/
class BookmarkController extends AbstractController
{
public function initializeStatusAction()
{
$this->defaultViewObjectName = JsonView::class;
}
/**
* @param int $objectUid
* @param string $tablename
* @throws \TYPO3\CMS\Frontend\Exception
*/
public function statusAction(int $objectUid,string $tablename) {
$user = $this->getCurrentUser();
$this->view->setVariablesToRender(['status']);
$this->view->assignMultiple([
'status' => ['status' => $this->bookmarkRepository->countByUserTablenameObjectUid($user['uid'],$tablename,$objectUid) === 0? 'false':'true']
]);
}
public function initializeToggleAction()
{
$this->defaultViewObjectName = JsonView::class;
}
/**
* @param int $objectUid
* @param string $tablename
* @throws \TYPO3\CMS\Frontend\Exception
*/
public function toggleAction(int $objectUid, string $tablename)
{
$user = $this->getCurrentUser();
$this->view->setVariablesToRender(['status']);
if ($this->bookmarkRepository->countByUserTablenameObjectUid($user['uid'], $tablename, $objectUid) === 0) {
$bookmark = new Bookmark();
$bookmark->setUser($user['uid']);
$bookmark->setTablename($tablename);
$bookmark->setObjectUid($objectUid);
$this->bookmarkRepository->add($bookmark);
$this->view->assignMultiple([
'status' => ['status' => 'true']
]);
} else {
$this->bookmarkRepository->removeByUserTablenameObjectUid($user['uid'], $tablename, $objectUid);
$this->view->assignMultiple([
'status' => ['status' => 'false']
]);
}
}
/**
* @param int $objectUid
* @param string $tablename
* @throws \TYPO3\CMS\Frontend\Exception
*/
public function deleteAction(int $objectUid, string $tablename)
{
$user = $this->getCurrentUser();
$this->bookmarkRepository->removeByUserTablenameObjectUid($user['uid'], $tablename, $objectUid);
$this->forward('personalList');
}
/**
*/
public function personalListAction()
{
$user = $this->getCurrentUser();
$bookmarks = [];
$objs = $this->bookmarkRepository->findByUser($user['uid']);
/** @var Bookmark $obj */
foreach ($objs as $obj) {
$bookmark = [];
$bookmark['tablename'] = $obj->getTablename();
$bookmark['object_uid'] = $obj->getObjectUid();
if ($obj->getTablename() === 'pages') {
$page = BackendUtility::getRecord('pages',$obj->getObjectUid(),'title');
if ($page) {
$bookmark['title'] = $page['title'];
$bookmark['url'] = $this->uriBuilder->reset()->setTargetPageUid($obj->getObjectUid())->buildFrontendUri();
}
$bookmarks[] = $bookmark;
}
}
$this->view->assignMultiple([
'bookmarks' => $bookmarks
]);
}
}

View File

@ -1,109 +0,0 @@
<?php
/*
* This file is part of the package buepro/bookmark_pages.
*
* For the full copyright and license information, please read the
* LICENSE file that was distributed with this source code.
*/
namespace WapplerSystems\BookmarksLikesRatings\Controller;
use WapplerSystems\BookmarksLikesRatings\Model\Bookmark;
use WapplerSystems\BookmarksLikesRatings\Model\Bookmarks;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
/**
* Plugin controller
*/
class BookmarksController extends ActionController
{
/**
* display bookmarks list
*/
public function indexAction()
{
$bookmark = Bookmark::createFromCurrent();
$this->view->assignMultiple([
'bookmark' => $bookmark->toArray()
]);
}
/**
* Adds the current page as bookmark and renders/returns updated list as html
*
* This is meant to be called by ajax (typoscript_rendering)
*
* @param array $localBookmarks
*/
public function bookmarkAction($localBookmarks = [])
{
// use the parameter directly and ignore chash because url is submitted by JS
$url = GeneralUtility::_GP('url');
$url = $url ? $url : null;
$bookmark = Bookmark::createFromCurrent($url);
$bookmarks = new Bookmarks();
$bookmarks->merge($localBookmarks);
$bookmarks->addBookmark($bookmark);
$bookmarks->persist();
$this->updateAndSendList($bookmarks);
}
/**
* Remove a bookmark from list and renders/returns updated list as html
*
* This is meant to be called by ajax (typoscript_rendering)
*
* @param string $id
* @param array $localBookmarks
*/
public function deleteAction($id = '', $localBookmarks = [])
{
$bookmarks = new Bookmarks();
$bookmarks->merge($localBookmarks);
if ($id) {
$bookmarks->removeBookmark($id);
$bookmarks->persist();
}
$this->updateAndSendList($bookmarks);
}
/**
* Action to get bookmark list
*
* @param array $localBookmarks
*/
public function listEntriesAction($localBookmarks = [])
{
$bookmarks = new Bookmarks();
$bookmarks->merge($localBookmarks);
$this->updateAndSendList($bookmarks);
}
/**
* This is for ajax requests
*
* @param Bookmarks $bookmarks
*/
public function updateAndSendList(Bookmarks $bookmarks)
{
// check if we bookmarked the current page
$bookmark = Bookmark::createFromCurrent();
$isBookmarked = $bookmarks->bookmarkExists($bookmark);
// build the ajax response data
$response = [
'isBookmarked' => $isBookmarked,
'bookmarks' => $bookmarks->getBookmarksForLocalStorage()
];
header('Content-Type: application/json');
echo json_encode($response);
die();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -10,13 +10,26 @@
namespace WapplerSystems\BookmarksLikesRatings\Domain\Model;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
/**
*
*/
class Bookmark
class Bookmark extends AbstractEntity
{
/** @var int */
protected $user;
/** @var string */
protected $tablename;
/** @var int */
protected $objectUid;
/**
* @var string
*/
@ -29,15 +42,64 @@ class Bookmark
* @var string
*/
protected $url;
/**
* @var int
*/
protected $pid;
/**
* @var string
*/
protected $parameter;
/**
* @return int
*/
public function getUser(): int
{
return $this->user;
}
/**
* @param int $user
*/
public function setUser(int $user): void
{
$this->user = $user;
}
/**
* @return string
*/
public function getTablename(): string
{
return $this->tablename;
}
/**
* @param string $tablename
*/
public function setTablename(string $tablename): void
{
$this->tablename = $tablename;
}
/**
* @return int
*/
public function getObjectUid(): int
{
return $this->objectUid;
}
/**
* @param int $objectUid
*/
public function setObjectUid(int $objectUid): void
{
$this->objectUid = $objectUid;
}
/**
* Bookmark constructor.
* Initialize the bookmark with data
@ -47,7 +109,7 @@ class Bookmark
* @param null $pid page id
* @param null $parameter
*/
public function __construct($url, $title = null, $pid = null, $parameter = null)
public function construct2($url, $title = null, $pid = null, $parameter = null)
{
if (is_array($url)) {
$this->id = $url['id'];
@ -169,22 +231,6 @@ class Bookmark
$this->url = $url;
}
/**
* @return int
*/
public function getPid()
{
return $this->pid;
}
/**
* @param int $pid
*/
public function setPid($pid)
{
$this->pid = $pid;
}
/**
* @return string
*/

View File

@ -0,0 +1,73 @@
<?php
namespace WapplerSystems\BookmarksLikesRatings\Domain\Model;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
/**
*
*/
class Like extends AbstractEntity
{
/** @var int */
protected $user;
/** @var string */
protected $tablename;
/** @var int */
protected $objectUid;
/**
* @return int
*/
public function getUser(): int
{
return $this->user;
}
/**
* @param int $user
*/
public function setUser(int $user): void
{
$this->user = $user;
}
/**
* @return string
*/
public function getTablename(): string
{
return $this->tablename;
}
/**
* @param string $tablename
*/
public function setTablename(string $tablename): void
{
$this->tablename = $tablename;
}
/**
* @return int
*/
public function getObjectUid(): int
{
return $this->objectUid;
}
/**
* @param int $objectUid
*/
public function setObjectUid(int $objectUid): void
{
$this->objectUid = $objectUid;
}
}

View File

@ -0,0 +1,130 @@
<?php
namespace WapplerSystems\BookmarksLikesRatings\Domain\Repository;
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating;
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote;
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Voter;
use TYPO3\CMS\Extbase\Persistence\Repository;
/**
*/
class BookmarkRepository extends Repository
{
public function countByUserTablenameObjectUid($userUid, $tablename, $objectUid)
{
$query = $this->createQuery();
return $query->matching(
$query->logicalAnd(
[
$query->equals('user', $userUid),
$query->equals('tablename', $tablename),
$query->equals('objectUid', $objectUid)
]
)
)->execute()->count();
}
public function removeByUserTablenameObjectUid($userUid, $tablename, $objectUid)
{
$query = $this->createQuery();
$objs = $query->matching(
$query->logicalAnd(
[
$query->equals('user', $userUid),
$query->equals('tablename', $tablename),
$query->equals('objectUid', $objectUid)
]
)
)->execute()->toArray();
foreach ($objs as $obj) {
$this->remove($obj);
}
}
/**
* Initialize this repository
*/
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 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;
}
}

View File

@ -0,0 +1,75 @@
<?php
namespace WapplerSystems\BookmarksLikesRatings\Domain\Repository;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\Utility\DebugUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating;
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote;
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Voter;
use TYPO3\CMS\Extbase\Persistence\Repository;
/**
*/
class LikeRepository extends Repository
{
public function countByUserTablenameObjectUid($userUid, $tablename, $objectUid)
{
$query = $this->createQuery();
return $query->matching(
$query->logicalAnd(
[
$query->equals('user', $userUid),
$query->equals('tablename', $tablename),
$query->equals('objectUid', $objectUid)
]
)
)->execute()->count();
}
public function removeByUserTablenameObjectUid($userUid, $tablename, $objectUid)
{
$query = $this->createQuery();
$objs = $query->matching(
$query->logicalAnd(
[
$query->equals('user', $userUid),
$query->equals('tablename', $tablename),
$query->equals('objectUid', $objectUid)
]
)
)->execute()->toArray();
foreach ($objs as $obj) {
$this->remove($obj);
}
}
public function getTop($limit)
{
/** @var QueryBuilder $queryBuilder */
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_bookmarkslikesratings_domain_model_like');
return $queryBuilder
->select('tablename')
->addSelect('object_uid')
->addSelectLiteral('count(*) as number')
->from('tx_bookmarkslikesratings_domain_model_like')
->groupBy('tablename')
->addGroupBy('object_uid')
->orderBy('number', 'DESC')
->setMaxResults($limit)
->execute()->fetchAll();
}
}

View 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 Bookmark2ViewHelper 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;
}
}

View File

@ -12,11 +12,13 @@ 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\Mvc\Web\Routing\UriBuilder;
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\TagBuilder;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
/**
@ -25,47 +27,21 @@ 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');
$this->registerArgument('table', 'string', 'The rating tablename');
$this->registerArgument('uid', 'integer', 'The uid of the object', true);
$this->registerArgument('class', 'string', 'The class', true);
$this->registerArgument('id', 'string', 'The id');
}
/**
@ -83,163 +59,29 @@ class BookmarkViewHelper extends AbstractViewHelper
\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();
$tagBuilder = new TagBuilder('button');
if ($arguments['id']) {
$tagBuilder->addAttribute('id',$arguments['id']);
}
$contentObjectRenderer->start([]);
$tagBuilder->addAttribute('class',$arguments['class']);
$tagBuilder->addAttribute('data-table',$arguments['table']);
$tagBuilder->addAttribute('data-uid',$arguments['uid']);
$tagBuilder->addAttribute('data-blr-type','bookmark');
$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, ]
);
/** @var UriBuilder $uriBuilder */
$uriBuilder = $renderingContext->getControllerContext()->getUriBuilder();
$uriBuilder->reset();
$uriBuilder->setTargetPageType(874655);
$tagBuilder->addAttribute('data-status-url',$uriBuilder->buildFrontendUri());
throw new \TYPO3Fluid\Fluid\Core\ViewHelper\Exception(
'TypoScript object path "' . $typoscriptObjectPath . '" does not exist',
1549388144
);
}
$setup = $setup[$segment . '.'];
}
$uriBuilder->reset();
$uriBuilder->setTargetPageType(874654);
$tagBuilder->addAttribute('data-toggle-url',$uriBuilder->buildFrontendUri());
if (!isset($setup[$lastSegment])) {
throw new \TYPO3Fluid\Fluid\Core\ViewHelper\Exception(
'No Content Object definition found at TypoScript object path "' . $typoscriptObjectPath . '"',
1549388123
);
}
$tagBuilder->setContent((string)$renderChildrenClosure());
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 $tagBuilder->render();
}
/**
* @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;
}
}

View File

@ -12,11 +12,13 @@ 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\Mvc\Web\Routing\UriBuilder;
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\TagBuilder;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
/**
@ -25,47 +27,21 @@ 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');
$this->registerArgument('table', 'string', 'The rating tablename');
$this->registerArgument('uid', 'integer', 'The uid of the object', true);
$this->registerArgument('class', 'string', 'The class', true);
$this->registerArgument('id', 'string', 'The id');
}
/**
@ -83,163 +59,31 @@ class LikeViewHelper extends AbstractViewHelper
\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();
$tagBuilder = new TagBuilder('button');
if ($arguments['id']) {
$tagBuilder->addAttribute('id',$arguments['id']);
}
$contentObjectRenderer->start([]);
$tagBuilder->addAttribute('class',$arguments['class']);
$tagBuilder->addAttribute('data-table',$arguments['table']);
$tagBuilder->addAttribute('data-uid',$arguments['uid']);
$tagBuilder->addAttribute('data-blr-type','like');
$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, ]
);
/** @var UriBuilder $uriBuilder */
$uriBuilder = $renderingContext->getControllerContext()->getUriBuilder();
$uriBuilder->reset();
$uriBuilder->setTargetPageType(874645);
$tagBuilder->addAttribute('data-status-url',$uriBuilder->buildFrontendUri());
throw new \TYPO3Fluid\Fluid\Core\ViewHelper\Exception(
'TypoScript object path "' . $typoscriptObjectPath . '" does not exist',
1549388144
);
}
$setup = $setup[$segment . '.'];
}
$uriBuilder->reset();
$uriBuilder->setTargetPageType(874644);
$tagBuilder->addAttribute('data-toggle-url',$uriBuilder->buildFrontendUri());
if (!isset($setup[$lastSegment])) {
throw new \TYPO3Fluid\Fluid\Core\ViewHelper\Exception(
'No Content Object definition found at TypoScript object path "' . $typoscriptObjectPath . '"',
1549388123
);
}
$tagBuilder->setContent((string)$renderChildrenClosure());
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 $tagBuilder->render();
}
/**
* @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;
}
}

View File

@ -5,34 +5,52 @@ 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;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Utility\DebugUtility;
use WapplerSystems\BookmarksLikesRatings\Domain\Repository\LikeRepository;
class TopLikesDataProvider implements ListDataProviderInterface
class TopLikesDataProvider
{
/** @var LikeRepository */
protected $likeRepository;
/**
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Repository\LikeRepository $bookmarkRepository
*/
public function injectLikeRepository(LikeRepository $likeRepository) {
$this->likeRepository = $likeRepository;
}
public function __construct()
{
}
public function getItems(): array
public function getItems()
{
/** @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();
$objs = $this->likeRepository->getTop(10);
$items = [];
foreach ($objs as $obj) {
$title = '';
if ($obj['tablename'] === 'pages') {
$page = BackendUtility::getRecord('pages',$obj['object_uid'],'title');
if ($page) {
$title = $page['title'];
}
}
$items[] = [
'title' => $title,
'number' => $obj['number']
];
}