1 : <?php
2 : /**
3 : * Roman de Renart
4 : *
5 : * PHP version 5
6 : *
7 : * @category Rdr
8 : * @package Edit
9 : * @author Michel Corne <mcorne@yahoo.com>
10 : * @copyright 2010 Michel Corne
11 : * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
12 : * @link http://roman-de-renart.blogspot.com/
13 : * @version SVN: $Id$
14 : */
15 :
16 : require_once 'Episode.php';
17 : require_once 'TableContents.php';
18 :
19 : /**
20 : * Writing an episode for loading in a blog message
21 : *
22 : * @category Rdr
23 : * @package Edit
24 : * @author Michel Corne <mcorne@yahoo.com>
25 : * @copyright 2010 Michel Corne
26 : * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
27 : */
28 :
29 : class Write extends Episode
30 : {
31 : /**
32 : * The error message reported when there is no gothic letter image
33 : */
34 : const ERR_NO_GOTHIC_LETTER = 'no gothic letter';
35 :
36 : /**
37 : * The name of the file storing the list of gothic letter image URL
38 : */
39 : const GOTHIC_LETTERS_FILE = 'gothic-letters.php';
40 :
41 : /**
42 : * The message reported when the episode is written
43 : */
44 : const MSG_EPISODE_WRITTEN = 'Episode written into: %s';
45 :
46 : /**
47 : * The name of the file storing the list of gothic letter image URL
48 : * @var string
49 : */
50 : public $gothicLetterFile;
51 :
52 : /**
53 : * Constructor
54 : *
55 : * @param array $config the configuration directives
56 : * @param boolean $setFileNames sets the names of the working files if true, no setting if false
57 : * @return void
58 : */
59 : public function __construct($config, $setFileNames = true)
60 : {
61 10 : parent::__construct($config, false);
62 :
63 10 : $this->setFileNames($setFileNames);
64 :
65 10 : }
66 :
67 : /**
68 : * Sets default details for a new episode
69 : *
70 : * @return array the episode details
71 : * @access public
72 : */
73 : public function makeNewEpisode()
74 : {
75 2 : $episode = $this->episodeDefault;
76 2 : $episode['links-top'] = $episode['links-bottom'] = $this->linksDefault;
77 :
78 2 : return $episode;
79 : }
80 :
81 : /**
82 : * Sets the names of the working files
83 : *
84 : * @param string $setFileNames sets episode file names if true, no setting otherwise
85 : * @return void
86 : */
87 : public function setFileNames($setFileNames = true)
88 : {
89 10 : $this->gothicLetterFile = $this->makeFilePath(self::GOTHIC_LETTERS_FILE, 'data-dir');
90 10 : $setFileNames and parent::setFileNames();
91 10 : }
92 :
93 : /**
94 : * Writes the episode from the PHP working file and worksheet into the HTML output file
95 : *
96 : * @return string a message reporting that the episode is written
97 : * @access public
98 : */
99 : public function writeEpisode()
100 : {
101 : // reads the worsheet
102 1 : $this->readSheet();
103 : // reads the episode details from the PHP working file or
104 : // the default settings if this is a new episode
105 1 : $isNewEpisode = $this->episode == $this->newEpisode;
106 1 : $episode = $isNewEpisode? $this->makeNewEpisode() : $this->includeFile($this->workingFile);
107 :
108 : // updates the episode details with the worksheet data
109 1 : $episode = array_merge($episode, $this->readColumns($this->columnNamesToNumbers));
110 :
111 1 : $episode = $this->writeGothicLetter($episode);
112 1 : $episode = $this->writeNoteId($episode);
113 1 : $episode = $this->writeLinks($episode, $isNewEpisode);
114 :
115 : // creates the HTML content of the first line of each text
116 1 : $episode = $this->writeText($episode, 'fro-first-line', 'fro-text', true);
117 1 : $episode = $this->writeText($episode, 'trans-first-line', 'trans-text');
118 1 : $episode = $this->writeNumbers($episode);
119 :
120 : // creates the HTML content of the lists
121 1 : $episode = $this->arrayMapKeys('writeList', $episode, array(
122 1 : 'questions',
123 1 : 'mapping',
124 1 : 'differences',
125 1 : ));
126 :
127 : // creates the HTML content of the Meon and Martin texts and line numbers
128 1 : $episode = $this->arrayMapKeys('writeLines', $episode, array(
129 1 : 'meon-numbers',
130 1 : 'meon-text',
131 1 : 'martin-chapters',
132 1 : 'martin-numbers',
133 1 : 'martin-text',
134 1 : 'fro-numbers',
135 1 : ));
136 :
137 : // creates the HTML content of the episode
138 1 : $episodeContent = vsprintf(Episode::EPISODE_TPL, $episode);
139 1 : $episodeContent = sprintf(Episode::CONTAINER_TPL, $episodeContent);
140 :
141 : // adds non-breaking spaces before some punctuation characters
142 1 : $episodeContent = $this->addNbsp($episodeContent);
143 : // writes the episode into the HTML output file
144 1 : $this->writeFile($this->outputFile, $episodeContent);
145 :
146 1 : return sprintf(self::MSG_EPISODE_WRITTEN, basename($this->outputFile));
147 : }
148 :
149 : /**
150 : * Writes the name of gothic letter image file in the episode details
151 : *
152 : * @param array $episode the episode details
153 : * @return array the updated episode details
154 : * @access public
155 : */
156 : public function writeGothicLetter($episode)
157 : {
158 2 : $gothicLetters = $this->includeFile($this->gothicLetterFile);
159 :
160 2 : $firstLetter = $episode['fro-text'][0][0];
161 2 : isset($gothicLetters[$firstLetter]) or $this->abort(self::ERR_NO_GOTHIC_LETTER);
162 2 : $episode['letter-src'] = $gothicLetters[$firstLetter];
163 :
164 2 : return $episode;
165 : }
166 :
167 : /**
168 : * Writes text lines in HTML
169 : *
170 : * @param array $lines the lines to write in HTML
171 : * @return string the lines in HTML
172 : * @access public
173 : */
174 : public function writeLines($lines)
175 : {
176 4 : return implode(Episode::LINE_SEPARATOR . "\n", $lines);
177 : }
178 :
179 : /**
180 : * Writes the links details in HTML in the episode details
181 : *
182 : * @param array $episode the episode details
183 : * @param bool $isNewEpisode true if this is a new episode, false otherwise
184 : * @return array the updated episode details
185 : * @access public
186 : */
187 : public function writeLinks($episode, $isNewEpisode)
188 : {
189 : // gets the link default details
190 2 : $links = $this->linksDefault;
191 : // extracts the episode name
192 2 : $episodeName = $isNewEpisode? null : basename($this->episode['path'], '.html');
193 2 : $tableContents = new TableContents($this->config);
194 :
195 : // finds the previousn current and next stories
196 2 : list($links['prev-story-title'], $links['prev-story-url']) =
197 2 : $tableContents->findPreviousStory($episodeName);
198 2 : list($links['curr-story-title'], $links['curr-story-url']) =
199 2 : $tableContents->findCurrentStory($episodeName);
200 2 : list($links['next-story-title'], $links['next-story-url']) =
201 2 : $tableContents->findNextStory($episodeName);
202 :
203 : // finds the previous and next episodes
204 2 : $links['prev-episode-url'] = $tableContents->findPreviousEpisode($episodeName);
205 2 : $links['next-episode-url'] = $tableContents->findNextEpisode($episodeName);
206 :
207 2 : $episode['links-bottom'] = $episode['links-top'] = vsprintf(Episode::LINKS_TPL, $links);
208 :
209 2 : return $episode;
210 : }
211 :
212 : /**
213 : * Writes a list in HTML
214 : *
215 : * @param array $list the list details
216 : * @return mixed the list in HTML
217 : * @access public
218 : */
219 : public function writeList($list)
220 : {
221 2 : $list = array_filter($list);
222 :
223 2 : return array_reduce($list, array($this, 'writeListItem'));
224 : }
225 :
226 : /**
227 : * Writes a list item in HTML
228 : *
229 : * Typically used as a callback for array_reduce.
230 : *
231 : * @param string $list the concatenated list in HTML
232 : * @param string $listItem a list item
233 : * @return string the concatenated list updated with the list item
234 : * @access public
235 : */
236 : public function writeListItem($list, $listItem)
237 : {
238 3 : $list .= sprintf(Episode::LIST_TPL . "\n", $listItem);
239 :
240 3 : return $list;
241 : }
242 :
243 : /**
244 : * Writes the translation note identifier in the episode details
245 : *
246 : * @param array $episode the episode details
247 : * @return array the updated episode details
248 : * @access public
249 : */
250 : public function writeNoteId($episode)
251 : {
252 2 : $episode['notes-id1'] = $episode['notes-id0'] = $episode['fro-numbers'][0];
253 :
254 2 : return $episode;
255 : }
256 :
257 : /**
258 : * Writes the text line numbers in HTML in the episode details
259 : *
260 : * Only line numbers multiple of 4 are written.
261 : *
262 : * @param array $episode the episode details
263 : * @return array the updated episode details
264 : * @access public
265 : */
266 : public function writeNumbers($episode)
267 : {
268 2 : $numbers = $episode['fro-numbers'];
269 2 : array_shift($numbers);
270 :
271 2 : foreach($numbers as &$number) {
272 2 : $number % 4 and $number = '';
273 2 : }
274 :
275 2 : $episode['blog-numbers'] = $this->writeLines($numbers);
276 :
277 2 : return $episode;
278 : }
279 :
280 : /**
281 : * Writes a text in HTML in the episode details
282 : *
283 : * @param array $episode the episode details
284 : * @param string $firstLineKey the key of the fist line
285 : * @param string $textKey the key or name of the text
286 : * @param boolean $removeFirstChar the first character is to be removed if true, kept if false
287 : * @return array the updated episode details
288 : * @access public
289 : */
290 : public function writeText($episode, $firstLineKey, $textKey, $removeFirstChar = false)
291 : {
292 2 : $text = $episode[$textKey];
293 :
294 : // extracts the first line from the text
295 2 : $firstLine = array_shift($text);
296 : // removes the first character if requested
297 2 : $removeFirstChar and $firstLine = substr($firstLine, 1);
298 : // adds the line-breaks to the first line
299 2 : $breaks = str_repeat(Episode::LINE_SEPARATOR, count($episode[$firstLineKey]['breaks']));
300 2 : $episode[$firstLineKey] = $breaks . $firstLine;
301 : // writes the text line in HTML
302 2 : $episode[$textKey] = $this->writeLines($text);
303 :
304 2 : return $episode;
305 : }
|