diff --git a/lib/CProject.php b/lib/CProject.php index 7a99bbb..ab88159 100644 --- a/lib/CProject.php +++ b/lib/CProject.php @@ -16,6 +16,8 @@ class CProject { private $downloads = array(); private $downloads_hashes = array(); + public $downloads_section_was_replaced = false; + public $lifespan = 0; public $tags = array(); @@ -26,19 +28,23 @@ class CProject { $this->dir = BASEDIR.'data/'.$dirname.'/'; $this->projname = $projname; + $matches = []; + // Identify resources in folder $ls = scandir($this->dir); $found_real_lastupdate = false; foreach($ls as $file) { - if ($file[0] == '.') continue; + if ($file[0] == '.') { + continue; + } if ($file == 'README.txt') { $this->longdesc = file_get_contents($this->dir.'README.txt'); + $this->longdesc = str_replace("\r", "", $this->longdesc); // filter windows CR // Guess 'last update' time - $matches = []; if (preg_match('~\n(\d\d\d\d-\d\d-\d\d)~', $this->longdesc, $matches)) { // Use first date entry (assumed to be a CHANGELOG) $this->lastupdate = strtotime($matches[1]); @@ -60,13 +66,12 @@ class CProject { $this->lifespan = floor(max(0, $newest - $eldest) / 3600); // could divide by 86400 but it doesn't matter // Find 'written in' - $matches = array(); - if (preg_match('~Written in ([^\\r\\n]+)~', $this->longdesc, $matches)) { + if (preg_match('~Written in ([^\\n]+)~', $this->longdesc, $matches)) { $this->subtag = rtrim($matches[1], ' .'); } // Find tags - if (preg_match('~Tags: ([^\\r\\n]+)~', $this->longdesc, $matches)) { + if (preg_match('~Tags: ([^\\n]+)~', $this->longdesc, $matches)) { $this->tags = array_map('trim', explode(',', $matches[1])); } @@ -75,11 +80,10 @@ class CProject { $this->shortdesc = array_shift($parts); $this->shortdesc[0] = strtolower($this->shortdesc[0]); // cosmetic lowercase - // Filters for longdesc - $this->longdesc = str_replace("\r", "", $this->longdesc); // filter windows CR + // Filters for longdesc $prefix_html = ''; - $this->longdesc = preg_replace_callback('~\r?\nWritten in ([^\\n]+)~ms', function($matches) use (&$prefix_html) { + $this->longdesc = preg_replace_callback('~\nWritten in ([^\\n]+)~ms', function($matches) use (&$prefix_html) { $prefix_html .= ( (SHIELDS_PREFIX ? mkshield('build', 'success', 'brightgreen').' ' : ''). mkshield('written in', rtrim($matches[1], '.'), 'blue') @@ -120,6 +124,8 @@ class CProject { sha1_file($this->dir.$this->downloads[$i]) ); } + + } public function genHomeImage() { @@ -134,6 +140,71 @@ class CProject { } + protected function filterLongDescArea() { + + // If *all* downloads can be assigned to a changelog release entry, + // then move the files + // A release entry is marked by any string following the date field. + + preg_match_all('~^(\d\d\d\d-\d\d-\d\d):? (.+?)\n[\s\t]*\n~ms', $this->longdesc, $matches, PREG_SET_ORDER); + + do { + // Ensure changelog exists + if (! count($matches)) { + break; + } + + // Find all tags + $known_tags = []; + foreach($matches as $i => $match) { + $tag = trim(explode("\n", $match[2])[0]); + $known_tags[$tag] = $i; + } + + // Ensure all release entries have tags + if (count($matches) != count($known_tags)) { + error_log("[".$this->projname."] not all release entries have tags\n"); + break; + } + + // Ensure all downloads can be assigned to tags + $found_idx = []; + foreach($this->downloads as $idx => $filename) { + foreach(array_keys($known_tags) as $tagname) { + if (stripos($filename, $tagname) !== false) { + $found_idx[$filename] = true; + } + } + } + if (count($found_idx) != count($this->downloads)) { + error_log("[".$this->projname."] not all downloads have matching tags"); + break; + } + + // Make HTML modifications + foreach($known_tags as $tag_name => $tag_idx) { + $find = rtrim($matches[$tag_idx][0]); + $this->longdesc = str_replace( + $find, + $find.'${{TAG_'.$tag_idx.'}}', + $this->longdesc + ); + } + + $this->longdesc = text2html($this->longdesc); + foreach($known_tags as $tag_name => $tag_idx) { + $this->longdesc = str_replace('${{TAG_'.$tag_idx.'}}', $this->renderDownloadsBlock(false, $tag_name), $this->longdesc); + } + + // Skip displaying the global downloads area + // This flag also indicates that the content has been pre-HTMLified + $this->downloads_section_was_replaced = true; + + error_log("[".$this->projname."] successful upgrade\n"); + + } while(false); + } + public function numDownloads() { return count($this->downloads); } @@ -185,7 +256,46 @@ class CProject { } } + public function renderDownloadsBlock($include_header=false, $filter='') { + $render_downloads = []; + if (strlen($filter)) { + foreach($this->downloads as $idx => $filename) { + if (stripos($filename, $filter) !== false) { + $render_downloads[$idx] = $filename; + } + } + } else { + $render_downloads = $this->downloads; + } + + if (! count($render_downloads)) { + return; + } + + ob_start(); +?> + + DOWNLOAD + + +filterLongDescArea(); + $longdesc_html = $this->downloads_section_was_replaced ? $this->longdesc : text2html($this->longdesc); + ?>

projname))?>

@@ -198,26 +308,15 @@ class CProject { - -

longdesc)?>

+ +

-downloads)) { ?> - - DOWNLOAD - - +downloads_section_was_replaced) { ?> + renderDownloadsBlock(true, '')?> + images)) { ?>