<?php
/*
* Copyright Blackbit digital Commerce GmbH <info@blackbit.de>
*
* 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 3 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
*/
namespace Blackbit\DataDirectorBundle\EventListener;
use Blackbit\DataDirectorBundle\lib\Pim\Helper;
use Blackbit\DataDirectorBundle\lib\Pim\Item\ItemMoldBuilder;
use Blackbit\DataDirectorBundle\model\Dataport;
use Blackbit\DataDirectorBundle\model\PimcoreDbRepository;
use Pimcore\Bundle\SimpleBackendSearchBundle\Model\Search\Backend\Data\Id;
use Pimcore\Db;
use Pimcore\Model\Asset;
use Pimcore\Model\DataObject\AbstractObject;
use Pimcore\Model\DataObject\ClassDefinition;
use Pimcore\Model\DataObject\ClassDefinition\Data;
use Pimcore\Model\DataObject\ClassDefinition\Listing;
use Pimcore\Model\DataObject\Concrete;
use Pimcore\Model\Document;
use Pimcore\Model\Element\ElementInterface;
use Pimcore\Model\Element\Service;
use Pimcore\Model\Listing\AbstractListing;
use Pimcore\Translation\Translator;
use Psr\Log\LoggerInterface;
class QuickSearchListener
{
public function loadByKeyFields($event) {
$db = \Pimcore\Db::get();
$query = $event->getArgument('query');
$searcherList = new \Pimcore\Bundle\SimpleBackendSearchBundle\Model\Search\Backend\Data\Listing();
$conditionParts = [];
$conditionParts[] = $this->getPermittedPaths();
$queryParts = preg_split('/(\s+|,|\.)/', $query);
foreach ($queryParts as &$queryPart) {
if (mb_substr($queryPart, 0, 1) !== '-' && strlen($queryPart) > 2) {
$queryPart = '+'.$queryPart;
}
}
unset($queryPart);
$matchCondition = 'MATCH (`data`,`properties`) AGAINST ('.$db->quote(implode(' ', $queryParts)).' IN BOOLEAN MODE)';
$conditionParts[] = $matchCondition." AND `type` != 'folder'";
$archiveFolders = [];
foreach(Dataport::getInstance()->find() as $dataport) {
if(!empty($dataport['sourceconfig']['archiveFolder'])) {
$archiveFolders[] = rtrim($dataport['sourceconfig']['archiveFolder'], '/').'/';
}
}
$assetArchiveFolders = PimcoreDbRepository::getInstance()->findColumnInSql('SELECT path FROM assets WHERE path IN (?)', [$archiveFolders]);
foreach($assetArchiveFolders as $assetArchiveFolder) {
$conditionParts[] = 'fullpath NOT LIKE '.$db->quote($assetArchiveFolder.'%');
}
$queryCondition = '('.implode(') AND (', array_unique($conditionParts)).')';
$searcherList->setCondition($queryCondition);
$searcherList->setLimit(50);
$searcherList->setOrderKey($matchCondition, false);
$searcherList->setOrder('DESC');
$event->setArgument('list', $searcherList);
}
protected function getPermittedPaths($types = ['asset', 'document', 'object'])
{
$user = Helper::getUser();
if($user->isAdmin()) {
return '1';
}
$db = \Pimcore\Db::get();
$allowedTypes = [];
foreach ($types as $type) {
if ($user->isAllowed($type.'s')) { //the permissions are just plural
$elementPaths = Service::findForbiddenPaths($type, $user);
$forbiddenPathSql = [];
$allowedPathSql = [];
foreach ($elementPaths['forbidden'] as $forbiddenPath => $allowedPaths) {
$exceptions = '';
$folderSuffix = '';
if ($allowedPaths) {
$exceptionsConcat = implode("%' OR fullpath LIKE '", $allowedPaths);
$exceptions = " OR (fullpath LIKE '".$exceptionsConcat."%')";
$folderSuffix = '/'; //if allowed children are found, the current folder is listable but its content is still blocked, can easily done by adding a trailing slash
}
$forbiddenPathSql[] = ' (fullpath NOT LIKE '.$db->quote($forbiddenPath.$folderSuffix.'%').$exceptions.') ';
}
foreach ($elementPaths['allowed'] as $allowedPaths) {
$allowedPathSql[] = ' fullpath LIKE '.$db->quote($allowedPaths.'%');
}
// this is to avoid query error when implode is empty.
// the result would be like `(maintype = type AND ((path1 OR path2) AND (not_path3 AND not_path4)))`
$forbiddenAndAllowedSql = '(maintype = \''.$type.'\'';
if ($allowedPathSql || $forbiddenPathSql) {
$forbiddenAndAllowedSql .= ' AND (';
$forbiddenAndAllowedSql .= $allowedPathSql ? '( '.implode(' OR ', $allowedPathSql).' )' : '';
if ($forbiddenPathSql) {
//if $allowedPathSql "implosion" is present, we need `AND` in between
$forbiddenAndAllowedSql .= $allowedPathSql ? ' AND ' : '';
$forbiddenAndAllowedSql .= implode(' AND ', $forbiddenPathSql);
}
$forbiddenAndAllowedSql .= ' )';
}
$forbiddenAndAllowedSql .= ' )';
$allowedTypes[] = $forbiddenAndAllowedSql;
}
}
//if allowedTypes is still empty after getting the workspaces, it means that there are no any main permissions set
// by setting a `false` condition in the query makes sure that nothing would be displayed.
if (!$allowedTypes) {
$allowedTypes = ['false'];
}
return '('.implode(' OR ', $allowedTypes).')';
}
}