<?php
/**
* Copyright (C) 2021 Rhyme Digital, LLC.
*
* @link https://rhyme.digital
* @license http://www.gnu.org/licenses/lgpl-3.0.html LGPL
*/
namespace Rhyme\WMassArtsHub\Module\Submission;
use Contao\StringUtil;
use Rhyme\WMassArtsHub\Model\Submission\CallsForArt;
use Rhyme\WMassArtsHub\Model\Submission\Funding;
use Rhyme\WMassArtsHub\Model\Submission\Profdev;
use Rhyme\WMassArtsHub\Model\Submission\Space;
use Contao\Date;
use Contao\Input;
use Contao\Config;
use Contao\Module;
use Contao\Environment;
use Contao\Pagination;
use Contao\Model\Collection;
use Contao\BackendTemplate;
use Contao\FrontendTemplate;
use Contao\CoreBundle\Exception\PageNotFoundException;
use Rhyme\WMassArtsHub\Model\Submission\SubmissionInterface;
use Rhyme\WMassArtsHub\Model\Submission\Venue;
/**
* Class CombinedLister
* @package Rhyme\WMassArtsHub\Module
*/
class CombinedLister extends Module
{
/**
* Current date object
* @var Date
*/
protected $Date;
/**
* Total items we have to work with after query
* @var integer
*/
protected $totalItems;
/**
* Template
* @var string
*/
protected $strTemplate = 'mod_artshub_submission_combinedlister';
/**
* Display a wildcard in the back end
*
* @return string
*/
public function generate()
{
if (TL_MODE == 'BE') {
$objTemplate = new BackendTemplate('be_wildcard');
$objTemplate->wildcard = '### ARTSHUB COMBINED SUBMISSIONLISTER ###';
$objTemplate->title = $this->headline;
$objTemplate->id = $this->id;
$objTemplate->link = $this->name;
$objTemplate->href = 'contao/main.php?do=themes&table=tl_module&act=edit&id=' . $this->id;
return $objTemplate->parse();
}
$strBuffer = parent::generate();
return empty($this->Template->items) ? '' : $strBuffer;
}
/**
* Generate the module
*/
protected function compile()
{
global $objPage;
// Set body class
$objPage->cssClass = $objPage->cssClass . (stripos($objPage->cssClass, 'hasLister') !== false ? '' : 'hasLister');
//Make sure we only grab ones we want
$arrElementTypes = StringUtil::deserialize($this->elementTypes);
$callsforartCollection = in_array(CallsForArt::getTable(), $arrElementTypes) ? CallsForArt::findAllPublished() : null;
$spaceCollection = in_array(Space::getTable(), $arrElementTypes) ? Space::findAllPublished() : null;
$fundingCollection = in_array(Funding::getTable(), $arrElementTypes) ? Funding::findAllPublished() : null;
$profDevCollection = in_array(Profdev::getTable(), $arrElementTypes) ? Profdev::findAllPublished() : null;
$venueCollection = in_array(Venue::getTable(), $arrElementTypes) ? Venue::findAllPublished() : null;
//Set up arrays for already listed items if they have not been
if(!$GLOBALS['COMBINEDLISTERITEMS'][CallsForArt::getTable()]) $GLOBALS['COMBINEDLISTERITEMS'][CallsForArt::getTable()] = array();
if(!$GLOBALS['COMBINEDLISTERITEMS'][Space::getTable()]) $GLOBALS['COMBINEDLISTERITEMS'][Space::getTable()] = array();
if(!$GLOBALS['COMBINEDLISTERITEMS'][Funding::getTable()]) $GLOBALS['COMBINEDLISTERITEMS'][Funding::getTable()] = array();
if(!$GLOBALS['COMBINEDLISTERITEMS'][Profdev::getTable()]) $GLOBALS['COMBINEDLISTERITEMS'][Profdev::getTable()] = array();
if(!$GLOBALS['COMBINEDLISTERITEMS'][Venue::getTable()]) $GLOBALS['COMBINEDLISTERITEMS'][Venue::getTable()] = array();
$sortedData = $this->sortModels($callsforartCollection, $spaceCollection, $fundingCollection, $profDevCollection, $venueCollection);
//Determine the number of events we need relative to everything else
$limit = $this->totalItems;
$offset = (int) $this->skipFirst;
// Maximum number of items
if ($this->numberOfItems > 0)
{
$limit = min($this->numberOfItems, $this->totalItems);
}
$total = $this->totalItems - $offset;
// Pagination
if ($this->perPage > 0 && (!isset($limit) || $this->numberOfItems > $this->perPage))
{
// Adjust the overall limit
if (isset($limit))
{
$total = min($limit, $total);
}
$id = 'page_e' . $this->id;
$page = Input::get($id) ?? 1;
// Do not index or cache the page if the page number is outside the range
if ($page < 1 || $page > max(ceil($total/$this->perPage), 1))
{
throw new PageNotFoundException('Page not found: ' . Environment::get('uri'));
}
// Set limit and offset
$limit = $this->perPage;
$offset += (max($page, 1) - 1) * $this->perPage;
$skip = (int) $this->skipFirst;
// Overall limit
if ($offset + $limit > $total + $skip)
{
$limit = $total + $skip - $offset;
}
$objPagination = new Pagination($total, $this->perPage, Config::get('maxPaginationLinks'), $id);
$this->Template->pagination = $objPagination->generate("\n ");
}
$arrParsedItems = array();
// Parse items
for ($i=$offset; $i<($limit + $offset); $i++)
{
/** @var CallsForArt|Space|Funding|Profdev|null $model */
$model = $sortedData[$i];
if(null !== $model) {
$arrParsedItems[] = array('model' => $model, 'content' => $model->generate($this));
$GLOBALS['COMBINEDLISTERITEMS'][$model::getTable()][] = $model->id;
}
}
$this->Template->items = $arrParsedItems;
$this->Template->emptyMsg = $GLOBALS['TL_LANG']['ARTSHUB_SUBMISSIONLISTER']['empty'];
// Add modal
$objModalTpl = new FrontendTemplate('modal_artshub_combinedlister');
$GLOBALS['TL_BODY']['modal_artshub_combinedlister'] = $objModalTpl->parse();
// Add scripts
$GLOBALS['TL_JAVASCRIPT']['combinedListerModal'] = 'web/bundles/rhymewmassartshub/assets/js/frontend/combinedLister/modal.js|static';
}
/**
* Sort out the model collection data into arrays
*
* @param Collection|null $callsforartCollection
* @param Collection|null $spaceCollection
* @param Collection|null $fundingCollection
* @param Collection|null $profDevCollection
* @param Collection|null $venueCollection
* @return array $sortedModels
*/
protected function sortModels($callsforartCollection, $spaceCollection, $fundingCollection, $profDevCollection, $venueCollection)
{
$arrCollections = array($callsforartCollection, $spaceCollection, $fundingCollection, $profDevCollection, $venueCollection);
if($this->artshub_sorting === 'title') {
return $this->sortByTitle($arrCollections);
}
return $this->sortByDateSubmitted($arrCollections);
}
/**
* Default sorting - by date submitted
*
* @param array $arrCollections
* @return array $returnArray
*/
protected function sortByDateSubmitted($arrCollections){
$sortedModels = array(
CallsForArt::getTable() => array(),
Space::getTable() => array(),
Funding::getTable() => array(),
Profdev::getTable() => array(),
Venue::getTable() => array(),
);
$totalAllItems = 0;
foreach($arrCollections as $index=>$collection) {
if (null !== $collection) {
while ($collection->next()) {
$t = $collection->current()::getTable();
if (!in_array($collection->current()->id, $GLOBALS['COMBINEDLISTERITEMS'][$t])) {
/** @var SubmissionInterface $collection ->current() */
$sortedModels[$t][$collection->current()->getDateSubmitted()][] = $collection->current();
$totalAllItems++;
}
}
}
}
//Sort items low to high
ksort( $sortedModels[CallsForArt::getTable()]);
ksort( $sortedModels[Space::getTable()]);
ksort( $sortedModels[Funding::getTable()]);
ksort( $sortedModels[Profdev::getTable()]);
ksort( $sortedModels[Venue::getTable()]);
$sortedData = array();
//Get all items we want with dayStart as key (need to do this b/c of different date sorts)
foreach($sortedModels as $table => $dateGroup) {
foreach($dateGroup as $date => $modelArrays) {
foreach($modelArrays as $model) {
/** @var SubmissionInterface $model */
$t = $model::getTable();
$day = new Date($date);
$sortedData[$day->dayBegin][] = $model;
}
}
}
//Reverse sort for chronological
krsort($sortedData);
$this->totalItems = 0;
//Loop and return simple sorted array
$returnArray = array();
foreach($sortedData as $date => $modelGroup) {
foreach($modelGroup as $model) {
$this->totalItems++;
$returnArray[] = $model;
}
}
return $returnArray;
}
/**
* Default sorting - by date submitted
*
* @param array $arrCollections
* @return array $returnArray
*/
protected function sortByTitle($arrCollections){
$sortedModels = array(
CallsForArt::getTable() => array(),
Space::getTable() => array(),
Funding::getTable() => array(),
Profdev::getTable() => array(),
Venue::getTable() => array(),
);
$totalAllItems = 0;
foreach($arrCollections as $index=>$collection) {
if (null !== $collection) {
while ($collection->next()) {
$t = $collection->current()::getTable();
if (!in_array($collection->current()->id, $GLOBALS['COMBINEDLISTERITEMS'][$t])) {
/** @var SubmissionInterface $collection ->current() */
$sortedModels[$t][$collection->current()->getTitle()][] = $collection->current();
$totalAllItems++;
}
}
}
}
//Sort items low to high
ksort( $sortedModels[CallsForArt::getTable()]);
ksort( $sortedModels[Space::getTable()]);
ksort( $sortedModels[Funding::getTable()]);
ksort( $sortedModels[Profdev::getTable()]);
ksort( $sortedModels[Venue::getTable()]);
$sortedData = array();
//I know that we are looping a couple times when we probably don't need to
//But trying to also account for if they want a limit on certain things, etc, like we did with Noho
foreach($sortedModels as $table => $dateGroup) {
foreach($dateGroup as $title => $modelArrays) {
foreach($modelArrays as $model) {
/** @var SubmissionInterface $model */
$t = $model::getTable();
$sortedData[$model->getTitle()][] = $model;
}
}
}
//Sort titles
ksort($sortedData);
$this->totalItems = 0;
//Loop and return simple sorted array
$returnArray = array();
foreach($sortedData as $title => $modelGroup) {
foreach($modelGroup as $model) {
$this->totalItems++;
$returnArray[] = $model;
}
}
return $returnArray;
}
}