xref: /web-php/bin/createNewsEntry (revision 9482f9bd)
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