Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Merge branch 'psr2' into psr2-config
* psr2: fix appveyor, download from https always Issue #1250, associated unit test translation update translation update fix(TASK_RECENTCHANGES_TRIM event): Add isMedia flag rename task event add missing visibility indicator and docblocks translation update refactor: Rename lib/exe/indexer.php to taskrunner.php 🔨 refactor: Move the remainder of code from lib/exe/indexer.php to TaskRunner::run 🔨 Fix for Issue#1250 Footnotes break metadata abstract saving feat: Trigger new event when changelog is trimmed ✨ style(TaskRunner): automatic whitespace fixes 🎨 refactor: Extract code from lib/exe/indexer into new TaskRunner class 🔨 corectly disable sniff for one file translation update
- Loading branch information
Showing
35 changed files
with
718 additions
and
327 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<?php | ||
|
||
/** | ||
* Class renderer_xhtml_test | ||
*/ | ||
class renderer_metadata_test extends DokuWikiTest { | ||
/** @var Doku_Renderer_xhtml */ | ||
protected $R; | ||
|
||
/** | ||
* Called for each test | ||
* | ||
* @throws Exception | ||
*/ | ||
function setUp() { | ||
parent::setUp(); | ||
$this->R = new Doku_Renderer_metadata(); | ||
} | ||
|
||
function tearDown() { | ||
unset($this->R); | ||
} | ||
|
||
|
||
function test_footnote_and_abstract() { | ||
// avoid issues with the filectime() & filemtime in document_start() & document_end() | ||
$now = time(); | ||
$this->R->persistent['date']['created'] = $now; | ||
$this->R->persistent['date']['modified'] = $now; | ||
|
||
$this->R->document_start(); | ||
|
||
$this->R->cdata("abstract: "); | ||
|
||
$this->R->footnote_open(); | ||
$this->R->cdata(str_pad("footnote: ", Doku_Renderer_metadata::ABSTRACT_MAX, "lotsa junk ")); | ||
$this->R->footnote_close(); | ||
|
||
$this->R->cdata("abstract end."); | ||
|
||
$this->R->document_end(); | ||
|
||
$expected = 'abstract: abstract end.'; | ||
$this->assertEquals($expected, $this->R->meta['description']['abstract']); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,239 @@ | ||
<?php | ||
|
||
namespace dokuwiki; | ||
|
||
use Doku_Event; | ||
use Sitemapper; | ||
use Subscription; | ||
|
||
/** | ||
* Class TaskRunner | ||
* | ||
* Run an asynchronous task. | ||
*/ | ||
class TaskRunner | ||
{ | ||
/** | ||
* Run the next task | ||
* | ||
* @todo refactor to remove dependencies on globals | ||
* @triggers INDEXER_TASKS_RUN | ||
*/ | ||
public function run() | ||
{ | ||
global $INPUT, $conf, $ID; | ||
|
||
// keep running after browser closes connection | ||
@ignore_user_abort(true); | ||
|
||
// check if user abort worked, if yes send output early | ||
$defer = !@ignore_user_abort() || $conf['broken_iua']; | ||
$output = $INPUT->has('debug') && $conf['allowdebug']; | ||
if(!$defer && !$output){ | ||
$this->sendGIF(); | ||
} | ||
|
||
$ID = cleanID($INPUT->str('id')); | ||
|
||
// Catch any possible output (e.g. errors) | ||
if(!$output) { | ||
ob_start(); | ||
} else { | ||
header('Content-Type: text/plain'); | ||
} | ||
|
||
// run one of the jobs | ||
$tmp = []; // No event data | ||
$evt = new Doku_Event('INDEXER_TASKS_RUN', $tmp); | ||
if ($evt->advise_before()) { | ||
$this->runIndexer() or | ||
$this->runSitemapper() or | ||
$this->sendDigest() or | ||
$this->runTrimRecentChanges() or | ||
$this->runTrimRecentChanges(true) or | ||
$evt->advise_after(); | ||
} | ||
|
||
if(!$output) { | ||
ob_end_clean(); | ||
if($defer) { | ||
$this->sendGIF(); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Just send a 1x1 pixel blank gif to the browser | ||
* | ||
* @author Andreas Gohr <andi@splitbrain.org> | ||
* @author Harry Fuecks <fuecks@gmail.com> | ||
*/ | ||
protected function sendGIF() | ||
{ | ||
$img = base64_decode('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7'); | ||
header('Content-Type: image/gif'); | ||
header('Content-Length: '.strlen($img)); | ||
header('Connection: Close'); | ||
print $img; | ||
tpl_flush(); | ||
// Browser should drop connection after this | ||
// Thinks it's got the whole image | ||
} | ||
|
||
/** | ||
* Trims the recent changes cache (or imports the old changelog) as needed. | ||
* | ||
* @param bool $media_changes If the media changelog shall be trimmed instead of | ||
* the page changelog | ||
* | ||
* @return bool | ||
* @triggers TASK_RECENTCHANGES_TRIM | ||
* @author Ben Coburn <btcoburn@silicodon.net> | ||
*/ | ||
protected function runTrimRecentChanges($media_changes = false) | ||
{ | ||
global $conf; | ||
|
||
echo "runTrimRecentChanges($media_changes): started" . NL; | ||
|
||
$fn = ($media_changes ? $conf['media_changelog'] : $conf['changelog']); | ||
|
||
// Trim the Recent Changes | ||
// Trims the recent changes cache to the last $conf['changes_days'] recent | ||
// changes or $conf['recent'] items, which ever is larger. | ||
// The trimming is only done once a day. | ||
if (file_exists($fn) && | ||
(@filemtime($fn . '.trimmed') + 86400) < time() && | ||
!file_exists($fn . '_tmp')) { | ||
@touch($fn . '.trimmed'); | ||
io_lock($fn); | ||
$lines = file($fn); | ||
if (count($lines) <= $conf['recent']) { | ||
// nothing to trim | ||
io_unlock($fn); | ||
echo "runTrimRecentChanges($media_changes): finished" . NL; | ||
return false; | ||
} | ||
|
||
io_saveFile($fn . '_tmp', ''); // presave tmp as 2nd lock | ||
$trim_time = time() - $conf['recent_days'] * 86400; | ||
$out_lines = []; | ||
$old_lines = []; | ||
for ($i = 0; $i < count($lines); $i++) { | ||
$log = parseChangelogLine($lines[$i]); | ||
if ($log === false) { | ||
continue; | ||
} // discard junk | ||
if ($log['date'] < $trim_time) { | ||
$old_lines[$log['date'] . ".$i"] = $lines[$i]; // keep old lines for now (append .$i to prevent key collisions) | ||
} else { | ||
$out_lines[$log['date'] . ".$i"] = $lines[$i]; // definitely keep these lines | ||
} | ||
} | ||
|
||
if (count($lines) == count($out_lines)) { | ||
// nothing to trim | ||
@unlink($fn . '_tmp'); | ||
io_unlock($fn); | ||
echo "runTrimRecentChanges($media_changes): finished" . NL; | ||
return false; | ||
} | ||
|
||
// sort the final result, it shouldn't be necessary, | ||
// however the extra robustness in making the changelog cache self-correcting is worth it | ||
ksort($out_lines); | ||
$extra = $conf['recent'] - count($out_lines); // do we need extra lines do bring us up to minimum | ||
if ($extra > 0) { | ||
ksort($old_lines); | ||
$out_lines = array_merge(array_slice($old_lines, -$extra), $out_lines); | ||
} | ||
|
||
$eventData = [ | ||
'isMedia' => $media_changes, | ||
'trimmedChangelogLines' => $out_lines, | ||
'removedChangelogLines' => $extra > 0 ? array_slice($old_lines, 0, -$extra) : $old_lines, | ||
]; | ||
trigger_event('TASK_RECENTCHANGES_TRIM', $eventData); | ||
$out_lines = $eventData['trimmedChangelogLines']; | ||
|
||
// save trimmed changelog | ||
io_saveFile($fn . '_tmp', implode('', $out_lines)); | ||
@unlink($fn); | ||
if (!rename($fn . '_tmp', $fn)) { | ||
// rename failed so try another way... | ||
io_unlock($fn); | ||
io_saveFile($fn, implode('', $out_lines)); | ||
@unlink($fn . '_tmp'); | ||
} else { | ||
io_unlock($fn); | ||
} | ||
echo "runTrimRecentChanges($media_changes): finished" . NL; | ||
return true; | ||
} | ||
|
||
// nothing done | ||
echo "runTrimRecentChanges($media_changes): finished" . NL; | ||
return false; | ||
} | ||
|
||
|
||
/** | ||
* Runs the indexer for the current page | ||
* | ||
* @author Andreas Gohr <andi@splitbrain.org> | ||
*/ | ||
protected function runIndexer() | ||
{ | ||
global $ID; | ||
global $conf; | ||
print 'runIndexer(): started' . NL; | ||
|
||
if (!$ID) { | ||
return false; | ||
} | ||
|
||
// do the work | ||
return idx_addPage($ID, true); | ||
} | ||
|
||
/** | ||
* Builds a Google Sitemap of all public pages known to the indexer | ||
* | ||
* The map is placed in the root directory named sitemap.xml.gz - This | ||
* file needs to be writable! | ||
* | ||
* @author Andreas Gohr | ||
* @link https://www.google.com/webmasters/sitemaps/docs/en/about.html | ||
*/ | ||
protected function runSitemapper() | ||
{ | ||
print 'runSitemapper(): started' . NL; | ||
$result = Sitemapper::generate() && Sitemapper::pingSearchEngines(); | ||
print 'runSitemapper(): finished' . NL; | ||
return $result; | ||
} | ||
|
||
/** | ||
* Send digest and list mails for all subscriptions which are in effect for the | ||
* current page | ||
* | ||
* @author Adrian Lang <lang@cosmocode.de> | ||
*/ | ||
protected function sendDigest() | ||
{ | ||
global $conf; | ||
global $ID; | ||
|
||
echo 'sendDigest(): started' . NL; | ||
if (!actionOK('subscribe')) { | ||
echo 'sendDigest(): disabled' . NL; | ||
return false; | ||
} | ||
$sub = new Subscription(); | ||
$sent = $sub->send_bulk($ID); | ||
|
||
echo "sendDigest(): sent $sent mails" . NL; | ||
echo 'sendDigest(): finished' . NL; | ||
return (bool)$sent; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.