summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/ModernTimeline/src
diff options
context:
space:
mode:
authorYaco <franco@reevo.org>2020-06-04 11:01:00 -0300
committerYaco <franco@reevo.org>2020-06-04 11:01:00 -0300
commitfc7369835258467bf97eb64f184b93691f9a9fd5 (patch)
treedaabd60089d2dd76d9f5fb416b005fbe159c799d /www/wiki/extensions/ModernTimeline/src
first commit
Diffstat (limited to 'www/wiki/extensions/ModernTimeline/src')
-rw-r--r--www/wiki/extensions/ModernTimeline/src/Event.php34
-rw-r--r--www/wiki/extensions/ModernTimeline/src/JsonBuilder.php122
-rw-r--r--www/wiki/extensions/ModernTimeline/src/ModernTimelinePrinter.php59
-rw-r--r--www/wiki/extensions/ModernTimeline/src/ModernTimelineSetup.php30
-rw-r--r--www/wiki/extensions/ModernTimeline/src/ResultFacade/PropertyValueCollection.php35
-rw-r--r--www/wiki/extensions/ModernTimeline/src/ResultFacade/ResultSimplifier.php57
-rw-r--r--www/wiki/extensions/ModernTimeline/src/ResultFacade/Subject.php39
-rw-r--r--www/wiki/extensions/ModernTimeline/src/ResultFacade/SubjectCollection.php23
-rw-r--r--www/wiki/extensions/ModernTimeline/src/SlidePresenter/SimpleSlidePresenter.php40
-rw-r--r--www/wiki/extensions/ModernTimeline/src/SlidePresenter/SlidePresenter.php13
-rw-r--r--www/wiki/extensions/ModernTimeline/src/SlidePresenter/TemplateSlidePresenter.php60
-rw-r--r--www/wiki/extensions/ModernTimeline/src/TimelineOptions.php143
-rw-r--r--www/wiki/extensions/ModernTimeline/src/TimelinePresenter.php105
13 files changed, 760 insertions, 0 deletions
diff --git a/www/wiki/extensions/ModernTimeline/src/Event.php b/www/wiki/extensions/ModernTimeline/src/Event.php
new file mode 100644
index 00000000..821e5810
--- /dev/null
+++ b/www/wiki/extensions/ModernTimeline/src/Event.php
@@ -0,0 +1,34 @@
+<?php
+
+declare( strict_types = 1 );
+
+namespace ModernTimeline;
+
+use ModernTimeline\ResultFacade\Subject;
+use SMWDITime;
+
+class Event {
+
+ private $subject;
+ private $startDate;
+ private $endDate;
+
+ public function __construct( Subject $subject, SMWDITime $startDate, ?SMWDITime $endDate ) {
+ $this->subject = $subject;
+ $this->startDate = $startDate;
+ $this->endDate = $endDate;
+ }
+
+ public function getSubject(): Subject {
+ return $this->subject;
+ }
+
+ public function getStartDate(): SMWDITime {
+ return $this->startDate;
+ }
+
+ public function getEndDate(): ?SMWDITime {
+ return $this->endDate;
+ }
+
+}
diff --git a/www/wiki/extensions/ModernTimeline/src/JsonBuilder.php b/www/wiki/extensions/ModernTimeline/src/JsonBuilder.php
new file mode 100644
index 00000000..2f727df1
--- /dev/null
+++ b/www/wiki/extensions/ModernTimeline/src/JsonBuilder.php
@@ -0,0 +1,122 @@
+<?php
+
+declare( strict_types = 1 );
+
+namespace ModernTimeline;
+
+use ModernTimeline\ResultFacade\PropertyValueCollection;
+use ModernTimeline\ResultFacade\Subject;
+use ModernTimeline\ResultFacade\SubjectCollection;
+use ModernTimeline\SlidePresenter\SlidePresenter;
+use SMWDITime;
+
+class JsonBuilder {
+
+ private $slidePresenter;
+
+ public function __construct( SlidePresenter $slidePresenter ) {
+ $this->slidePresenter = $slidePresenter;
+ }
+
+ public function buildTimelineJson( SubjectCollection $pages ): array {
+ $events = [];
+
+ foreach ( $pages->getSubjects() as $subject ) {
+ [ $startDate, $endDate ] = $this->getDates( $subject );
+
+ if ( $startDate !== null ) {
+ $events[] = new Event( $subject, $startDate, $endDate );
+ }
+ }
+
+ return $this->eventsToTimelineJson( $events );
+ }
+
+ private function getDates( Subject $subject ): array {
+ $startDate = null;
+ $endDate = null;
+
+ foreach ( $this->getPropertyValueCollectionsWithDates( $subject ) as $propertyValues ) {
+ $dataItem = $propertyValues->getDataItems()[0];
+
+ if ( $dataItem instanceof SMWDITime ) {
+ if ( $startDate === null ) {
+ $startDate = $dataItem;
+ }
+ else if ( $endDate === null ) {
+ $endDate = $dataItem;
+ }
+ else {
+ break;
+ }
+ }
+ }
+
+ return [ $startDate, $endDate ];
+ }
+
+ /**
+ * @param Event[] $events
+ * @return array
+ */
+ public function eventsToTimelineJson( array $events ): array {
+ $jsonEvents = [];
+
+ foreach ( $events as $event ) {
+ $jsonEvents[] = $this->buildEvent( $event );
+ }
+
+ return [ 'events' => $jsonEvents ];
+ }
+
+ private function buildEvent( Event $event ): array {
+ $jsonEvent = [
+ 'text' => [
+ 'headline' => $this->newHeadline( $event->getSubject()->getWikiPage()->getTitle() ),
+ 'text' => $this->slidePresenter->getText( $event->getSubject() )
+ ],
+ 'start_date' => $this->timeToJson( $event->getStartDate() )
+ ];
+
+ if ( $event->getEndDate() !== null ) {
+ $jsonEvent['end_date'] = $this->timeToJson( $event->getEndDate() );
+ }
+
+ return $jsonEvent;
+ }
+
+ /**
+ * @return PropertyValueCollection[]
+ */
+ private function getPropertyValueCollectionsWithDates( Subject $subject ) {
+ return array_filter(
+ $subject->getPropertyValueCollections(),
+ function( PropertyValueCollection $pvc ) {
+ return $pvc->getPrintRequest()->getTypeID() === '_dat'
+ && $pvc->getDataItems() !== [];
+ }
+ );
+ }
+
+ private function newHeadline( \Title $title ): string {
+ return \Html::element(
+ 'a',
+ [ 'href' => $title->getFullURL() ],
+ $title->getText()
+ );
+
+// return DataValueFactory::getInstance()->newDataValueByItem( $subject->getWikiPage() )->getLongHTMLText( smwfGetLinker() );
+ }
+
+ private function timeToJson( SMWDITime $time ): array {
+ return [
+ 'year' => $time->getYear(),
+ 'month' => $time->getMonth(),
+ 'day' => $time->getDay(),
+ 'hour' => $time->getHour(),
+ 'minute' => $time->getMinute(),
+ 'second' => (int)$time->getSecond(),
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/ModernTimeline/src/ModernTimelinePrinter.php b/www/wiki/extensions/ModernTimeline/src/ModernTimelinePrinter.php
new file mode 100644
index 00000000..51d8d6dc
--- /dev/null
+++ b/www/wiki/extensions/ModernTimeline/src/ModernTimelinePrinter.php
@@ -0,0 +1,59 @@
+<?php
+
+declare( strict_types = 1 );
+
+namespace ModernTimeline;
+
+use ParamProcessor\ProcessedParam;
+use SMW\Parser\RecursiveTextProcessor;
+use SMW\Query\ResultPrinter;
+use SMWQuery;
+use SMWQueryResult;
+
+class ModernTimelinePrinter implements ResultPrinter {
+
+ public function getName(): string {
+ return wfMessage( 'modern-timeline-format-name' )->text();
+ }
+
+ public function getParamDefinitions( array $definitions ) {
+ return array_merge( $definitions, TimelineOptions::getTimelineParameterDefinitions() );
+ }
+
+ /**
+ * @param SMWQueryResult $result
+ * @param ProcessedParam[] $parameters Note: currently getting Param[] from SMW but lets pretend the legacy refactor happened already
+ * @param int $outputMode
+ *
+ * @return string
+ */
+ public function getResult( SMWQueryResult $result, array $parameters, $outputMode ): string {
+ return ( new TimelinePresenter( $parameters ) )->getResult( $result );
+ }
+
+ public function getQueryMode( $context ): int {
+ return SMWQuery::MODE_INSTANCES;
+ }
+
+ public function setShowErrors( $show ) {
+ }
+
+ public function isExportFormat(): bool {
+ return false;
+ }
+
+ public function getDefaultSort(): string {
+ return 'ASC';
+ }
+
+ public function isDeferrable(): bool {
+ return false;
+ }
+
+ public function supportsRecursiveAnnotation(): bool {
+ return false;
+ }
+
+ public function setRecursiveTextProcessor( RecursiveTextProcessor $recursiveTextProcessor ) {
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/ModernTimeline/src/ModernTimelineSetup.php b/www/wiki/extensions/ModernTimeline/src/ModernTimelineSetup.php
new file mode 100644
index 00000000..f2853953
--- /dev/null
+++ b/www/wiki/extensions/ModernTimeline/src/ModernTimelineSetup.php
@@ -0,0 +1,30 @@
+<?php
+
+declare( strict_types = 1 );
+
+namespace ModernTimeline;
+
+class ModernTimelineSetup {
+
+ public static function onExtensionFunction() {
+ self::doSmwCheck();
+
+ $GLOBALS['smwgResultFormats']['moderntimeline'] = ModernTimelinePrinter::class;
+ }
+
+ private static function doSmwCheck() {
+ if ( !defined( 'SMW_VERSION' ) ) {
+
+ if ( PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' ) {
+ die( "\nThe 'Modern Timeline' extension requires 'Semantic MediaWiki' to be installed and enabled.\n" );
+ }
+
+ die(
+ '<b>Error:</b> The <a href="https://github.com/ProfessionalWiki/ModernTimeline">Modern Timeline</a> ' .
+ 'extension requires <a href="https://www.semantic-mediawiki.org/wiki/Semantic_MediaWiki">Semantic MediaWiki</a> to be ' .
+ 'installed and enabled.<br />'
+ );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/ModernTimeline/src/ResultFacade/PropertyValueCollection.php b/www/wiki/extensions/ModernTimeline/src/ResultFacade/PropertyValueCollection.php
new file mode 100644
index 00000000..d70d7e92
--- /dev/null
+++ b/www/wiki/extensions/ModernTimeline/src/ResultFacade/PropertyValueCollection.php
@@ -0,0 +1,35 @@
+<?php
+
+declare( strict_types = 1 );
+
+namespace ModernTimeline\ResultFacade;
+
+use SMW\Query\PrintRequest;
+use SMWDataItem;
+
+class PropertyValueCollection {
+
+ private $printRequest;
+ private $dataItems;
+
+ /**
+ * @param PrintRequest $printRequest
+ * @param SMWDataItem[] $dataItems
+ */
+ public function __construct( PrintRequest $printRequest, array $dataItems ) {
+ $this->printRequest = $printRequest;
+ $this->dataItems = $dataItems;
+ }
+
+ public function getPrintRequest(): PrintRequest {
+ return $this->printRequest;
+ }
+
+ /**
+ * @return SMWDataItem[]
+ */
+ public function getDataItems(): array {
+ return $this->dataItems;
+ }
+
+}
diff --git a/www/wiki/extensions/ModernTimeline/src/ResultFacade/ResultSimplifier.php b/www/wiki/extensions/ModernTimeline/src/ResultFacade/ResultSimplifier.php
new file mode 100644
index 00000000..1c58345a
--- /dev/null
+++ b/www/wiki/extensions/ModernTimeline/src/ResultFacade/ResultSimplifier.php
@@ -0,0 +1,57 @@
+<?php
+
+declare( strict_types = 1 );
+
+namespace ModernTimeline\ResultFacade;
+
+use SMW\DIWikiPage;
+use SMW\Query\PrintRequest;
+use SMWQueryResult;
+
+class ResultSimplifier {
+
+ public function newSubjectCollection( SMWQueryResult $result ): SubjectCollection {
+ $subjects = [];
+
+ foreach ( $result->getResults() as $diWikiPage ) {
+ $subjects[] = $this->newSubject( $diWikiPage, $result->getPrintRequests(), $result );
+ }
+
+ return new SubjectCollection( $subjects );
+ }
+
+ /**
+ * @param DIWikiPage $resultPage
+ * @param PrintRequest[] $printRequests
+ * @param SMWQueryResult $result
+ * @return Subject
+ */
+ private function newSubject( DIWikiPage $resultPage, array $printRequests, SMWQueryResult $result ): Subject {
+ $propertyValueCollections = [];
+
+ foreach ( $printRequests as $printRequest ) {
+ $dataItems = $this->newResultArray( $resultPage, $printRequest, $result )->getContent();
+
+ $propertyValueCollections[] = new PropertyValueCollection(
+ $printRequest,
+ $dataItems === false ? [] : $dataItems
+ );
+ }
+
+ return new Subject( $resultPage, $propertyValueCollections );
+ }
+
+ /**
+ * Compat with SMW 3.0
+ * In 3.1+ do: ResultArray::factory( $resultPage, $printRequest, $result )
+ */
+ private function newResultArray( DIWikiPage $resultPage, PrintRequest $printRequest, SMWQueryResult $result ): \SMWResultArray {
+ return new \SMWResultArray(
+ $resultPage,
+ $printRequest,
+ $result->getStore(),
+ method_exists( $result, 'getFieldItemFinder' ) ? $result->getFieldItemFinder() : null
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/ModernTimeline/src/ResultFacade/Subject.php b/www/wiki/extensions/ModernTimeline/src/ResultFacade/Subject.php
new file mode 100644
index 00000000..2d67bcda
--- /dev/null
+++ b/www/wiki/extensions/ModernTimeline/src/ResultFacade/Subject.php
@@ -0,0 +1,39 @@
+<?php
+
+declare( strict_types = 1 );
+
+namespace ModernTimeline\ResultFacade;
+
+use SMW\DIWikiPage;
+
+/**
+ * Data from a single subject (page or subobject)
+ */
+class Subject {
+
+ private $wikiPage;
+ private $propertyValueCollections;
+
+ /**
+ * @param DIWikiPage $wikiPage
+ * @param PropertyValueCollection[] $propertyValueCollections
+ */
+ public function __construct( DIWikiPage $wikiPage, array $propertyValueCollections ) {
+ $this->wikiPage = $wikiPage;
+ $this->propertyValueCollections = $propertyValueCollections;
+ }
+
+ public function getWikiPage(): DIWikiPage {
+ return $this->wikiPage;
+ }
+
+ /**
+ * @return PropertyValueCollection[]
+ */
+ public function getPropertyValueCollections(): array {
+ return $this->propertyValueCollections;
+ }
+
+
+
+} \ No newline at end of file
diff --git a/www/wiki/extensions/ModernTimeline/src/ResultFacade/SubjectCollection.php b/www/wiki/extensions/ModernTimeline/src/ResultFacade/SubjectCollection.php
new file mode 100644
index 00000000..77b31123
--- /dev/null
+++ b/www/wiki/extensions/ModernTimeline/src/ResultFacade/SubjectCollection.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace ModernTimeline\ResultFacade;
+
+class SubjectCollection {
+
+ private $pages;
+
+ /**
+ * @param Subject[] $pages
+ */
+ public function __construct( array $pages ) {
+ $this->pages = $pages;
+ }
+
+ /**
+ * @return Subject[]
+ */
+ public function getSubjects(): iterable {
+ return $this->pages;
+ }
+
+}
diff --git a/www/wiki/extensions/ModernTimeline/src/SlidePresenter/SimpleSlidePresenter.php b/www/wiki/extensions/ModernTimeline/src/SlidePresenter/SimpleSlidePresenter.php
new file mode 100644
index 00000000..14be23e1
--- /dev/null
+++ b/www/wiki/extensions/ModernTimeline/src/SlidePresenter/SimpleSlidePresenter.php
@@ -0,0 +1,40 @@
+<?php
+
+declare( strict_types = 1 );
+
+namespace ModernTimeline\SlidePresenter;
+
+use ModernTimeline\ResultFacade\Subject;
+use SMW\DataValueFactory;
+use SMW\Query\PrintRequest;
+
+class SimpleSlidePresenter implements SlidePresenter {
+
+ public function getText( Subject $subject ): string {
+ return implode( '<br>', iterator_to_array( $this->getDisplayValues( $subject ) ) );
+ }
+
+ private function getDisplayValues( Subject $subject ) {
+ foreach ( $subject->getPropertyValueCollections() as $propertyValues ) {
+ foreach ( $propertyValues->getDataItems() as $dataItem ) {
+ yield $this->getDisplayValue( $propertyValues->getPrintRequest(), $dataItem );
+ }
+ }
+ }
+
+ private function getDisplayValue( PrintRequest $pr, \SMWDataItem $dataItem ) {
+ $property = $pr->getText( null );
+ $value = $this->dataItemToText( $dataItem );
+
+ if ( $property === '' ) {
+ return $value;
+ }
+
+ return $property . ': ' . $value;
+ }
+
+ private function dataItemToText( \SMWDataItem $dataItem ): string {
+ return DataValueFactory::getInstance()->newDataValueByItem( $dataItem )->getLongHTMLText();
+ }
+
+}
diff --git a/www/wiki/extensions/ModernTimeline/src/SlidePresenter/SlidePresenter.php b/www/wiki/extensions/ModernTimeline/src/SlidePresenter/SlidePresenter.php
new file mode 100644
index 00000000..b272eb1c
--- /dev/null
+++ b/www/wiki/extensions/ModernTimeline/src/SlidePresenter/SlidePresenter.php
@@ -0,0 +1,13 @@
+<?php
+
+declare( strict_types = 1 );
+
+namespace ModernTimeline\SlidePresenter;
+
+use ModernTimeline\ResultFacade\Subject;
+
+interface SlidePresenter {
+
+ public function getText( Subject $subject ): string;
+
+}
diff --git a/www/wiki/extensions/ModernTimeline/src/SlidePresenter/TemplateSlidePresenter.php b/www/wiki/extensions/ModernTimeline/src/SlidePresenter/TemplateSlidePresenter.php
new file mode 100644
index 00000000..09c821d5
--- /dev/null
+++ b/www/wiki/extensions/ModernTimeline/src/SlidePresenter/TemplateSlidePresenter.php
@@ -0,0 +1,60 @@
+<?php
+
+declare( strict_types = 1 );
+
+namespace ModernTimeline\SlidePresenter;
+
+use ModernTimeline\ResultFacade\PropertyValueCollection;
+use ModernTimeline\ResultFacade\Subject;
+use SMW\DataValueFactory;
+
+class TemplateSlidePresenter implements SlidePresenter {
+
+ private $templateName;
+
+ public function __construct( string $templateName ) {
+ $this->templateName = $templateName;
+ }
+
+ public function getText( Subject $subject ): string {
+ $parser = $this->getParser();
+
+ return $parser->recursiveTagParseFully(
+ ( new TemplateSlidePresenter( $this->templateName ) )->getTemplateText( $subject )
+ );
+ }
+
+ private function getParser(): \Parser {
+ return $GLOBALS['wgParser'];
+ }
+
+ public function getTemplateText( Subject $subject ): string {
+ return '{{' . implode( '|', $this->getTemplateSegments( $subject ) ) . '}}';
+ }
+
+ private function getTemplateSegments( Subject $subject ): array {
+ return array_merge(
+ [
+ $this->templateName,
+ $this->parameter( 'title', $subject->getWikiPage()->getTitle()->getFullText() )
+ ],
+ array_map(
+ function( PropertyValueCollection $pvc ) {
+ return $this->parameter(
+ $pvc->getPrintRequest()->getText( null ) ?? '',
+ $pvc->getDataItems() === [] ? '' : $this->dataItemToText( $pvc->getDataItems()[0] )
+ );
+ },
+ $subject->getPropertyValueCollections()
+ )
+ );
+ }
+
+ private function dataItemToText( \SMWDataItem $dataItem ): string {
+ return DataValueFactory::getInstance()->newDataValueByItem( $dataItem )->getLongHTMLText();
+ }
+
+ private function parameter( string $name, string $value ): string {
+ return $name . '=' . $value;
+ }
+}
diff --git a/www/wiki/extensions/ModernTimeline/src/TimelineOptions.php b/www/wiki/extensions/ModernTimeline/src/TimelineOptions.php
new file mode 100644
index 00000000..934358d5
--- /dev/null
+++ b/www/wiki/extensions/ModernTimeline/src/TimelineOptions.php
@@ -0,0 +1,143 @@
+<?php
+
+declare( strict_types = 1 );
+
+namespace ModernTimeline;
+
+use ParamProcessor\ParameterTypes;
+use ParamProcessor\ProcessedParam;
+
+class TimelineOptions {
+
+ public const PARAM_WIDTH = 'width';
+ public const PARAM_HEIGHT = 'height';
+ private const PARAM_BOOKMARK = 'bookmark';
+ private const PARAM_BACKGROUND = 'background';
+ private const PARAM_SCALE_FACTOR = 'scale factor';
+ private const PARAM_POSITION = 'position';
+ private const PARAM_TICK_WIDTH = 'tick width';
+ private const PARAM_START_SLIDE = 'start slide';
+ private const PARAM_START_AT_END = 'start at end';
+ private const PARAM_TRANSITION_DURATION = 'transition duration';
+ private const PARAM_NAV_HEIGHT = 'navigation height';
+ private const PARAM_TEMPLATE = 'template';
+
+ public static function getTimelineParameterDefinitions(): array {
+ $definitions = [];
+
+ $definitions[self::PARAM_WIDTH] = [
+ 'type' => ParameterTypes::DIMENSION,
+ 'allowauto' => true,
+ 'units' => [ 'px', 'ex', 'em', '%', '' ],
+ 'default' => $GLOBALS['wgModernTimelineWidth'],
+ ];
+
+ $definitions[self::PARAM_HEIGHT] = [
+ 'type' => ParameterTypes::DIMENSION,
+ 'units' => [ 'px', 'ex', 'em', '' ],
+ 'default' => $GLOBALS['wgModernTimelineHeight'],
+ ];
+
+ $definitions[self::PARAM_BOOKMARK] = [
+ 'type' => ParameterTypes::BOOLEAN,
+ 'default' => $GLOBALS['wgModernTimelineBookmark'],
+ ];
+
+ $definitions[self::PARAM_BACKGROUND] = [
+ 'type' => ParameterTypes::STRING,
+ 'default' => $GLOBALS['wgModernTimelineBackground'],
+ ];
+
+ $definitions[self::PARAM_SCALE_FACTOR] = [
+ 'type' => ParameterTypes::INTEGER,
+ 'default' => $GLOBALS['wgModernTimelineScaleFactor'],
+ 'lowerbound' => 1
+ ];
+
+ $definitions[self::PARAM_POSITION] = [
+ 'type' => ParameterTypes::STRING,
+ 'default' => $GLOBALS['wgModernTimelinePosition'],
+ 'values' => [ 'top', 'bottom' ],
+ ];
+
+ $definitions[self::PARAM_TICK_WIDTH] = [
+ 'type' => ParameterTypes::INTEGER,
+ 'default' => $GLOBALS['wgModernTimelineTickWidth']
+ ];
+
+ $definitions[self::PARAM_START_SLIDE] = [
+ 'type' => ParameterTypes::INTEGER,
+ 'default' => $GLOBALS['wgModernTimelineStartSlide'],
+ 'lowerbound' => 1
+ ];
+
+ $definitions[self::PARAM_START_AT_END] = [
+ 'type' => ParameterTypes::BOOLEAN,
+ 'default' => $GLOBALS['wgModernTimelineStartAtEnd']
+ ];
+
+ $definitions[self::PARAM_TRANSITION_DURATION] = [
+ 'type' => ParameterTypes::INTEGER,
+ 'aliases' => 'duration',
+ 'default' => $GLOBALS['wgModernTimelineTransitionDuration'],
+ 'lowerbound' => 1
+ ];
+
+ $definitions[self::PARAM_NAV_HEIGHT] = [
+ 'type' => ParameterTypes::DIMENSION,
+ 'units' => [ 'px', '%' ],
+ 'default' => $GLOBALS['wgModernTimelineNavHeight'],
+ ];
+
+ $definitions[self::PARAM_TEMPLATE] = [
+ 'type' => ParameterTypes::STRING,
+ 'default' => $GLOBALS['wgModernTimelineTemplate']
+ ];
+
+ foreach ( $definitions as $name => $definition ) {
+ $definitions[$name]['message'] = 'modern-timeline-param-' . str_replace( ' ', '-', $name );
+
+ if ( strpos( $name, ' ' ) !== false ) {
+ $definitions[$name]['aliases'] = array_merge(
+ array_key_exists( 'aliases', $definitions[$name] ) ? (array)$definitions[$name]['aliases'] : [],
+ [ str_replace( ' ', '', $name ) ]
+ );
+ }
+ }
+
+ return $definitions;
+ }
+
+ /**
+ * @param ProcessedParam[] $parameters
+ * @return array
+ */
+ public static function processedParamsToJson( array $parameters ): array {
+ $json = [
+ 'hash_bookmark' => $parameters[self::PARAM_BOOKMARK]->getValue(),
+ 'default_bg_color' => $parameters[self::PARAM_BACKGROUND]->getValue(),
+ 'scale_factor' => $parameters[self::PARAM_SCALE_FACTOR]->getValue(),
+ 'timenav_position' => $parameters[self::PARAM_POSITION]->getValue(),
+ 'optimal_tick_width' => $parameters[self::PARAM_TICK_WIDTH]->getValue(),
+ 'start_at_slide' => self::getStartAtSlide( $parameters ),
+ 'start_at_end' => $parameters[self::PARAM_START_AT_END]->getValue(),
+ 'duration' => $parameters[self::PARAM_TRANSITION_DURATION]->getValue(),
+ ];
+
+ $height = $parameters[self::PARAM_NAV_HEIGHT]->getValue();
+
+ if ( strpos( $height, '%' ) === false ) {
+ $json['timenav_height'] = (int)substr( $height, 0, -2 );
+ }
+ else {
+ $json['timenav_height_percentage'] = (int)substr( $height, 0, -1 );
+ }
+
+ return $json;
+ }
+
+ private static function getStartAtSlide( array $parameters ): int {
+ return $parameters[self::PARAM_START_SLIDE]->getValue() - 1;
+ }
+
+} \ No newline at end of file
diff --git a/www/wiki/extensions/ModernTimeline/src/TimelinePresenter.php b/www/wiki/extensions/ModernTimeline/src/TimelinePresenter.php
new file mode 100644
index 00000000..b0d00689
--- /dev/null
+++ b/www/wiki/extensions/ModernTimeline/src/TimelinePresenter.php
@@ -0,0 +1,105 @@
+<?php
+
+declare( strict_types = 1 );
+
+namespace ModernTimeline;
+
+use ModernTimeline\ResultFacade\ResultSimplifier;
+use ModernTimeline\SlidePresenter\SimpleSlidePresenter;
+use ModernTimeline\SlidePresenter\SlidePresenter;
+use ModernTimeline\SlidePresenter\TemplateSlidePresenter;
+use ParamProcessor\ProcessedParam;
+use SMWOutputs;
+use SMWQueryResult;
+
+class TimelinePresenter {
+
+ private $id;
+ private $parameters;
+
+ /**
+ * @param ProcessedParam[] $parameters
+ */
+ public function __construct( array $parameters ) {
+ $this->parameters = $parameters;
+ $this->id = $this->newTimelineId();
+ }
+
+ private function newTimelineId(): string {
+ static $timelineNumber = 0;
+ return 'modern_timeline_' . ++$timelineNumber;
+ }
+
+ public function getResult( SMWQueryResult $result ): string {
+ SMWOutputs::requireResource( 'ext.modern.timeline' );
+
+ $json = $this->createJsonString( $result );
+
+ SMWOutputs::requireHeadItem(
+ $this->id,
+ $this->createJs( $json )
+ );
+
+ return $this->createDiv( $json );
+ }
+
+ private function createJsonString( SMWQueryResult $result ) {
+ $preJson = ( new JsonBuilder( $this->getSlidePresenter() ) )->buildTimelineJson(
+ ( new ResultSimplifier() )->newSubjectCollection( $result )
+ );
+
+ $preJson['options'] = TimelineOptions::processedParamsToJson( $this->parameters );
+
+ return json_encode( $preJson );
+ }
+
+ private function getSlidePresenter(): SlidePresenter {
+ if ( $this->getTemplateName() === '' ) {
+ return new SimpleSlidePresenter();
+ }
+
+ return new TemplateSlidePresenter( $this->getTemplateName() );
+ }
+
+ private function getTemplateName(): string {
+ return $this->parameters['template']->getValue();
+ }
+
+ private function createJs( string $json ): string {
+ return \Html::rawElement(
+ 'script',
+ [
+ 'type' => 'text/javascript'
+ ],
+ "if (!window.hasOwnProperty('modernTimeline')) {window.modernTimeline = {};}"
+ . "\n window.modernTimeline.{$this->id} = $json;"
+ );
+ }
+
+ private function createDiv( string $json ): string {
+ $width = $this->parameters[TimelineOptions::PARAM_WIDTH]->getValue();
+ $height = $this->parameters[TimelineOptions::PARAM_HEIGHT]->getValue();
+
+ return \Html::rawElement(
+ 'div',
+ [
+ 'id' => $this->id,
+ 'style' => "width: $width; height: $height",
+ 'class' => 'modern_timeline_outer_div'
+ ],
+ \Html::element(
+ 'div',
+ [
+ 'class' => 'modern_timeline_inner_div',
+ 'style' => 'width: 100%; height: calc(100% - 10px); background-color: rgba(0, 0, 0, 0.05); margin-top: 5px; margin-bottom: 5px;'
+ ]
+ )
+ )
+ . \Html::element( // TODO: remove when system tests can test head items
+ 'div',
+ [ 'style' => 'display:none' ],
+ $json
+ );
+ }
+
+}