1<?php
2/** @noinspection PhpUnused */
3/** @noinspection PhpPossiblePolymorphicInvocationInspection */
4/**  TEST AT 9:00 and then 9:35*/
5/**
6 * DokuWiki Plugin externalembed (action Component)
7 *
8 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
9 * @author  Cameron <cameronward007@gmail.com>
10 */
11
12// must be run within Dokuwiki
13if(!defined('DOKU_INC')) {
14    die();
15}
16
17class InvalidCacheCreation extends Exception {
18    public function errorMessage(): string {
19        return $this->getMessage();
20    }
21}
22
23class action_plugin_externalembed extends DokuWiki_Action_Plugin {
24
25    /**
26     * Registers a callback function for a given event
27     *
28     * @param Doku_Event_Handler $controller DokuWiki's event controller object
29     *
30     * @return void
31     */
32    public function register(Doku_Event_Handler $controller) {
33        $controller->register_hook('INDEXER_TASKS_RUN', 'BEFORE', $this, 'handle_indexer_tasks_run');
34        $controller->register_hook('PARSER_CACHE_USE', 'BEFORE', $this, 'handle_parser_cache_use');
35
36    }
37
38    /**
39     * Checks the currently used cache files and then invalidates the cache if it is out of date
40     *
41     * Called for event:
42     *
43     * @param Doku_Event $event  event object by reference
44     * @param mixed      $param  the parameters passed as fifth argument to register_hook() when this
45     *                           handler was registered
46     *
47     * @return void
48     * @noinspection PhpUnusedParameterInspection
49     */
50    public function handle_indexer_tasks_run(Doku_Event $event, $param) {
51        $metadata = p_get_metadata($_GET['id']);
52        if(empty($metadata)) return;
53        if(!($cacheHelper = $this->loadHelper('externalembed_cacheInterface'))) { //load the helper functions
54            echo 'Could not load cache interface helper';
55        }
56        $video_ids    = $metadata["plugin"]["externalembed"]["video_ids"];
57        $playlist_ids = $metadata['plugin']['externalembed']['playlist_ids'];
58        if(!empty($video_ids)) {
59            $expire_time = $this->getConf('THUMBNAIL_CACHE_TIME') * 60 * 60;
60            foreach($video_ids as $video_id) { //check each cache file to see if it needs to be updated
61                if(!$cacheHelper->checkCacheFreshness($video_id, $expire_time)) {
62                    //cache is not fresh time to update
63                    $event->preventDefault();
64                    $event->stopPropagation();
65                    touch($cacheHelper->getCacheFile($video_id));
66                }
67            }
68        }
69        if(!empty($playlist_ids)) {
70            $expire_time = $this->getConf('PLAYLIST_CACHE_TIME') * 60 * 60;
71            foreach($playlist_ids as $playlist_id) {
72                if(!$cacheHelper->checkCacheFreshness($playlist_id, $expire_time)) {
73                    //cache is not fresh time to update
74                    $event->preventDefault();
75                    $event->stopPropagation();
76                    touch($cacheHelper->getCacheFile($playlist_id));
77                }
78            }
79        }
80
81    }
82
83    /**
84     * Handles the parser cache use event.
85     * Checks the cache files created using the metadata
86     * Adds the cache files to the depends array to be used by the indexer event later
87     * @param Doku_Event $event
88     * @param            $param
89     * @noinspection PhpUnusedParameterInspection
90     * @noinspection PhpParameterByRefIsNotUsedAsReferenceInspection
91     */
92    public function handle_parser_cache_use(Doku_Event &$event, $param) {
93        $page_cache =& $event->data;
94
95        if(!isset($page_cache->page)) {
96            return;
97        }
98        if(!isset($page_cache->mode) || $page_cache->mode != 'xhtml') {
99            return;
100        }
101
102        if(!($cacheHelper = $this->loadHelper('externalembed_cacheInterface'))) { //load the helper functions
103            echo 'Could not load cache interface helper';
104        }
105
106        $metadata = p_get_metadata($page_cache->page, 'plugin');
107
108        if(empty($metadata['externalembed'])) {
109            return;
110        }
111
112        $video_ids    = $metadata['externalembed']['video_ids'];
113        $playlist_ids = $metadata['externalembed']['playlist_ids'];
114
115        try {
116            if(!empty($video_ids)) {
117                $expire_time = $this->getConf('THUMBNAIL_CACHE_TIME') * 60 * 60;
118                foreach($video_ids as $video_id) {
119                    if(!$cacheHelper->checkCacheFreshness($video_id, $expire_time)) { //update cache if not fresh (expired)
120                        $latest_thumbnail = $cacheHelper->getYouTubeThumbnail($video_id); //get latest thumbnail
121                        if($latest_thumbnail === $cacheHelper->getExistingCache($video_id)) { //check if the current cache is the same as the "new" cache
122                            $cacheHelper->updateETag($video_id); //update the last time we checked
123                        } else {
124                            $new_cache                      = $cacheHelper->cacheYouTubeThumbnail($video_id, $latest_thumbnail); //create new cache file with updated data
125                            $page_cache->depends['files'][] = $new_cache->cache; //add cache file to the 'depends' array
126                        }
127                    } else {
128                        $page_cache->depends['files'][] = $cacheHelper->getCacheFile($video_id); // adds the file path to the depends array
129                    }
130                }
131            }
132            if(!empty($playlist_ids)) {
133                $expire_time = $this->getConf('PLAYLIST_CACHE_TIME') * 60 * 60;
134                foreach($playlist_ids as $playlist_id) {
135                    if(!$cacheHelper->checkCacheFreshness($playlist_id, $expire_time)) { //update cache if not fresh (expired)
136                        $latest_playlist = $cacheHelper->getPlaylist($playlist_id); //get latest playlist
137                        $existing_cache  = $cacheHelper->getExistingCache($playlist_id);
138                        if($latest_playlist === $existing_cache) { //check if current cache is the same as the "new" cache
139                            $cacheHelper->updateETag(md5(time()));
140                        } else {
141                            $cacheHelper->removeOldVideo(end($existing_cache), $page_cache);
142                            $new_cache = $cacheHelper->cachePlaylist($playlist_id, $latest_playlist); //create new cache file
143
144                            //Get the latest video from the playlist and add it to the page's metadata
145                            $new_playlist_data = $new_cache->getCacheData();
146                            $new_metadata      = p_read_metadata($page_cache->page); //get existing metadata
147                            array_push($new_metadata['current']["plugin"]["externalembed"]["video_ids"], end($new_playlist_data));
148                            array_push($new_metadata['persistent']["plugin"]["externalembed"]["video_ids"], end($new_playlist_data));
149
150                            p_save_metadata($page_cache->page, $new_metadata); //add the video ids to the page's metadata
151
152                            $page_cache->depends['files'][] = $new_cache->cache; //add new playlist cache file to the depends array
153
154                            return;
155                        }
156                    }
157                    $page_cache->depends['files'][] = $cacheHelper->getExistingCache($playlist_id)->cache;
158
159                }
160            }
161            return;
162        } catch(InvalidCacheCreation $e) {
163            echo "<p style='color: red; font-weight: bold;'>External Embed Error: " . $e->getMessage() . "</p>";
164            return;
165        }
166    }
167}
168
169