first commit
This commit is contained in:
@@ -0,0 +1,346 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup announcement Announcement
|
||||
* Implements announcements that can be presented to website visitors.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file classes/announcement/Announcement.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 Announcement
|
||||
*
|
||||
* @ingroup announcement
|
||||
*
|
||||
* @see DAO
|
||||
*
|
||||
* @brief Basic class describing a announcement.
|
||||
*/
|
||||
|
||||
namespace PKP\announcement;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\facades\Repo;
|
||||
use APP\file\PublicFileManager;
|
||||
use PKP\db\DAORegistry;
|
||||
|
||||
class Announcement extends \PKP\core\DataObject
|
||||
{
|
||||
//
|
||||
// Get/set methods
|
||||
//
|
||||
/**
|
||||
* Get assoc ID for this announcement.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getAssocId()
|
||||
{
|
||||
return $this->getData('assocId');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set assoc ID for this announcement.
|
||||
*
|
||||
* @param int $assocId
|
||||
*/
|
||||
public function setAssocId($assocId)
|
||||
{
|
||||
$this->setData('assocId', $assocId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get assoc type for this announcement.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getAssocType()
|
||||
{
|
||||
return $this->getData('assocType');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set assoc type for this announcement.
|
||||
*
|
||||
* @param int $assocType
|
||||
*/
|
||||
public function setAssocType($assocType)
|
||||
{
|
||||
$this->setData('assocType', $assocType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the announcement type of the announcement.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTypeId()
|
||||
{
|
||||
return $this->getData('typeId');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the announcement type of the announcement.
|
||||
*
|
||||
* @param int $typeId
|
||||
*/
|
||||
public function setTypeId($typeId)
|
||||
{
|
||||
$this->setData('typeId', $typeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the announcement type name of the announcement.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getAnnouncementTypeName()
|
||||
{
|
||||
$announcementTypeDao = DAORegistry::getDAO('AnnouncementTypeDAO'); /** @var AnnouncementTypeDAO $announcementTypeDao */
|
||||
$announcementType = $announcementTypeDao->getById($this->getData('typeId'));
|
||||
return $announcementType ? $announcementType->getLocalizedTypeName() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get localized announcement title
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocalizedTitle()
|
||||
{
|
||||
return $this->getLocalizedData('title');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get full localized announcement title including type name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocalizedTitleFull()
|
||||
{
|
||||
$typeName = $this->getAnnouncementTypeName();
|
||||
if (!empty($typeName)) {
|
||||
return $typeName . ': ' . $this->getLocalizedTitle();
|
||||
} else {
|
||||
return $this->getLocalizedTitle();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get announcement title.
|
||||
*
|
||||
* @param string $locale
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle($locale)
|
||||
{
|
||||
return $this->getData('title', $locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set announcement title.
|
||||
*
|
||||
* @param string $title
|
||||
* @param string $locale
|
||||
*/
|
||||
public function setTitle($title, $locale)
|
||||
{
|
||||
$this->setData('title', $title, $locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get localized short description
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocalizedDescriptionShort()
|
||||
{
|
||||
return $this->getLocalizedData('descriptionShort');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get announcement brief description.
|
||||
*
|
||||
* @param string $locale
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDescriptionShort($locale)
|
||||
{
|
||||
return $this->getData('descriptionShort', $locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set announcement brief description.
|
||||
*
|
||||
* @param string $descriptionShort
|
||||
* @param string $locale
|
||||
*/
|
||||
public function setDescriptionShort($descriptionShort, $locale)
|
||||
{
|
||||
$this->setData('descriptionShort', $descriptionShort, $locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get localized full description
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocalizedDescription()
|
||||
{
|
||||
return $this->getLocalizedData('description');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get announcement description.
|
||||
*
|
||||
* @param string $locale
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription($locale)
|
||||
{
|
||||
return $this->getData('description', $locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set announcement description.
|
||||
*
|
||||
* @param string $description
|
||||
* @param string $locale
|
||||
*/
|
||||
public function setDescription($description, $locale)
|
||||
{
|
||||
$this->setData('description', $description, $locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get announcement expiration date.
|
||||
*
|
||||
* @return string (YYYY-MM-DD)
|
||||
*/
|
||||
public function getDateExpire()
|
||||
{
|
||||
return $this->getData('dateExpire');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set announcement expiration date.
|
||||
*
|
||||
* @param string $dateExpire (YYYY-MM-DD)
|
||||
*/
|
||||
public function setDateExpire($dateExpire)
|
||||
{
|
||||
$this->setData('dateExpire', $dateExpire);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get announcement posted date.
|
||||
*
|
||||
* @return string (YYYY-MM-DD)
|
||||
*/
|
||||
public function getDatePosted()
|
||||
{
|
||||
return date('Y-m-d', strtotime($this->getData('datePosted')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get announcement posted datetime.
|
||||
*
|
||||
* @return string (YYYY-MM-DD HH:MM:SS)
|
||||
*/
|
||||
public function getDatetimePosted()
|
||||
{
|
||||
return $this->getData('datePosted');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set announcement posted date.
|
||||
*
|
||||
* @param string $datePosted (YYYY-MM-DD)
|
||||
*/
|
||||
public function setDatePosted($datePosted)
|
||||
{
|
||||
$this->setData('datePosted', $datePosted);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set announcement posted datetime.
|
||||
*
|
||||
* @param string $datetimePosted (YYYY-MM-DD HH:MM:SS)
|
||||
*/
|
||||
public function setDatetimePosted($datetimePosted)
|
||||
{
|
||||
$this->setData('datePosted', $datetimePosted);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the featured image data
|
||||
*/
|
||||
public function getImage(): ?array
|
||||
{
|
||||
return $this->getData('image');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the featured image data
|
||||
*/
|
||||
public function setImage(array $image): void
|
||||
{
|
||||
$this->setData('image', $image);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full URL to the image
|
||||
*
|
||||
* @param bool $withTimestamp Pass true to include a query argument with a timestamp
|
||||
* of the date the image was uploaded in order to workaround cache bugs in browsers
|
||||
*/
|
||||
public function getImageUrl(bool $withTimestamp = true): string
|
||||
{
|
||||
$image = $this->getImage();
|
||||
|
||||
if (!$image) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$filename = $image['uploadName'];
|
||||
if ($withTimestamp) {
|
||||
$filename .= '?'. strtotime($image['dateUploaded']);
|
||||
}
|
||||
|
||||
$publicFileManager = new PublicFileManager();
|
||||
|
||||
return join('/', [
|
||||
Application::get()->getRequest()->getBaseUrl(),
|
||||
$this->getAssocId()
|
||||
? $publicFileManager->getContextFilesPath((int) $this->getAssocId())
|
||||
: $publicFileManager->getSiteFilesPath(),
|
||||
Repo::announcement()->getImageSubdirectory(),
|
||||
$filename
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the alt text for the image
|
||||
*/
|
||||
public function getImageAltText(): string
|
||||
{
|
||||
$image = $this->getImage();
|
||||
|
||||
if (!$image || !$image['altText']) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $image['altText'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\announcement\Announcement', '\Announcement');
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/announcement/AnnouncementType.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 AnnouncementType
|
||||
*
|
||||
* @ingroup announcement
|
||||
*
|
||||
* @see AnnouncementTypeDAO, AnnouncementTypeForm
|
||||
*
|
||||
* @brief Basic class describing an announcement type.
|
||||
*/
|
||||
|
||||
namespace PKP\announcement;
|
||||
|
||||
class AnnouncementType extends \PKP\core\DataObject
|
||||
{
|
||||
//
|
||||
// Get/set methods
|
||||
//
|
||||
/**
|
||||
* Get context ID for this announcement.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getContextId()
|
||||
{
|
||||
return $this->getData('contextId');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set context ID for this announcement.
|
||||
*
|
||||
* @param int $contextId
|
||||
*/
|
||||
public function setContextId($contextId)
|
||||
{
|
||||
$this->setData('contextId', $contextId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of the announcement type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocalizedTypeName()
|
||||
{
|
||||
return $this->getLocalizedData('name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of the announcement type.
|
||||
*
|
||||
* @param string $locale
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName($locale)
|
||||
{
|
||||
return $this->getData('name', $locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the type of the announcement type.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $locale
|
||||
*/
|
||||
public function setName($name, $locale)
|
||||
{
|
||||
$this->setData('name', $name, $locale);
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\announcement\AnnouncementType', '\AnnouncementType');
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/announcement/AnnouncementTypeDAO.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 AnnouncementTypeDAO
|
||||
*
|
||||
* @ingroup announcement
|
||||
*
|
||||
* @see AnnouncementType
|
||||
*
|
||||
* @brief Operations for retrieving and modifying AnnouncementType objects.
|
||||
*/
|
||||
|
||||
namespace PKP\announcement;
|
||||
|
||||
use APP\facades\Repo;
|
||||
|
||||
class AnnouncementTypeDAO extends \PKP\db\DAO
|
||||
{
|
||||
/**
|
||||
* Generate a new data object.
|
||||
*
|
||||
* @return AnnouncementType
|
||||
*/
|
||||
public function newDataObject()
|
||||
{
|
||||
return new AnnouncementType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an announcement type by announcement type ID.
|
||||
*
|
||||
* @param ?int $typeId Announcement type ID
|
||||
* @param ?int $contextId Optional context ID
|
||||
*
|
||||
* @return AnnouncementType
|
||||
*/
|
||||
public function getById($typeId, $contextId = null)
|
||||
{
|
||||
$params = [(int) $typeId];
|
||||
if ($contextId !== null) {
|
||||
$params[] = (int) $contextId;
|
||||
}
|
||||
$result = $this->retrieve(
|
||||
'SELECT * FROM announcement_types WHERE type_id = ?' .
|
||||
($contextId !== null ? ' AND context_id = ?' : ''),
|
||||
$params
|
||||
);
|
||||
$row = $result->current();
|
||||
return $row ? $this->_fromRow((array) $row) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the locale field names.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLocaleFieldNames()
|
||||
{
|
||||
return ['name'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal function to return an AnnouncementType object from a row.
|
||||
*
|
||||
* @param array $row
|
||||
*
|
||||
* @return AnnouncementType
|
||||
*/
|
||||
public function _fromRow($row)
|
||||
{
|
||||
$announcementType = $this->newDataObject();
|
||||
$announcementType->setId($row['type_id']);
|
||||
$announcementType->setData('contextId', $row['context_id']);
|
||||
$this->getDataObjectSettings('announcement_type_settings', 'type_id', $row['type_id'], $announcementType);
|
||||
|
||||
return $announcementType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the localized settings for this object
|
||||
*
|
||||
* @param AnnouncementType $announcementType
|
||||
*/
|
||||
public function updateLocaleFields($announcementType)
|
||||
{
|
||||
$this->updateDataObjectSettings(
|
||||
'announcement_type_settings',
|
||||
$announcementType,
|
||||
['type_id' => (int) $announcementType->getId()]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new AnnouncementType.
|
||||
*
|
||||
* @param AnnouncementType $announcementType
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function insertObject($announcementType)
|
||||
{
|
||||
$this->update(
|
||||
sprintf('INSERT INTO announcement_types
|
||||
(context_id)
|
||||
VALUES
|
||||
(?)'),
|
||||
[
|
||||
$announcementType->getContextId()
|
||||
? (int) $announcementType->getContextId()
|
||||
: null
|
||||
]
|
||||
);
|
||||
$announcementType->setId($this->getInsertId());
|
||||
$this->updateLocaleFields($announcementType);
|
||||
return $announcementType->getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing announcement type.
|
||||
*
|
||||
* @param AnnouncementType $announcementType
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function updateObject($announcementType)
|
||||
{
|
||||
$returner = $this->update(
|
||||
'UPDATE announcement_types
|
||||
SET context_id = ?
|
||||
WHERE type_id = ?',
|
||||
[
|
||||
$announcementType->getContextId(),
|
||||
(int) $announcementType->getId()
|
||||
]
|
||||
);
|
||||
|
||||
$this->updateLocaleFields($announcementType);
|
||||
return $returner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an announcement type. Note that all announcements with this type are also
|
||||
* deleted.
|
||||
*
|
||||
* @param AnnouncementType $announcementType
|
||||
*/
|
||||
public function deleteObject($announcementType)
|
||||
{
|
||||
return $this->deleteById($announcementType->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an announcement type by announcement type ID. Note that all announcements with
|
||||
* this type ID are also deleted.
|
||||
*
|
||||
* @param int $typeId
|
||||
*/
|
||||
public function deleteById($typeId)
|
||||
{
|
||||
$this->update('DELETE FROM announcement_type_settings WHERE type_id = ?', [(int) $typeId]);
|
||||
$this->update('DELETE FROM announcement_types WHERE type_id = ?', [(int) $typeId]);
|
||||
|
||||
$collector = Repo::announcement()->getCollector()->filterByTypeIds([(int) $typeId]);
|
||||
Repo::announcement()->deleteMany($collector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete announcement types by context ID.
|
||||
*
|
||||
* @param int $contextId
|
||||
*/
|
||||
public function deleteByContextId($contextId)
|
||||
{
|
||||
foreach ($this->getByContextId($contextId) as $type) {
|
||||
$this->deleteObject($type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an array of announcement types matching a particular context ID.
|
||||
*
|
||||
* @return \Generator<int,AnnouncementType> Matching AnnouncementTypes
|
||||
*/
|
||||
public function getByContextId(?int $contextId)
|
||||
{
|
||||
if ($contextId) {
|
||||
$result = $this->retrieve(
|
||||
'SELECT * FROM announcement_types WHERE context_id = ? ORDER BY type_id',
|
||||
[$contextId]
|
||||
);
|
||||
} else {
|
||||
$result = $this->retrieve(
|
||||
'SELECT * FROM announcement_types WHERE context_id IS NULL ORDER BY type_id'
|
||||
);
|
||||
}
|
||||
foreach ($result as $row) {
|
||||
yield $row->type_id => $this->_fromRow((array) $row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\announcement\AnnouncementTypeDAO', '\AnnouncementTypeDAO');
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/announcement/DAO.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 DAO
|
||||
*
|
||||
* @brief Read and write announcements to the database.
|
||||
*/
|
||||
|
||||
namespace PKP\announcement;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\LazyCollection;
|
||||
use PKP\core\EntityDAO;
|
||||
|
||||
/**
|
||||
* @template T of Announcement
|
||||
* @extends EntityDAO<T>
|
||||
*/
|
||||
class DAO extends EntityDAO
|
||||
{
|
||||
/** @copydoc EntityDAO::$schema */
|
||||
public $schema = \PKP\services\PKPSchemaService::SCHEMA_ANNOUNCEMENT;
|
||||
|
||||
/** @copydoc EntityDAO::$table */
|
||||
public $table = 'announcements';
|
||||
|
||||
/** @copydoc EntityDAO::$settingsTable */
|
||||
public $settingsTable = 'announcement_settings';
|
||||
|
||||
/** @copydoc EntityDAO::$primaryKeyColumn */
|
||||
public $primaryKeyColumn = 'announcement_id';
|
||||
|
||||
/** @copydoc EntityDAO::$primaryTableColumns */
|
||||
public $primaryTableColumns = [
|
||||
'id' => 'announcement_id',
|
||||
'assocId' => 'assoc_id',
|
||||
'assocType' => 'assoc_type',
|
||||
'typeId' => 'type_id',
|
||||
'dateExpire' => 'date_expire',
|
||||
'datePosted' => 'date_posted',
|
||||
];
|
||||
|
||||
/**
|
||||
* Instantiate a new DataObject
|
||||
*/
|
||||
public function newDataObject(): Announcement
|
||||
{
|
||||
return app(Announcement::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an announcement exists
|
||||
*/
|
||||
public function exists(int $id): bool
|
||||
{
|
||||
return DB::table($this->table)
|
||||
->where($this->primaryKeyColumn, '=', $id)
|
||||
->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an announcement
|
||||
*/
|
||||
public function get(int $id): ?Announcement
|
||||
{
|
||||
$row = DB::table($this->table)
|
||||
->where($this->primaryKeyColumn, $id)
|
||||
->first();
|
||||
return $row ? $this->fromRow($row) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of announcements matching the configured query
|
||||
*/
|
||||
public function getCount(Collector $query): int
|
||||
{
|
||||
return $query
|
||||
->getQueryBuilder()
|
||||
->get('a.' . $this->primaryKeyColumn)
|
||||
->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of ids matching the configured query
|
||||
*
|
||||
* @return Collection<int,int>
|
||||
*/
|
||||
public function getIds(Collector $query): Collection
|
||||
{
|
||||
return $query
|
||||
->getQueryBuilder()
|
||||
->pluck('a.' . $this->primaryKeyColumn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection of announcements matching the configured query
|
||||
*
|
||||
* @return LazyCollection<int,T>
|
||||
*/
|
||||
public function getMany(Collector $query): LazyCollection
|
||||
{
|
||||
$rows = $query
|
||||
->getQueryBuilder()
|
||||
->get();
|
||||
|
||||
return LazyCollection::make(function () use ($rows) {
|
||||
foreach ($rows as $row) {
|
||||
yield $row->announcement_id => $this->fromRow($row);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc EntityDAO::insert()
|
||||
*/
|
||||
public function insert(Announcement $announcement): int
|
||||
{
|
||||
return parent::_insert($announcement);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc EntityDAO::update()
|
||||
*/
|
||||
public function update(Announcement $announcement)
|
||||
{
|
||||
parent::_update($announcement);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc EntityDAO::delete()
|
||||
*/
|
||||
public function delete(Announcement $announcement)
|
||||
{
|
||||
parent::_delete($announcement);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,352 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/announcement/Repository.php
|
||||
*
|
||||
* Copyright (c) 2014-2020 Simon Fraser University
|
||||
* Copyright (c) 2000-2020 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class Repository
|
||||
*
|
||||
* @brief A repository to find and manage announcements.
|
||||
*/
|
||||
|
||||
namespace PKP\announcement;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\core\Request;
|
||||
use APP\file\PublicFileManager;
|
||||
use PKP\context\Context;
|
||||
use PKP\core\Core;
|
||||
use PKP\core\exceptions\StoreTemporaryFileException;
|
||||
use PKP\core\PKPString;
|
||||
use PKP\file\FileManager;
|
||||
use PKP\file\TemporaryFile;
|
||||
use PKP\file\TemporaryFileManager;
|
||||
use PKP\plugins\Hook;
|
||||
use PKP\services\PKPSchemaService;
|
||||
use PKP\user\User;
|
||||
use PKP\validation\ValidatorFactory;
|
||||
|
||||
class Repository
|
||||
{
|
||||
/** @var DAO $dao */
|
||||
public $dao;
|
||||
|
||||
/** @var string $schemaMap The name of the class to map this entity to its schema */
|
||||
public $schemaMap = maps\Schema::class;
|
||||
|
||||
/** @var Request $request */
|
||||
protected $request;
|
||||
|
||||
/** @var PKPSchemaService<Announcement> $schemaService */
|
||||
protected $schemaService;
|
||||
|
||||
|
||||
public function __construct(DAO $dao, Request $request, PKPSchemaService $schemaService)
|
||||
{
|
||||
$this->dao = $dao;
|
||||
$this->request = $request;
|
||||
$this->schemaService = $schemaService;
|
||||
}
|
||||
|
||||
/** @copydoc DAO::newDataObject() */
|
||||
public function newDataObject(array $params = []): Announcement
|
||||
{
|
||||
$object = $this->dao->newDataObject();
|
||||
if (!empty($params)) {
|
||||
$object->setAllData($params);
|
||||
}
|
||||
return $object;
|
||||
}
|
||||
|
||||
/** @copydoc DAO::get() */
|
||||
public function get(int $id): ?Announcement
|
||||
{
|
||||
return $this->dao->get($id);
|
||||
}
|
||||
|
||||
/** @copydoc DAO::exists() */
|
||||
public function exists(int $id): bool
|
||||
{
|
||||
return $this->dao->exists($id);
|
||||
}
|
||||
|
||||
/** @copydoc DAO::getCollector() */
|
||||
public function getCollector(): Collector
|
||||
{
|
||||
return app(Collector::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of the map class for mapping
|
||||
* announcements to their schema
|
||||
*/
|
||||
public function getSchemaMap(): maps\Schema
|
||||
{
|
||||
return app('maps')->withExtensions($this->schemaMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate properties for an announcement
|
||||
*
|
||||
* Perform validation checks on data used to add or edit an announcement.
|
||||
*
|
||||
* @param array $props A key/value array with the new data to validate
|
||||
* @param array $allowedLocales The context's supported locales
|
||||
* @param string $primaryLocale The context's primary locale
|
||||
*
|
||||
* @return array A key/value array with validation errors. Empty if no errors
|
||||
*/
|
||||
public function validate(?Announcement $object, array $props, array $allowedLocales, string $primaryLocale): array
|
||||
{
|
||||
$validator = ValidatorFactory::make(
|
||||
$props,
|
||||
$this->schemaService->getValidationRules($this->dao->schema, $allowedLocales),
|
||||
[
|
||||
'dateExpire.date_format' => __('stats.dateRange.invalidDate'),
|
||||
]
|
||||
);
|
||||
|
||||
// Check required fields
|
||||
ValidatorFactory::required(
|
||||
$validator,
|
||||
$object,
|
||||
$this->schemaService->getRequiredProps($this->dao->schema),
|
||||
$this->schemaService->getMultilingualProps($this->dao->schema),
|
||||
$allowedLocales,
|
||||
$primaryLocale
|
||||
);
|
||||
|
||||
// Check for input from disallowed locales
|
||||
ValidatorFactory::allowedLocales($validator, $this->schemaService->getMultilingualProps($this->dao->schema), $allowedLocales);
|
||||
|
||||
$errors = [];
|
||||
|
||||
if ($validator->fails()) {
|
||||
$errors = $this->schemaService->formatValidationErrors($validator->errors());
|
||||
}
|
||||
|
||||
Hook::call('Announcement::validate', [&$errors, $object, $props, $allowedLocales, $primaryLocale]);
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/** @copydoc DAO::insert() */
|
||||
public function add(Announcement $announcement): int
|
||||
{
|
||||
$announcement->setData('datePosted', Core::getCurrentDate());
|
||||
$id = $this->dao->insert($announcement);
|
||||
$announcement = $this->get($id);
|
||||
|
||||
if ($announcement->getImage()) {
|
||||
$this->handleImageUpload($announcement);
|
||||
}
|
||||
|
||||
Hook::call('Announcement::add', [$announcement]);
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an object in the database
|
||||
*
|
||||
* Deletes the old image if it has been removed, or a new image has
|
||||
* been uploaded.
|
||||
*/
|
||||
public function edit(Announcement $announcement, array $params)
|
||||
{
|
||||
$newAnnouncement = clone $announcement;
|
||||
$newAnnouncement->setAllData(array_merge($newAnnouncement->_data, $params));
|
||||
|
||||
Hook::call('Announcement::edit', [$newAnnouncement, $announcement, $params]);
|
||||
|
||||
$this->dao->update($newAnnouncement);
|
||||
|
||||
$image = $newAnnouncement->getImage();
|
||||
$hasNewImage = $image && $image['temporaryFileId'];
|
||||
|
||||
if ((!$image || $hasNewImage) && $announcement->getImage()) {
|
||||
$this->deleteImage($announcement);
|
||||
}
|
||||
|
||||
if ($hasNewImage) {
|
||||
$this->handleImageUpload($newAnnouncement);
|
||||
}
|
||||
}
|
||||
|
||||
/** @copydoc DAO::delete() */
|
||||
public function delete(Announcement $announcement)
|
||||
{
|
||||
Hook::call('Announcement::delete::before', [$announcement]);
|
||||
|
||||
if ($announcement->getImage()) {
|
||||
$this->deleteImage($announcement);
|
||||
}
|
||||
|
||||
$this->dao->delete($announcement);
|
||||
|
||||
Hook::call('Announcement::delete', [$announcement]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a collection of announcements
|
||||
*/
|
||||
public function deleteMany(Collector $collector)
|
||||
{
|
||||
foreach ($collector->getMany() as $announcement) {
|
||||
$this->delete($announcement);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The subdirectory where announcement images are stored
|
||||
*/
|
||||
public function getImageSubdirectory(): string
|
||||
{
|
||||
return 'announcements';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base URL for announcement file uploads
|
||||
*/
|
||||
public function getFileUploadBaseUrl(?Context $context = null): string
|
||||
{
|
||||
return join('/', [
|
||||
Application::get()->getRequest()->getPublicFilesUrl($context),
|
||||
$this->getImageSubdirectory(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle image uploads
|
||||
*
|
||||
* @throws StoreTemporaryFileException Unable to store temporary file upload
|
||||
*/
|
||||
protected function handleImageUpload(Announcement $announcement): void
|
||||
{
|
||||
$image = $announcement->getImage();
|
||||
if ($image && $image['temporaryFileId']) {
|
||||
$user = Application::get()->getRequest()->getUser();
|
||||
$image = $announcement->getImage();
|
||||
$temporaryFileManager = new TemporaryFileManager();
|
||||
$temporaryFile = $temporaryFileManager->getFile((int) $image['temporaryFileId'], $user?->getId());
|
||||
$filePath = $this->getImageSubdirectory() . '/' . $this->getImageFilename($announcement, $temporaryFile);
|
||||
if (!$this->isValidImage($temporaryFile, $filePath, $user, $announcement)) {
|
||||
throw new StoreTemporaryFileException($temporaryFile, $filePath, $user, $announcement);
|
||||
}
|
||||
if ($this->storeTemporaryFile($temporaryFile, $filePath, $user->getId(), $announcement)) {
|
||||
$announcement->setImage(
|
||||
$this->getImageData($announcement, $temporaryFile)
|
||||
);
|
||||
$this->dao->update($announcement);
|
||||
} else {
|
||||
$this->delete($announcement);
|
||||
throw new StoreTemporaryFileException($temporaryFile, $filePath, $user, $announcement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a temporary file upload in the public files directory
|
||||
*
|
||||
* @param string $newPath The new filename with the path relative to the public files directoruy
|
||||
* @return bool Whether or not the operation was successful
|
||||
*/
|
||||
protected function storeTemporaryFile(TemporaryFile $temporaryFile, string $newPath, int $userId, Announcement $announcement): bool
|
||||
{
|
||||
$publicFileManager = new PublicFileManager();
|
||||
$temporaryFileManager = new TemporaryFileManager();
|
||||
|
||||
if ($announcement->getAssocId()) {
|
||||
$result = $publicFileManager->copyContextFile(
|
||||
$announcement->getAssocId(),
|
||||
$temporaryFile->getFilePath(),
|
||||
$newPath
|
||||
);
|
||||
} else {
|
||||
$result = $publicFileManager->copySiteFile(
|
||||
$temporaryFile->getFilePath(),
|
||||
$newPath
|
||||
);
|
||||
}
|
||||
|
||||
if (!$result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$temporaryFileManager->deleteById($temporaryFile->getId(), $userId);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data array for a temporary file that has just been stored
|
||||
*
|
||||
* @return array Data about the image, like the upload name, alt text, and date uploaded
|
||||
*/
|
||||
protected function getImageData(Announcement $announcement, TemporaryFile $temporaryFile): array
|
||||
{
|
||||
$image = $announcement->getImage();
|
||||
|
||||
return [
|
||||
'name' => $temporaryFile->getOriginalFileName(),
|
||||
'uploadName' => $this->getImageFilename($announcement, $temporaryFile),
|
||||
'dateUploaded' => Core::getCurrentDate(),
|
||||
'altText' => !empty($image['altText']) ? $image['altText'] : '',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the filename of the image upload
|
||||
*/
|
||||
protected function getImageFilename(Announcement $announcement, TemporaryFile $temporaryFile): string
|
||||
{
|
||||
$fileManager = new FileManager();
|
||||
|
||||
return $announcement->getId()
|
||||
. $fileManager->getImageExtension($temporaryFile->getFileType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the image related to announcement
|
||||
*/
|
||||
protected function deleteImage(Announcement $announcement): void
|
||||
{
|
||||
$image = $announcement->getImage();
|
||||
if ($image && $image['uploadName']) {
|
||||
$publicFileManager = new PublicFileManager();
|
||||
$filesPath = $announcement->getAssocId()
|
||||
? $publicFileManager->getContextFilesPath($announcement->getAssocId())
|
||||
: $publicFileManager->getSiteFilesPath();
|
||||
|
||||
$publicFileManager->deleteByPath(
|
||||
join('/', [
|
||||
$filesPath,
|
||||
$this->getImageSubdirectory(),
|
||||
$image['uploadName'],
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that temporary file is an image
|
||||
*/
|
||||
protected function isValidImage(TemporaryFile $temporaryFile): bool
|
||||
{
|
||||
if (getimagesize($temporaryFile->getFilePath()) === false) {
|
||||
return false;
|
||||
}
|
||||
$extension = pathinfo($temporaryFile->getOriginalFileName(), PATHINFO_EXTENSION);
|
||||
$fileManager = new FileManager();
|
||||
$extensionFromMimeType = $fileManager->getImageExtension(
|
||||
PKPString::mime_content_type($temporaryFile->getFilePath())
|
||||
);
|
||||
if ($extensionFromMimeType !== '.' . $extension) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/announcement/maps/Schema.php
|
||||
*
|
||||
* Copyright (c) 2014-2020 Simon Fraser University
|
||||
* Copyright (c) 2000-2020 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class Schema
|
||||
*
|
||||
* @brief Map announcements to the properties defined in the announcement schema
|
||||
*/
|
||||
|
||||
namespace PKP\announcement\maps;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\core\Request;
|
||||
use Illuminate\Support\Enumerable;
|
||||
use PKP\announcement\Announcement;
|
||||
use PKP\core\PKPApplication;
|
||||
use PKP\services\PKPSchemaService;
|
||||
|
||||
class Schema extends \PKP\core\maps\Schema
|
||||
{
|
||||
public Enumerable $collection;
|
||||
|
||||
public string $schema = PKPSchemaService::SCHEMA_ANNOUNCEMENT;
|
||||
|
||||
/**
|
||||
* Map an announcement
|
||||
*
|
||||
* Includes all properties in the announcement schema.
|
||||
*/
|
||||
public function map(Announcement $item): array
|
||||
{
|
||||
return $this->mapByProperties($this->getProps(), $item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Summarize an announcement
|
||||
*
|
||||
* Includes properties with the apiSummary flag in the announcement schema.
|
||||
*/
|
||||
public function summarize(Announcement $item): array
|
||||
{
|
||||
return $this->mapByProperties($this->getSummaryProps(), $item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a collection of Announcements
|
||||
*
|
||||
* @see self::map
|
||||
*/
|
||||
public function mapMany(Enumerable $collection): Enumerable
|
||||
{
|
||||
$this->collection = $collection;
|
||||
return $collection->map(function ($item) {
|
||||
return $this->map($item);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Summarize a collection of Announcements
|
||||
*
|
||||
* @see self::summarize
|
||||
*/
|
||||
public function summarizeMany(Enumerable $collection): Enumerable
|
||||
{
|
||||
$this->collection = $collection;
|
||||
return $collection->map(function ($item) {
|
||||
return $this->summarize($item);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Map schema properties of an Announcement to an assoc array
|
||||
*/
|
||||
protected function mapByProperties(array $props, Announcement $item): array
|
||||
{
|
||||
$output = [];
|
||||
foreach ($props as $prop) {
|
||||
switch ($prop) {
|
||||
case '_href':
|
||||
$output[$prop] = $this->getApiUrl('announcements/' . $item->getId());
|
||||
break;
|
||||
case 'url':
|
||||
$output[$prop] = $this->request->getDispatcher()->url(
|
||||
$this->request,
|
||||
PKPApplication::ROUTE_PAGE,
|
||||
$this->getUrlPath(),
|
||||
'announcement',
|
||||
'view',
|
||||
$item->getId()
|
||||
);
|
||||
break;
|
||||
default:
|
||||
$output[$prop] = $item->getData($prop);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$output = $this->schemaService->addMissingMultilingualValues($this->schema, $output, $this->getSupportedLocales());
|
||||
|
||||
ksort($output);
|
||||
|
||||
return $this->withExtensions($output, $item);
|
||||
}
|
||||
|
||||
protected function getUrlPath(): string
|
||||
{
|
||||
if (isset($this->context)) {
|
||||
return $this->context->getData('urlPath');
|
||||
}
|
||||
return 'index';
|
||||
}
|
||||
|
||||
protected function getSupportedLocales(): array
|
||||
{
|
||||
if (isset($this->context)) {
|
||||
return $this->context->getSupportedFormLocales();
|
||||
}
|
||||
return Application::get()->getRequest()->getSite()->getSupportedLocales();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user