|
1
|
|
|
<?php |
|
2
|
|
|
/* |
|
3
|
|
|
* This file is part of the trefoil application. |
|
4
|
|
|
* |
|
5
|
|
|
* (c) Miguel Angel Gabriel <[email protected]> |
|
6
|
|
|
* |
|
7
|
|
|
* For the full copyright and license information, please view the LICENSE |
|
8
|
|
|
* file that was distributed with this source code. |
|
9
|
|
|
*/ |
|
10
|
|
|
|
|
11
|
|
|
namespace Trefoil\Publishers; |
|
12
|
|
|
|
|
13
|
|
|
use Easybook\Publishers\BasePublisher as EasybookBasePublisher; |
|
14
|
|
|
use Symfony\Component\Finder\Finder; |
|
15
|
|
|
use Trefoil\Util\Toolkit; |
|
16
|
|
|
|
|
17
|
|
|
abstract class BasePublisher extends EasybookBasePublisher |
|
18
|
|
|
{ |
|
19
|
|
|
|
|
20
|
|
|
/** |
|
21
|
|
|
* It controls the book publishing workflow for this particular publisher. |
|
22
|
|
|
*/ |
|
23
|
32 |
|
public function publishBook() |
|
24
|
|
|
{ |
|
25
|
32 |
|
$this->filterContents(); |
|
26
|
|
|
|
|
27
|
32 |
|
parent::publishBook(); |
|
28
|
32 |
|
} |
|
29
|
|
|
|
|
30
|
32 |
|
public function parseContents() |
|
31
|
|
|
{ |
|
32
|
32 |
|
parent::parseContents(); |
|
33
|
|
|
|
|
34
|
|
|
// Plugins may want to remove some content item. |
|
35
|
|
|
// Remove items with 'remove' property set to true. |
|
36
|
32 |
|
$items = array(); |
|
37
|
32 |
|
foreach ($this->app['publishing.items'] as $item) { |
|
38
|
32 |
|
$include = !isset($item['remove']) || (isset($item['remove']) && !$item['remove']); |
|
39
|
32 |
|
if ($include) { |
|
40
|
32 |
|
$items[] = $item; |
|
41
|
32 |
|
} |
|
42
|
32 |
|
} |
|
43
|
|
|
|
|
44
|
32 |
|
$this->app['publishing.items'] = $items; |
|
45
|
32 |
|
} |
|
46
|
|
|
|
|
47
|
|
|
/** |
|
48
|
|
|
* It prepares the book images by copying them into the appropriate |
|
49
|
|
|
* temporary directory. It also prepares an array with all the images |
|
50
|
|
|
* data needed later to generate the full ebook contents manifest. |
|
51
|
|
|
* |
|
52
|
|
|
* @param string $targetDir The directory where the images are copied. |
|
53
|
|
|
* |
|
54
|
|
|
* @throws \RuntimeException |
|
55
|
|
|
* @return array Images data needed to create the book manifest. |
|
56
|
|
|
*/ |
|
57
|
32 |
|
protected function prepareBookImages($targetDir) |
|
58
|
|
|
{ |
|
59
|
32 |
View Code Duplication |
if (!file_exists($targetDir)) { |
|
60
|
|
|
throw new \RuntimeException( |
|
61
|
|
|
sprintf( |
|
62
|
|
|
" ERROR: Books images couldn't be copied because \n" |
|
63
|
|
|
. " the given '%s' \n" |
|
64
|
|
|
. " directory doesn't exist.", |
|
65
|
|
|
$targetDir |
|
66
|
|
|
) |
|
67
|
|
|
); |
|
68
|
|
|
} |
|
69
|
|
|
|
|
70
|
32 |
|
$edition = $this->app['publishing.edition']; |
|
71
|
32 |
|
$format = Toolkit::getCurrentFormat($this->app); |
|
72
|
|
|
|
|
73
|
|
|
// construct the list of source directories for images. |
|
74
|
|
|
// they will be used sequentially, so images inside each one will override previous images. |
|
75
|
32 |
|
$sourceDirs = array(); |
|
76
|
|
|
|
|
77
|
|
|
// images into the Resources directory of the <format> directory of the current theme |
|
78
|
|
|
// (which can be set via command line argument): |
|
79
|
|
|
// <current-theme-dir>/<current-theme>/<format>/Resources/images/ |
|
80
|
|
|
// where <current_theme_dir> can be either |
|
81
|
|
|
// <trefoil-dir>/app/Resources/Themes/ |
|
82
|
|
|
// or |
|
83
|
|
|
// <the path set with the "--dir" publish command line argument> |
|
84
|
|
|
// 'Common' format takes precedence |
|
85
|
32 |
|
$sourceDirs[] = Toolkit::getCurrentResourcesDir($this->app, 'Common') . '/images'; |
|
86
|
32 |
|
$sourceDirs[] = Toolkit::getCurrentResourcesDir($this->app) . '/images'; |
|
87
|
|
|
|
|
88
|
|
|
// theme images can be overriden by the book: |
|
89
|
|
|
// <book-dir>/Resources/images/ |
|
90
|
32 |
|
$sourceDirs[] = sprintf('%s/images', $this->app['publishing.dir.resources']); |
|
91
|
|
|
// <book-dir>/Resources/images/<edition-format>/ |
|
92
|
32 |
|
$sourceDirs[] = sprintf('%s/images/%s', $this->app['publishing.dir.resources'], $format); |
|
93
|
|
|
// <book-dir>/Resources/images/<edition-name>/ |
|
94
|
32 |
|
$sourceDirs[] = sprintf('%s/images/%s', $this->app['publishing.dir.resources'], $edition); |
|
95
|
|
|
|
|
96
|
|
|
// the normal book images: |
|
97
|
|
|
// <book-dir>/images/ |
|
98
|
32 |
|
$sourceDirs[] = $this->app['publishing.dir.contents'] . '/images'; |
|
99
|
|
|
|
|
100
|
|
|
// process each directory in sequence, so each one will override the previously copied images |
|
101
|
32 |
|
$imagesData = array(); |
|
102
|
32 |
|
$i = 1; |
|
103
|
32 |
|
foreach ($sourceDirs as $imagesDir) { |
|
104
|
|
|
|
|
105
|
32 |
|
if (file_exists($imagesDir)) { |
|
106
|
|
|
|
|
107
|
13 |
|
$images = Finder::create() |
|
108
|
32 |
|
->files() |
|
109
|
13 |
|
->sortByName() |
|
110
|
13 |
|
->in($imagesDir); |
|
111
|
|
|
|
|
112
|
13 |
|
foreach ($images as $image) { |
|
113
|
|
|
|
|
114
|
12 |
|
$this->app['filesystem']->copy( |
|
115
|
12 |
|
$image->getPathName(), |
|
116
|
12 |
|
$targetDir . '/' . $image->getFileName(), |
|
117
|
|
|
true // overwrite |
|
118
|
12 |
|
); |
|
119
|
|
|
|
|
120
|
|
|
// The right mediatype for jpeg images is jpeg, not jpg |
|
121
|
12 |
|
$mediaType = pathinfo($image->getFilename(), PATHINFO_EXTENSION); |
|
122
|
12 |
|
$mediaType = str_replace('jpg', 'jpeg', $mediaType); |
|
123
|
|
|
|
|
124
|
12 |
|
$imagesData[$image->getFileName()] = array( |
|
125
|
12 |
|
'id' => 'image-' . $i++, |
|
126
|
12 |
|
'filePath' => 'images/' . $image->getFileName(), |
|
127
|
|
|
'mediaType' => 'image/' . $mediaType |
|
128
|
12 |
|
); |
|
129
|
13 |
|
} |
|
130
|
13 |
|
} |
|
131
|
32 |
|
} |
|
132
|
|
|
|
|
133
|
32 |
|
return $imagesData; |
|
134
|
|
|
} |
|
135
|
|
|
|
|
136
|
|
|
/** |
|
137
|
|
|
* Retrieve the custom css file to be used with this book |
|
138
|
|
|
* |
|
139
|
|
|
* @return null|string |
|
140
|
|
|
*/ |
|
141
|
32 |
|
protected function getCustomCssFile() |
|
142
|
|
|
{ |
|
143
|
|
|
// try the text file "style.css" |
|
144
|
32 |
|
$customCss = $this->app->getCustomTemplate('style.css'); |
|
145
|
32 |
|
if ($customCss) { |
|
146
|
7 |
|
return $customCss; |
|
147
|
|
|
} |
|
148
|
|
|
|
|
149
|
|
|
// try the Twig template "style.css.twig" |
|
150
|
25 |
|
$customCss = $this->app->getCustomTemplate('style.css.twig'); |
|
151
|
25 |
|
if ($customCss) { |
|
152
|
|
|
return $customCss; |
|
153
|
|
|
} |
|
154
|
|
|
|
|
155
|
25 |
|
return null; |
|
156
|
|
|
} |
|
157
|
|
|
|
|
158
|
|
|
/** |
|
159
|
|
|
* Filters out the content items based on certain conditions. |
|
160
|
|
|
* |
|
161
|
|
|
* - publising edition: if the item has "editions" array, it will only be included |
|
162
|
|
|
* if edition is in "editions" array. Prefixing it with "!" means "not for that |
|
163
|
|
|
* edition". |
|
164
|
|
|
* |
|
165
|
|
|
* - publising edition format: if the item has "formats" array, it will only be included |
|
166
|
|
|
* if the edition format is in "formats" array. Prefixing it with "!" means "not for that |
|
167
|
|
|
* format". |
|
168
|
|
|
*/ |
|
169
|
32 |
|
protected function filterContents() |
|
170
|
|
|
{ |
|
171
|
32 |
|
$newContents = []; |
|
172
|
|
|
|
|
173
|
32 |
|
$edition = strtolower($this->app['publishing.edition']); |
|
174
|
32 |
|
$format = strtolower(Toolkit::getCurrentFormat($this->app)); |
|
175
|
|
|
|
|
176
|
|
|
// by default, all content items are included |
|
177
|
32 |
|
foreach ($this->app->book('contents') as $itemConfig) { |
|
178
|
|
|
|
|
179
|
32 |
|
$contentFilters = $this->extractContentFilters($itemConfig); |
|
180
|
|
|
|
|
181
|
|
|
// omit editions not in "editions" array |
|
182
|
32 |
|
if (count($contentFilters['editions']) && !in_array($edition, $contentFilters['editions'])) { |
|
183
|
3 |
|
continue; |
|
184
|
|
|
} |
|
185
|
|
|
|
|
186
|
|
|
// omit editions in "not-editions" array |
|
187
|
32 |
|
if (count($contentFilters['not-editions']) && in_array($edition, $contentFilters['not-editions'])) { |
|
188
|
1 |
|
continue; |
|
189
|
32 |
|
} |
|
190
|
|
|
|
|
191
|
|
|
// omit editions which format is not in "formats" array |
|
192
|
32 |
|
if (count($contentFilters['formats']) && !in_array($format, $contentFilters['formats'])) { |
|
193
|
2 |
|
continue; |
|
194
|
|
|
} |
|
195
|
|
|
|
|
196
|
|
|
// omit editions which format is in "not-formats" array |
|
197
|
32 |
|
if (count($contentFilters['not-formats']) && in_array($format, $contentFilters['not-formats'])) { |
|
198
|
4 |
|
continue; |
|
199
|
|
|
} |
|
200
|
|
|
|
|
201
|
32 |
|
$newContents[] = $itemConfig; |
|
202
|
32 |
|
} |
|
203
|
|
|
|
|
204
|
32 |
|
$this->app->book('contents', $newContents); |
|
205
|
32 |
|
} |
|
206
|
|
|
|
|
207
|
|
|
/** |
|
208
|
|
|
* Returns an array of content filters. |
|
209
|
|
|
* |
|
210
|
|
|
* @param $itemConfig |
|
211
|
|
|
* |
|
212
|
|
|
* @return array filters |
|
213
|
|
|
*/ |
|
214
|
32 |
|
protected function extractContentFilters($itemConfig) |
|
215
|
|
|
{ |
|
216
|
|
|
$contentFilters = array( |
|
217
|
32 |
|
'editions' => array(), |
|
218
|
32 |
|
'not-editions' => array(), |
|
219
|
32 |
|
'formats' => array(), |
|
220
|
32 |
|
'not-formats' => array() |
|
221
|
32 |
|
); |
|
222
|
|
|
|
|
223
|
32 |
View Code Duplication |
if (isset($itemConfig['editions'])) { |
|
|
|
|
|
|
224
|
|
|
|
|
225
|
4 |
|
foreach ($itemConfig['editions'] as $ed) { |
|
226
|
4 |
|
if (substr($ed, 0, 1) === '!') { |
|
227
|
4 |
|
$contentFilters['not-editions'][] = substr($ed, 1); |
|
228
|
4 |
|
} else { |
|
229
|
4 |
|
$contentFilters['editions'][] = $ed; |
|
230
|
|
|
} |
|
231
|
4 |
|
} |
|
232
|
4 |
|
} |
|
233
|
|
|
|
|
234
|
32 |
View Code Duplication |
if (isset($itemConfig['formats'])) { |
|
|
|
|
|
|
235
|
|
|
|
|
236
|
4 |
|
foreach ($itemConfig['formats'] as $fm) { |
|
237
|
4 |
|
if (substr($fm, 0, 1) === '!') { |
|
238
|
4 |
|
$contentFilters['not-formats'][] = substr($fm, 1); |
|
239
|
4 |
|
} else { |
|
240
|
4 |
|
$contentFilters['formats'][] = $fm; |
|
241
|
|
|
} |
|
242
|
4 |
|
} |
|
243
|
4 |
|
} |
|
244
|
|
|
|
|
245
|
32 |
|
return $contentFilters; |
|
246
|
|
|
} |
|
247
|
|
|
|
|
248
|
|
|
} |
|
249
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.