1#!/usr/bin/env php 2<?php 3PHP_SAPI == 'cli' or die("Please run this script using the cli sapi"); 4 5require_once __DIR__ . '/../src/autoload.php'; 6 7use phpweb\News\Entry; 8 9$imageRestriction = [ 10 'width' => 400, 11 'height' => 250 12]; 13 14// Create an entry! 15if (!file_exists(Entry::ARCHIVE_FILE_ABS)) { 16 fwrite(STDERR, "Can't find " . Entry::ARCHIVE_FILE_REL . ", are you sure you are in phpweb/?\n"); 17 exit(1); 18} 19 20if ($_SERVER['argc'] > 1) { 21 // getopt based non-interactive mode 22 $entry = parseOptions(); 23} else { 24 // Classic interactive prompts 25 $entry = getEntry(); 26} 27 28$entry->save()->updateArchiveXML(); 29 30fwrite(STDOUT, "File saved.\nPlease git diff " . Entry::ARCHIVE_FILE_REL . " and sanity-check the changes before committing\n"); 31fwrite(STDOUT, "NOTE: Remember to git add " . Entry::ARCHIVE_ENTRIES_REL . $entry->getId() . ".xml !!\n"); 32 33// Implementation functions 34 35function getEntry(): Entry { 36 $entry = new Entry; 37 $entry->setTitle(getTitle()); 38 $entry->setCategories(selectCategories()); 39 if ($entry->isConference()) { 40 $entry->setConfTime(getConfTime()); 41 } 42 43 $image = getImage(); 44 $entry->setImage($image['path'] ?? '', $image['title'] ?? '', $image['link'] ?? ''); 45 46 $entry->setContent(getContent()); 47 48 return $entry; 49} 50 51function getTitle(): string { 52 do { 53 fwrite(STDOUT, "Please type in the title: "); 54 $title = rtrim(fgets(STDIN)); 55 } while(strlen($title)<3); 56 57 return $title; 58} 59 60function selectCategories(): array { for(;;) { 61 $ids = array_keys(Entry::CATEGORIES); 62 63 fwrite(STDOUT, "Categories:\n"); 64 foreach($ids as $n => $id) { 65 fprintf(STDOUT, "\t%d: %-11s\t [%s]\n", $n, Entry::CATEGORIES[$id], $id); 66 } 67 fwrite(STDOUT, "Please select appropriate categories, seperated with space: "); 68 69 // Filter to 0..n-1, then map to short names. 70 $cat = array_map( 71 function ($c) use ($ids) { 72 return $ids[$c]; 73 }, 74 array_filter( 75 explode(" ", rtrim(fgets(STDIN))), 76 function ($c) { 77 return is_numeric($c) && ($c >= 0) && ($c < count(Entry::CATEGORIES)); 78 }) 79 ); 80 81 // Special case, we don't allow items in both 'cfp' and 'conferences'. 82 if (count(array_intersect($cat, ['cfp', 'conferences'])) >= 2) { 83 fwrite(STDERR, "Pick either a CfP OR a conference\n"); 84 continue; 85 } 86 87 if (count($cat) == 0) { 88 fwrite(STDERR, "You have to pick at least one category\n"); 89 continue; 90 } 91 92 return $cat; 93}} 94 95function getConfTime(): int { for(;;) { 96 fwrite(STDOUT, "When does the conference start/cfp end? (strtotime() compatible syntax): "); 97 98 $t = strtotime(fgets(STDIN)); 99 if (!$t) { 100 fwrite(STDERR, "I told you I would run it through strtotime()!\n"); 101 continue; 102 } 103 104 return $t; 105}} 106 107function getImage(): ?array { 108 global $imageRestriction; 109 110 fwrite(STDOUT, "Will a picture be accompanying this entry? "); 111 $yn = fgets(STDIN); 112 113 114 if (strtoupper($yn[0]) !== "Y") { 115 return NULL; 116 } 117 118 for ($isValidImage = false; !$isValidImage;) { 119 fwrite(STDOUT, "Enter the image name (note: the image has to exist in './images/news'): "); 120 $path = basename(rtrim(fgets(STDIN))); 121 122 if (true === file_exists(Entry::PHPWEB . "/images/news/$path")) { 123 $isValidImage = true; 124 125 if (extension_loaded('gd')) { 126 break; 127 } 128 129 $imageSizes = getimagesize("./images/news/$path"); 130 131 if (($imageSizes[0] > $imageRestriction['width']) || ($imageSizes[1] > $imageRestriction['height'])) { 132 fwrite(STDOUT, "Provided image has a higher size than recommended (" . implode(' by ', $imageRestriction) . "). Continue? "); 133 $ynImg = fgets(STDIN); 134 if (strtoupper($ynImg[0]) !== "Y") { 135 $isValidImage = false; 136 } 137 } 138 } 139 } 140 141 fwrite(STDOUT, "Image title: "); 142 $title = rtrim(fgets(STDIN)); 143 144 fwrite(STDOUT, "Link (when clicked on the image): "); 145 $via = rtrim(fgets(STDIN)); 146 147 return [ 148 'title' => $title, 149 'link' => $via, 150 'path' => $path, 151 ]; 152} 153 154function getContent(): string { 155 fwrite(STDOUT, "And at last; paste/write your news item here.\nTo end it, hit <enter>.<enter>\n"); 156 $news = "\n"; 157 while(($line = rtrim(fgets(STDIN))) != ".") { 158 $news .= " $line\n"; 159 } 160 161 return $news; 162} 163 164function parseOptions(): Entry { 165 $opts = getopt('h', [ 166 'help', 167 'title:', 168 'category:', 169 'conf-time:', 170 'image-path:', 171 'image-title:', 172 'image-link:', 173 'content:', 174 'content-file:', 175 ]); 176 if (isset($opts['h']) || isset($opts['help'])) { 177 echo "Usage: {$_SERVER['argv'][0]} --title 'Name of event' --category cfp ( --content 'text' | --content-file '-') [...options]\n\n"; 178 echo " --title 'value' The title of the entry (required)\n"; 179 echo " --category 'value' 'frontpage', 'release', 'cfp', or 'conference' (required; may repeat)\n"; 180 echo " --conf-time 'value' When the event will be occurign (cfp and conference categories only)\n"; 181 echo " --content 'value' Text content for the entry, may include XHTML\n"; 182 echo " --content-file 'value' Name of file to load content from, may not be specified with --content\n"; 183 echo " --image-path 'value' Basename of image file in " . Entry::IMAGE_PATH_REL . "\n"; 184 echo " --image-title 'value' Title for the image provided\n"; 185 echo " --image-link 'value' URI to direct to when clicking the image\n"; 186 exit(0); 187 } 188 189 $entry = new Entry; 190 if (!isset($opts['title'])) { 191 fwrite(STDERR, "--title required\n"); 192 exit(1); 193 } 194 $entry->setTitle($opts['title']); 195 196 if (empty($opts['category'])) { 197 fwrite(STDERR, "--category required\n"); 198 exit(1); 199 } 200 if (is_string($opts['category'])) { 201 $opts['category'] = [ $opts['category'] ]; 202 } 203 foreach ($opts['category'] as $cat) { 204 $entry->addCategory($cat); 205 } 206 if ($entry->isConference()) { 207 if (empty($opts['conf-time'])) { 208 fwrite(STDERR, "--conf-time required for conferences\n"); 209 exit(1); 210 } 211 $t = strtotime($opts['conf-time']); 212 if (!is_int($t)) { 213 fwrite(STDERR, "Error parsing --conf-time\n"); 214 exit(1); 215 } 216 $entry->setConfTime($t); 217 } elseif (!empty($opts['conf-time'])) { 218 fwrite(STDERR, "--conf-time not allowed with non-conference events\n"); 219 exit(1); 220 } 221 222 $entry->setImage($opts['image-path'] ?? '', $opts['image-title'] ?? '', $opts['image-link'] ?? ''); 223 224 if (isset($opts['content'])) { 225 if (isset($opts['content-file'])) { 226 fwrite(STDERR, "--content and --content-file may not be specified together\n"); 227 exit(1); 228 } 229 $entry->setContent($opts['content']); 230 } elseif (isset($opts['content-file'])) { 231 if ($opts['content-file'] === '-') { 232 $entry->setContent(stream_get_contents(STDIN)); 233 } else { 234 $entry->setContent(file_get_contents($opts['content-file'])); 235 } 236 } else { 237 fwrite(STDERR, "--content or --content-file required\n"); 238 exit(1); 239 } 240 241 return $entry; 242} 243