#!/usr/bin/env php 400, 'height' => 250 ]; // Create an entry! if (!file_exists(Entry::ARCHIVE_FILE_ABS)) { fwrite(STDERR, "Can't find " . Entry::ARCHIVE_FILE_REL . ", are you sure you are in phpweb/?\n"); exit(1); } if ($_SERVER['argc'] > 1) { // getopt based non-interactive mode $entry = parseOptions(); } else { // Classic interactive prompts $entry = getEntry(); } $entry->save()->updateArchiveXML(); fwrite(STDOUT, "File saved.\nPlease git diff " . Entry::ARCHIVE_FILE_REL . " and sanity-check the changes before committing\n"); fwrite(STDOUT, "NOTE: Remember to git add " . Entry::ARCHIVE_ENTRIES_REL . $entry->getId() . ".xml !!\n"); // Implementation functions function getEntry(): Entry { $entry = new Entry; $entry->setTitle(getTitle()); $entry->setCategories(selectCategories()); if ($entry->isConference()) { $entry->setConfTime(getConfTime()); } $image = getImage(); $entry->setImage($image['path'] ?? '', $image['title'] ?? '', $image['link'] ?? ''); $entry->setContent(getContent()); return $entry; } function getTitle(): string { do { fwrite(STDOUT, "Please type in the title: "); $title = rtrim(fgets(STDIN)); } while(strlen($title)<3); return $title; } function selectCategories(): array { for(;;) { $ids = array_keys(Entry::CATEGORIES); fwrite(STDOUT, "Categories:\n"); foreach($ids as $n => $id) { fprintf(STDOUT, "\t%d: %-11s\t [%s]\n", $n, Entry::CATEGORIES[$id], $id); } fwrite(STDOUT, "Please select appropriate categories, seperated with space: "); // Filter to 0..n-1, then map to short names. $cat = array_map( function ($c) use ($ids) { return $ids[$c]; }, array_filter( explode(" ", rtrim(fgets(STDIN))), function ($c) { return is_numeric($c) && ($c >= 0) && ($c < count(Entry::CATEGORIES)); }) ); // Special case, we don't allow items in both 'cfp' and 'conferences'. if (count(array_intersect($cat, ['cfp', 'conferences'])) >= 2) { fwrite(STDERR, "Pick either a CfP OR a conference\n"); continue; } if (count($cat) == 0) { fwrite(STDERR, "You have to pick at least one category\n"); continue; } return $cat; }} function getConfTime(): int { for(;;) { fwrite(STDOUT, "When does the conference start/cfp end? (strtotime() compatible syntax): "); $t = strtotime(fgets(STDIN)); if (!$t) { fwrite(STDERR, "I told you I would run it through strtotime()!\n"); continue; } return $t; }} function getImage(): ?array { global $imageRestriction; fwrite(STDOUT, "Will a picture be accompanying this entry? "); $yn = fgets(STDIN); if (strtoupper($yn[0]) !== "Y") { return NULL; } for ($isValidImage = false; !$isValidImage;) { fwrite(STDOUT, "Enter the image name (note: the image has to exist in './images/news'): "); $path = basename(rtrim(fgets(STDIN))); if (true === file_exists(Entry::PHPWEB . "/images/news/$path")) { $isValidImage = true; if (extension_loaded('gd')) { break; } $imageSizes = getimagesize("./images/news/$path"); if (($imageSizes[0] > $imageRestriction['width']) || ($imageSizes[1] > $imageRestriction['height'])) { fwrite(STDOUT, "Provided image has a higher size than recommended (" . implode(' by ', $imageRestriction) . "). Continue? "); $ynImg = fgets(STDIN); if (strtoupper($ynImg[0]) !== "Y") { $isValidImage = false; } } } } fwrite(STDOUT, "Image title: "); $title = rtrim(fgets(STDIN)); fwrite(STDOUT, "Link (when clicked on the image): "); $via = rtrim(fgets(STDIN)); return [ 'title' => $title, 'link' => $via, 'path' => $path, ]; } function getContent(): string { fwrite(STDOUT, "And at last; paste/write your news item here.\nTo end it, hit .\n"); $news = "\n"; while(($line = rtrim(fgets(STDIN))) != ".") { $news .= " $line\n"; } return $news; } function parseOptions(): Entry { $opts = getopt('h', [ 'help', 'title:', 'category:', 'conf-time:', 'image-path:', 'image-title:', 'image-link:', 'content:', 'content-file:', ]); if (isset($opts['h']) || isset($opts['help'])) { echo "Usage: {$_SERVER['argv'][0]} --title 'Name of event' --category cfp ( --content 'text' | --content-file '-') [...options]\n\n"; echo " --title 'value' The title of the entry (required)\n"; echo " --category 'value' 'frontpage', 'release', 'cfp', or 'conference' (required; may repeat)\n"; echo " --conf-time 'value' When the event will be occurign (cfp and conference categories only)\n"; echo " --content 'value' Text content for the entry, may include XHTML\n"; echo " --content-file 'value' Name of file to load content from, may not be specified with --content\n"; echo " --image-path 'value' Basename of image file in " . Entry::IMAGE_PATH_REL . "\n"; echo " --image-title 'value' Title for the image provided\n"; echo " --image-link 'value' URI to direct to when clicking the image\n"; exit(0); } $entry = new Entry; if (!isset($opts['title'])) { fwrite(STDERR, "--title required\n"); exit(1); } $entry->setTitle($opts['title']); if (empty($opts['category'])) { fwrite(STDERR, "--category required\n"); exit(1); } if (is_string($opts['category'])) { $opts['category'] = [ $opts['category'] ]; } foreach ($opts['category'] as $cat) { $entry->addCategory($cat); } if ($entry->isConference()) { if (empty($opts['conf-time'])) { fwrite(STDERR, "--conf-time required for conferences\n"); exit(1); } $t = strtotime($opts['conf-time']); if (!is_int($t)) { fwrite(STDERR, "Error parsing --conf-time\n"); exit(1); } $entry->setConfTime($t); } elseif (!empty($opts['conf-time'])) { fwrite(STDERR, "--conf-time not allowed with non-conference events\n"); exit(1); } $entry->setImage($opts['image-path'] ?? '', $opts['image-title'] ?? '', $opts['image-link'] ?? ''); if (isset($opts['content'])) { if (isset($opts['content-file'])) { fwrite(STDERR, "--content and --content-file may not be specified together\n"); exit(1); } $entry->setContent($opts['content']); } elseif (isset($opts['content-file'])) { if ($opts['content-file'] === '-') { $entry->setContent(stream_get_contents(STDIN)); } else { $entry->setContent(file_get_contents($opts['content-file'])); } } else { fwrite(STDERR, "--content or --content-file required\n"); exit(1); } return $entry; }