xref: /dokuwiki/inc/TaskRunner.php (revision 9493c275054ef649b724c083fdac46388e6e1361)
1*9493c275SMichael Große<?php
2*9493c275SMichael Große
3*9493c275SMichael Großenamespace dokuwiki;
4*9493c275SMichael Große
5*9493c275SMichael Großeuse Doku_Event;
6*9493c275SMichael Großeuse Sitemapper;
7*9493c275SMichael Großeuse Subscription;
8*9493c275SMichael Große
9*9493c275SMichael Großeclass TaskRunner
10*9493c275SMichael Große{
11*9493c275SMichael Große    public function run()
12*9493c275SMichael Große    {
13*9493c275SMichael Große        // run one of the jobs
14*9493c275SMichael Große        $tmp = []; // No event data
15*9493c275SMichael Große        $evt = new Doku_Event('INDEXER_TASKS_RUN', $tmp);
16*9493c275SMichael Große        if ($evt->advise_before()) {
17*9493c275SMichael Große            $this->runIndexer() or
18*9493c275SMichael Große            $this->runSitemapper() or
19*9493c275SMichael Große            $this->sendDigest() or
20*9493c275SMichael Große            $this->runTrimRecentChanges() or
21*9493c275SMichael Große            $this->runTrimRecentChanges(true) or
22*9493c275SMichael Große            $evt->advise_after();
23*9493c275SMichael Große        }
24*9493c275SMichael Große    }
25*9493c275SMichael Große
26*9493c275SMichael Große    /**
27*9493c275SMichael Große     * Trims the recent changes cache (or imports the old changelog) as needed.
28*9493c275SMichael Große     *
29*9493c275SMichael Große     * @param bool $media_changes If the media changelog shall be trimmed instead of
30*9493c275SMichael Große     *                              the page changelog
31*9493c275SMichael Große     * @return bool
32*9493c275SMichael Große     *
33*9493c275SMichael Große     * @author Ben Coburn <btcoburn@silicodon.net>
34*9493c275SMichael Große     */
35*9493c275SMichael Große    protected function runTrimRecentChanges($media_changes = false) {
36*9493c275SMichael Große        global $conf;
37*9493c275SMichael Große
38*9493c275SMichael Große        echo "runTrimRecentChanges($media_changes): started".NL;
39*9493c275SMichael Große
40*9493c275SMichael Große        $fn = ($media_changes ? $conf['media_changelog'] : $conf['changelog']);
41*9493c275SMichael Große
42*9493c275SMichael Große        // Trim the Recent Changes
43*9493c275SMichael Große        // Trims the recent changes cache to the last $conf['changes_days'] recent
44*9493c275SMichael Große        // changes or $conf['recent'] items, which ever is larger.
45*9493c275SMichael Große        // The trimming is only done once a day.
46*9493c275SMichael Große        if (file_exists($fn) &&
47*9493c275SMichael Große            (@filemtime($fn.'.trimmed')+86400)<time() &&
48*9493c275SMichael Große            !file_exists($fn.'_tmp')) {
49*9493c275SMichael Große            @touch($fn.'.trimmed');
50*9493c275SMichael Große            io_lock($fn);
51*9493c275SMichael Große            $lines = file($fn);
52*9493c275SMichael Große            if (count($lines)<=$conf['recent']) {
53*9493c275SMichael Große                // nothing to trim
54*9493c275SMichael Große                io_unlock($fn);
55*9493c275SMichael Große                echo "runTrimRecentChanges($media_changes): finished".NL;
56*9493c275SMichael Große                return false;
57*9493c275SMichael Große            }
58*9493c275SMichael Große
59*9493c275SMichael Große            io_saveFile($fn.'_tmp', '');          // presave tmp as 2nd lock
60*9493c275SMichael Große            $trim_time = time() - $conf['recent_days']*86400;
61*9493c275SMichael Große            $out_lines = array();
62*9493c275SMichael Große            $old_lines = array();
63*9493c275SMichael Große            for ($i=0; $i<count($lines); $i++) {
64*9493c275SMichael Große                $log = parseChangelogLine($lines[$i]);
65*9493c275SMichael Große                if ($log === false) continue;                      // discard junk
66*9493c275SMichael Große                if ($log['date'] < $trim_time) {
67*9493c275SMichael Große                    $old_lines[$log['date'].".$i"] = $lines[$i];     // keep old lines for now (append .$i to prevent key collisions)
68*9493c275SMichael Große                } else {
69*9493c275SMichael Große                    $out_lines[$log['date'].".$i"] = $lines[$i];     // definitely keep these lines
70*9493c275SMichael Große                }
71*9493c275SMichael Große            }
72*9493c275SMichael Große
73*9493c275SMichael Große            if (count($lines)==count($out_lines)) {
74*9493c275SMichael Große                // nothing to trim
75*9493c275SMichael Große                @unlink($fn.'_tmp');
76*9493c275SMichael Große                io_unlock($fn);
77*9493c275SMichael Große                echo "runTrimRecentChanges($media_changes): finished".NL;
78*9493c275SMichael Große                return false;
79*9493c275SMichael Große            }
80*9493c275SMichael Große
81*9493c275SMichael Große            // sort the final result, it shouldn't be necessary,
82*9493c275SMichael Große            //   however the extra robustness in making the changelog cache self-correcting is worth it
83*9493c275SMichael Große            ksort($out_lines);
84*9493c275SMichael Große            $extra = $conf['recent'] - count($out_lines);        // do we need extra lines do bring us up to minimum
85*9493c275SMichael Große            if ($extra > 0) {
86*9493c275SMichael Große                ksort($old_lines);
87*9493c275SMichael Große                $out_lines = array_merge(array_slice($old_lines,-$extra),$out_lines);
88*9493c275SMichael Große            }
89*9493c275SMichael Große
90*9493c275SMichael Große            // save trimmed changelog
91*9493c275SMichael Große            io_saveFile($fn.'_tmp', implode('', $out_lines));
92*9493c275SMichael Große            @unlink($fn);
93*9493c275SMichael Große            if (!rename($fn.'_tmp', $fn)) {
94*9493c275SMichael Große                // rename failed so try another way...
95*9493c275SMichael Große                io_unlock($fn);
96*9493c275SMichael Große                io_saveFile($fn, implode('', $out_lines));
97*9493c275SMichael Große                @unlink($fn.'_tmp');
98*9493c275SMichael Große            } else {
99*9493c275SMichael Große                io_unlock($fn);
100*9493c275SMichael Große            }
101*9493c275SMichael Große            echo "runTrimRecentChanges($media_changes): finished".NL;
102*9493c275SMichael Große            return true;
103*9493c275SMichael Große        }
104*9493c275SMichael Große
105*9493c275SMichael Große        // nothing done
106*9493c275SMichael Große        echo "runTrimRecentChanges($media_changes): finished".NL;
107*9493c275SMichael Große        return false;
108*9493c275SMichael Große    }
109*9493c275SMichael Große
110*9493c275SMichael Große
111*9493c275SMichael Große    /**
112*9493c275SMichael Große     * Runs the indexer for the current page
113*9493c275SMichael Große     *
114*9493c275SMichael Große     * @author Andreas Gohr <andi@splitbrain.org>
115*9493c275SMichael Große     */
116*9493c275SMichael Große    protected function runIndexer(){
117*9493c275SMichael Große        global $ID;
118*9493c275SMichael Große        global $conf;
119*9493c275SMichael Große        print "runIndexer(): started".NL;
120*9493c275SMichael Große
121*9493c275SMichael Große        if(!$ID) return false;
122*9493c275SMichael Große
123*9493c275SMichael Große        // do the work
124*9493c275SMichael Große        return idx_addPage($ID, true);
125*9493c275SMichael Große    }
126*9493c275SMichael Große
127*9493c275SMichael Große    /**
128*9493c275SMichael Große     * Builds a Google Sitemap of all public pages known to the indexer
129*9493c275SMichael Große     *
130*9493c275SMichael Große     * The map is placed in the root directory named sitemap.xml.gz - This
131*9493c275SMichael Große     * file needs to be writable!
132*9493c275SMichael Große     *
133*9493c275SMichael Große     * @author Andreas Gohr
134*9493c275SMichael Große     * @link   https://www.google.com/webmasters/sitemaps/docs/en/about.html
135*9493c275SMichael Große     */
136*9493c275SMichael Große    protected function runSitemapper(){
137*9493c275SMichael Große        print "runSitemapper(): started".NL;
138*9493c275SMichael Große        $result = Sitemapper::generate() && Sitemapper::pingSearchEngines();
139*9493c275SMichael Große        print 'runSitemapper(): finished'.NL;
140*9493c275SMichael Große        return $result;
141*9493c275SMichael Große    }
142*9493c275SMichael Große
143*9493c275SMichael Große    /**
144*9493c275SMichael Große     * Send digest and list mails for all subscriptions which are in effect for the
145*9493c275SMichael Große     * current page
146*9493c275SMichael Große     *
147*9493c275SMichael Große     * @author Adrian Lang <lang@cosmocode.de>
148*9493c275SMichael Große     */
149*9493c275SMichael Große    protected function sendDigest() {
150*9493c275SMichael Große        global $conf;
151*9493c275SMichael Große        global $ID;
152*9493c275SMichael Große
153*9493c275SMichael Große        echo 'sendDigest(): started'.NL;
154*9493c275SMichael Große        if(!actionOK('subscribe')) {
155*9493c275SMichael Große            echo 'sendDigest(): disabled'.NL;
156*9493c275SMichael Große            return false;
157*9493c275SMichael Große        }
158*9493c275SMichael Große        $sub = new Subscription();
159*9493c275SMichael Große        $sent = $sub->send_bulk($ID);
160*9493c275SMichael Große
161*9493c275SMichael Große        echo "sendDigest(): sent $sent mails".NL;
162*9493c275SMichael Große        echo 'sendDigest(): finished'.NL;
163*9493c275SMichael Große        return (bool) $sent;
164*9493c275SMichael Große    }
165*9493c275SMichael Große}
166