From 68538c6faec205440c58bde80f1a7da11eb814da Mon Sep 17 00:00:00 2001 From: Franck Dupont Date: Sat, 31 Oct 2020 15:33:53 +0100 Subject: [PATCH] Add "Recent changes" page on frontoffice --- asset/js/common/recent-changes.js | 10 ++ config/module.config.php | 14 +++ .../PublicApp/RecentChangesController.php | 26 +++++ src/Mediawiki/ApiClient.php | 44 +++++++ src/ViewHelper/Scripto.php | 10 ++ .../public-app/recent-changes/browse.phtml | 107 ++++++++++++++++++ 6 files changed, 211 insertions(+) create mode 100644 asset/js/common/recent-changes.js create mode 100644 src/Controller/PublicApp/RecentChangesController.php create mode 100644 view/scripto/public-app/recent-changes/browse.phtml diff --git a/asset/js/common/recent-changes.js b/asset/js/common/recent-changes.js new file mode 100644 index 00000000..6da7f4a7 --- /dev/null +++ b/asset/js/common/recent-changes.js @@ -0,0 +1,10 @@ +$(document).ready(function() { + +// Handle a time period selection. +$('#time-period').on('change', function() { + var thisSelect = $(this); + var params = {'hours': thisSelect.val()}; + window.location.href = thisSelect.data('url') + '?' + $.param(params); +}); + +}); diff --git a/config/module.config.php b/config/module.config.php index e3d63f51..49f66ca5 100644 --- a/config/module.config.php +++ b/config/module.config.php @@ -43,6 +43,7 @@ 'Scripto\Controller\PublicApp\Item' => Scripto\Controller\PublicApp\ItemController::class, 'Scripto\Controller\PublicApp\Media' => Scripto\Controller\PublicApp\MediaController::class, 'Scripto\Controller\PublicApp\Revision' => Scripto\Controller\PublicApp\RevisionController::class, + 'Scripto\Controller\PublicApp\RecentChanges' => Scripto\Controller\PublicApp\RecentChangesController::class, 'Scripto\Controller\Admin\User' => Scripto\Controller\Admin\UserController::class, 'Scripto\Controller\Admin\Item' => Scripto\Controller\Admin\ItemController::class, 'Scripto\Controller\Admin\Media' => Scripto\Controller\Admin\MediaController::class, @@ -301,6 +302,19 @@ ], ], ], + 'scripto-recent-changes' => [ + 'type' => 'Segment', + 'options' => [ + 'route' => '/scripto/recent-changes', + 'constraints' => [ + ], + 'defaults' => [ + '__NAMESPACE__' => 'Scripto\Controller\PublicApp', + 'controller' => 'recent-changes', + 'action' => 'browse', + ], + ], + ], 'scripto-talk-media-id' => [ 'type' => 'Segment', 'options' => [ diff --git a/src/Controller/PublicApp/RecentChangesController.php b/src/Controller/PublicApp/RecentChangesController.php new file mode 100644 index 00000000..1f055e68 --- /dev/null +++ b/src/Controller/PublicApp/RecentChangesController.php @@ -0,0 +1,26 @@ +params()->fromQuery('hours', 720); // 30 days + $continue = $this->params()->fromQuery('continue'); + + $response = $this->scripto()->apiClient()->queryRecentChanges($hours, 10, $continue); + + $recentChanges = $this->scripto()->prepareMediawikiList($response['query']['recentchanges']); + + $continue = isset($response['continue']) ? $response['continue']['rccontinue'] : null; + + $view = new ViewModel; + $view->setVariable('recentChanges', $recentChanges); + $view->setVariable('hours', $hours); + $view->setVariable('continue', $continue); + return $view; + } +} diff --git a/src/Mediawiki/ApiClient.php b/src/Mediawiki/ApiClient.php index 7d781dcd..38eb13cd 100644 --- a/src/Mediawiki/ApiClient.php +++ b/src/Mediawiki/ApiClient.php @@ -573,6 +573,50 @@ public function queryRevision($title, $revisionId) return $this->revisionCache[$title][$revisionId]; } + /** + * Query recent changes. + * + * @link https://www.mediawiki.org/wiki/API:RecentChanges + * @param int $hours How many hours ago to end listing + * @param int $limit + * @param string $continue + * @return array + */ + public function queryRecentChanges($hours, $limit, $continue = null) + { + if (!is_numeric($limit)) { + throw new Exception\InvalidArgumentException('A limit must be numeric'); + } + if (isset($continue) && !is_string($continue)) { + throw new Exception\InvalidArgumentException('A continue must be a string'); + } + + $request = [ + 'action' => 'query', + 'list' => 'recentchanges', + 'rclimit' => $limit, + 'rcend' => strtotime(sprintf('-%s hour', $hours)), + 'rcprop' => 'user|comment|timestamp|title|ids|sizes|parsedcomment|loginfo|flags', + ]; + if ($continue) { + $request['rccontinue'] = $continue; + } + + $query = $this->request($request); + + if (isset($query['error'])) { + throw new Exception\QueryException($query['error']['info']); + } + // Set timestamps to DateTime objects adjusted to Omeka's time zone. + foreach ($query['query']['recentchanges'] as $index => $recentChange) { + $dateTime = new DateTime($recentChange['timestamp']); + $dateTime->setTimezone(new DateTimeZone($this->timeZone)); + $query['query']['recentchanges'][$index]['timestamp'] = $dateTime; + } + + return $query; + } + /** * Parse revision wikitext into HTML. * diff --git a/src/ViewHelper/Scripto.php b/src/ViewHelper/Scripto.php index ce61e469..a6362225 100644 --- a/src/ViewHelper/Scripto.php +++ b/src/ViewHelper/Scripto.php @@ -456,6 +456,16 @@ public function watchlistTimePeriodSelect() ); } + /** + * Render the recentchanges time period select. + * + * @return string + */ + public function recentChangesTimePeriodSelect() + { + return $this->watchlistTimePeriodSelect(); + } + /** * Render an admin search box for filtering items and media. * diff --git a/view/scripto/public-app/recent-changes/browse.phtml b/view/scripto/public-app/recent-changes/browse.phtml new file mode 100644 index 00000000..afdf8219 --- /dev/null +++ b/view/scripto/public-app/recent-changes/browse.phtml @@ -0,0 +1,107 @@ +headScript()->appendFile($this->assetUrl('js/common/recent-changes.js', 'Scripto')); +$this->scripto()->postTitle($this->translate('Recent changes')); +?> +
+
+ scripto()->recentChangesTimePeriodSelect(); ?> + scripto()->mediawikiPagination(); ?> +
+ + + + + + + + + + + + + + + + + format('G:i, j F Y'); + $sizeDiff = $page['newlen'] - $page['oldlen']; + $sMedia = isset($page['scripto_media']) ? $page['scripto_media'] : null; + $sItem = $sMedia ? $sMedia->scriptoItem() : null; + $project = $sItem ? $sItem->scriptoProject() : null; + $isTalk = (1 === $page['ns']); + ?> + + + + + + + + + + + + + +
translate('Media #'); ?>translate('Type'); ?>translate('Item'); ?>translate('Project'); ?>translate('Revision'); ?>translate('Size'); ?>translate('User'); ?>translate('Comment'); ?>
+ hyperlink(sprintf($this->scripto()->translate($project->mediaType(), 'Media #%s notes'), $sMedia->position()), $sMedia->url('talk')) + : $this->hyperlink(sprintf($this->scripto()->translate($project->mediaType(), 'Media #%s'), $sMedia->position()), $sMedia->url()) + : $this->translate('n/a'); ?> + scripto()->translate($project->itemType(), 'Item') : $this->translate('n/a'); ?>link($sItem->item()->displayTitle()) : $page['title']; ?>link($project->title()) : $this->translate('n/a'); ?> + hyperlink($date, $this->url( + $isTalk ? 'scripto-talk-revision-id' : 'scripto-revision-id', + [ + 'action' => 'show', + 'project-id' => $project->id(), + 'item-id' => $sItem->item()->id(), + 'media-id' => $sMedia->media()->id(), + 'revision-id' => $page['revid'], + ], + true + )) + : $date; ?> + + hyperlink($this->translate('diff'), $this->url( + $isTalk ? 'scripto-talk-revision-compare' : 'scripto-revision-compare', + [ + 'action' => 'compare', + 'project-id' => $project->id(), + 'item-id' => $sItem->item()->id(), + 'media-id' => $sMedia->media()->id(), + 'from-revision-id' => $page['old_revid'], + 'to-revision-id' => $page['revid'], + ], + true + )) + : $this->translate('diff'), + $this->hyperlink($this->translate('hist'), $this->url( + $isTalk ? 'scripto-talk-revision' : 'scripto-revision', + [ + 'action' => 'browse', + 'project-id' => $project->id(), + 'item-id' => $sItem->item()->id(), + 'media-id' => $sMedia->media()->id(), + ], + true + )) + ) + : ''; ?> + translate('%s bytes (%s)'), + number_format($page['newlen']), + sprintf( + '%s%s', + 0 < $sizeDiff ? 'green' : (0 > $sizeDiff ? 'red' : 'inherit'), + 0 < $sizeDiff ? '+' : '', + number_format($sizeDiff) + ) + ); ?>hyperlink($page['user'], $this->url('scripto-user-contributions', ['action' => 'contributions', 'user-id' => $page['user']], true)); ?>
+