first commit
This commit is contained in:
@@ -0,0 +1,240 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/announcement/Collector.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class Collector
|
||||
*
|
||||
* @brief A helper class to configure a Query Builder to get a collection of announcements
|
||||
*/
|
||||
|
||||
namespace PKP\announcement;
|
||||
|
||||
use APP\core\Application;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\LazyCollection;
|
||||
use PKP\core\Core;
|
||||
use PKP\core\interfaces\CollectorInterface;
|
||||
use PKP\plugins\Hook;
|
||||
|
||||
/**
|
||||
* @template T of Announcement
|
||||
*/
|
||||
class Collector implements CollectorInterface
|
||||
{
|
||||
public const ORDERBY_DATE_POSTED = 'date_posted';
|
||||
public const ORDERBY_DATE_EXPIRE = 'date_expire';
|
||||
public const ORDER_DIR_ASC = 'ASC';
|
||||
public const ORDER_DIR_DESC = 'DESC';
|
||||
public const SITE_ONLY = 'site';
|
||||
public const SITE_AND_CONTEXTS = 'all';
|
||||
|
||||
public DAO $dao;
|
||||
public ?array $contextIds = null;
|
||||
public ?string $isActive = null;
|
||||
public ?string $searchPhrase = null;
|
||||
public ?array $typeIds = null;
|
||||
public ?string $includeSite = null;
|
||||
public ?int $count = null;
|
||||
public ?int $offset = null;
|
||||
public string $orderBy = self::ORDERBY_DATE_POSTED;
|
||||
public string $orderDirection = self::ORDER_DIR_DESC;
|
||||
|
||||
public function __construct(DAO $dao)
|
||||
{
|
||||
$this->dao = $dao;
|
||||
}
|
||||
|
||||
/** @copydoc DAO::getCount() */
|
||||
public function getCount(): int
|
||||
{
|
||||
return $this->dao->getCount($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc DAO::getIds()
|
||||
*
|
||||
* @return Collection<int,int>
|
||||
*/
|
||||
public function getIds(): Collection
|
||||
{
|
||||
return $this->dao->getIds($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc DAO::getMany()
|
||||
*
|
||||
* @return LazyCollection<int,T>
|
||||
*/
|
||||
public function getMany(): LazyCollection
|
||||
{
|
||||
return $this->dao->getMany($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter announcements by one or more contexts
|
||||
*/
|
||||
public function filterByContextIds(?array $contextIds): self
|
||||
{
|
||||
$this->contextIds = $contextIds;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter announcements by those that have not expired
|
||||
*
|
||||
* @param string $date Optionally filter announcements by those
|
||||
* not expired until $date (YYYY-MM-DD).
|
||||
*/
|
||||
public function filterByActive(string $date = ''): self
|
||||
{
|
||||
$this->isActive = empty($date)
|
||||
? Core::getCurrentDate()
|
||||
: $date;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter announcements by one or more announcement types
|
||||
*/
|
||||
public function filterByTypeIds(array $typeIds): self
|
||||
{
|
||||
$this->typeIds = $typeIds;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include site-level announcements in the results
|
||||
*/
|
||||
public function withSiteAnnouncements(?string $includeMethod = self::SITE_AND_CONTEXTS): self
|
||||
{
|
||||
$this->includeSite = $includeMethod;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter announcements by those matching a search query
|
||||
*/
|
||||
public function searchPhrase(?string $phrase): self
|
||||
{
|
||||
$this->searchPhrase = $phrase;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the number of objects retrieved
|
||||
*/
|
||||
public function limit(?int $count): self
|
||||
{
|
||||
$this->count = $count;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Offset the number of objects retrieved, for example to
|
||||
* retrieve the second page of contents
|
||||
*/
|
||||
public function offset(?int $offset): self
|
||||
{
|
||||
$this->offset = $offset;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Order the results
|
||||
*
|
||||
* Results are ordered by the date posted by default.
|
||||
*
|
||||
* @param string $sorter One of the self::ORDERBY_ constants
|
||||
* @param string $direction One of the self::ORDER_DIR_ constants
|
||||
*/
|
||||
public function orderBy(?string $sorter, string $direction = self::ORDER_DIR_DESC): self
|
||||
{
|
||||
$this->orderBy = $sorter;
|
||||
$this->orderDirection = $direction;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc CollectorInterface::getQueryBuilder()
|
||||
*/
|
||||
public function getQueryBuilder(): Builder
|
||||
{
|
||||
$qb = DB::table($this->dao->table . ' as a')
|
||||
->select(['a.*']);
|
||||
|
||||
if (isset($this->contextIds) && $this->includeSite !== self::SITE_ONLY) {
|
||||
$qb->where('a.assoc_type', Application::get()->getContextAssocType());
|
||||
$qb->whereIn('a.assoc_id', $this->contextIds);
|
||||
if ($this->includeSite === self::SITE_AND_CONTEXTS) {
|
||||
$qb->orWhereNull('a.assoc_id');
|
||||
}
|
||||
} elseif ($this->includeSite === self::SITE_ONLY) {
|
||||
$qb->where('a.assoc_type', Application::get()->getContextAssocType());
|
||||
$qb->whereNull('a.assoc_id');
|
||||
}
|
||||
|
||||
if (isset($this->typeIds)) {
|
||||
$qb->whereIn('a.type_id', $this->typeIds);
|
||||
}
|
||||
|
||||
$qb->when($this->isActive, fn ($qb) => $qb->where(function ($qb) {
|
||||
$qb->where('a.date_expire', '>', $this->isActive)
|
||||
->orWhereNull('a.date_expire');
|
||||
}));
|
||||
|
||||
if ($this->searchPhrase !== null) {
|
||||
$words = explode(' ', $this->searchPhrase);
|
||||
if (count($words)) {
|
||||
$qb->whereIn('a.announcement_id', function ($query) use ($words) {
|
||||
$query->select('announcement_id')->from($this->dao->settingsTable);
|
||||
foreach ($words as $word) {
|
||||
$word = strtolower(addcslashes($word, '%_'));
|
||||
$query->where(function ($query) use ($word) {
|
||||
$query->where(function ($query) use ($word) {
|
||||
$query->where('setting_name', 'title');
|
||||
$query->where(DB::raw('lower(setting_value)'), 'LIKE', "%{$word}%");
|
||||
})
|
||||
->orWhere(function ($query) use ($word) {
|
||||
$query->where('setting_name', 'descriptionShort');
|
||||
$query->where(DB::raw('lower(setting_value)'), 'LIKE', "%{$word}%");
|
||||
})
|
||||
->orWhere(function ($query) use ($word) {
|
||||
$query->where('setting_name', 'description');
|
||||
$query->where(DB::raw('lower(setting_value)'), 'LIKE', "%{$word}%");
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$qb->orderByDesc('a.date_posted');
|
||||
|
||||
if (isset($this->count)) {
|
||||
$qb->limit($this->count);
|
||||
}
|
||||
|
||||
if (isset($this->offset)) {
|
||||
$qb->offset($this->offset);
|
||||
}
|
||||
|
||||
if (isset($this->orderBy)) {
|
||||
$qb->orderBy('a.' . $this->orderBy, $this->orderDirection);
|
||||
// Add a secondary sort by id to catch cases where two
|
||||
// announcements share the same date
|
||||
if (in_array($this->orderBy, [SELF::ORDERBY_DATE_EXPIRE, SELF::ORDERBY_DATE_POSTED])) {
|
||||
$qb->orderBy('a.announcement_id', $this->orderDirection);
|
||||
}
|
||||
}
|
||||
|
||||
Hook::call('Announcement::Collector', [&$qb, $this]);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user