Module::getConfig()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
c 0
b 0
f 0
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
/**
3
 * YAWIK
4
 * Auth Module Bootstrap
5
 *
6
 * @copyright (c) 2013 - 2016 Cross Solution (http://cross-solution.de)
7
 * @license   MIT
8
 */
9
10
namespace Pdf;
11
12
use Laminas\ServiceManager\ServiceManager;
13
use SplFileInfo;
14
use Laminas\View\Resolver\ResolverInterface;
15
use Laminas\View\Renderer\RendererInterface as Renderer;
16
use Laminas\Mvc\MvcEvent;
17
use Laminas\View\ViewEvent;
18
use Laminas\EventManager\EventManagerInterface;
19
use Core\Html2Pdf\PdfInterface;
20
use Core\View\Helper\InsertFile\FileEvent;
21
use Core\Entity\FileEntity;
22
use Core\ModuleManager\Feature\VersionProviderInterface;
23
use Core\ModuleManager\Feature\VersionProviderTrait;
24
use Core\ModuleManager\ModuleConfigLoader;
25
use Mpdf\Mpdf;
26
27
/**
28
 * Make HTML to PDF
29
 *
30
 */
31
class Module implements PdfInterface, ResolverInterface, VersionProviderInterface
32
{
33
    use VersionProviderTrait;
34
35
    const VERSION = \Core\Module::VERSION;
36
    const RENDER_FULL = 0;
37
    const RENDER_WITHOUT_PDF = 1;
38
    const RENDER_WITHOUT_ATTACHMENTS = 2;
39
40
    protected $serviceManager;
41
42
    protected $viewResolverAttached = false;
43
44
    protected $appendPDF = array();
45
    protected $appendImage = array();
46
47
48
    /**
49
    * Loads module specific configuration.
50
    *
51
    * @return array
52
    */
53 5
    public function getConfig()
54
    {
55 5
        return ModuleConfigLoader::load(__DIR__ . '/../config');
56
    }
57
58
    public static function factory(ServiceManager $serviceManager)
59
    {
60
        $module = new static();
61
        $module->serviceManager = $serviceManager;
62
        return $module;
63
    }
64
65 4
    public function onBootstrap(MvcEvent $e)
66
    {
67 4
        $eventManager = $e->getApplication()->getEventManager();
68 4
        $eventManager->getSharedManager()->attach(
69 4
            'Applications',
70 4
            'application.detail.actionbuttons',
71
            function ($event) {
72
                return 'pdf/application/details/button';
73 4
            }
74
        );
75
    }
76
77
    /**
78
     * hook into the rendering for transformation of HTML to PDF
79
     * @param \Laminas\EventManager\EventManagerInterface $events
80
     */
81
    public function attach(EventManagerInterface $events)
82
    {
83
        $events->attach(ViewEvent::EVENT_RENDERER_POST, array($this, 'cleanLayout'), 1);
84
        $events->attach(ViewEvent::EVENT_RESPONSE, array($this, 'attachPDFtransformer'), 10);
85
    }
86
87
    /**
88
     * hook into the MVC
89
     * in here you could still decide, if you want to hook into the Rendering
90
     * @param \Laminas\EventManager\EventManagerInterface $events
91
     */
92
    public function attachMvc(EventManagerInterface $events)
93
    {
94
        $events->attach(MvcEvent::EVENT_RENDER, array($this, 'initializeViewHelper'), 100);
95
    }
96
97
    /**
98
     * hook into the Rendering of files
99
     * the manager to hook in is the viewhelper 'insertfiles'
100
     *
101
     * @param \Laminas\Mvc\MvcEvent $e
102
     */
103
    public function initializeViewHelper(MvcEvent $e)
104
    {
105
        $viewhelperManager = $this->serviceManager->get('ViewHelperManager');
106
        if ($viewhelperManager->has('InsertFile')) {
107
            $insertFile = $viewhelperManager->get('InsertFile');
108
            $insertFile->attach(FileEvent::GETFILE, array($this, 'getFile'));
109
            $insertFile->attach(FileEvent::RENDERFILE, array($this, 'renderFile'));
110
            $insertFile->attach(FileEvent::INSERTFILE, array($this, 'collectFiles'));
111
        }
112
    }
113
114
    /**
115
     * proxy, in case that you just got a name and have to find the associated file-entity
116
     * maybe this is redundant and can be deprecated
117
     *
118
     * @param \Core\View\Helper\InsertFile\FileEvent $e
119
     * @return null
120
     */
121
    public function getFile(FileEvent $e)
122
    {
123
        $lastFileName = $e->getLastFileName();
124
        if (is_string($lastFileName)) {
125
            $repository = $this->serviceManager->get('repositories')->get('Applications/Attachment');
126
            $file       = $repository->find($lastFileName);
127
            if (isset($file)) {
128
                $e->setFileObject($lastFileName, $file);
129
                $e->stopPropagation();
130
                return $file;
131
            }
132
            return null;
133
        }
134
        // if it is not a string i do presume it is already a file-Object
135
        return $lastFileName;
136
    }
137
138
    /**
139
     * here the inserted File is rendered,
140
     * there is a lot which still can be done like outsorcing the HTML to a template,
141
     * or distinguish between different File Types,
142
     * at the moment we assume the $file is always an (sub-)instance of \Core\File\Entity
143
     *
144
     * @param \Core\View\Helper\InsertFile\FileEvent $e
145
     * @return string
146
     */
147
    public function renderFile(FileEvent $e)
148
    {
149
        $file = $e->getLastFileObject();
150
        // assume it is of the class Core\Entity\FileEntity
151
        $return = '<div class="col-md-3"><a href="#attachment_' . $file->getId() . '">' . $file->getName() . '</a></div>' . PHP_EOL
152
                . '<div class="col-md-3">' . $file->getType() . '</div>'
153
                . '<div class="col-md-3">' . $file->prettySize . '</div>';
154
        /*
155
         * this snippet was for direct inserting an image into the PDF
156
        if ($file && $file instanceOf FileEntity && 0 === strpos($file->getType(), 'image')) {
157
            //$content = $file->getContent();
158
            //$url = 'data:image/' . $file->getType() . ';base64,' . base64_encode ($content);
159
            //$html = '<img src="' . $url . '" >';
160
            $html = '<a href="#1">' . $file->getName() . '</a>';
161
            $e->stopPropagation();
162
            return $html;
163
        }
164
         */
165
        return $return;
166
    }
167
168
    /**
169
     * give a summary of all inserted Files,
170
     * this is for having access to those files in the post-process
171
     * @param \Core\View\Helper\InsertFile\FileEvent|\Laminas\View\ViewEvent $e
172
     * @return NULL
173
     */
174
    public function collectFiles(FileEvent $e)
175
    {
176
        $this->appendPDF = array();
177
        $files = $e->getAllFiles();
178
        foreach ($files as $name => $file) {
179
            if (!empty($file) && $file instanceof FileEntity) {
180
                if (0 === strpos($file->getType(), 'image')) {
181
                    $this->appendImage[] = $file;
182
                }
183
                if (strtolower($file->getType()) == 'application/pdf') {
184
                    $this->appendPDF[] = $file;
185
                }
186
            }
187
        }
188
        return null;
189
    }
190
191
    /**
192
     * remove unwanted or layout related data
193
     *
194
     * basically you rake through the viewmodel for the data you want to use for your template,
195
     * this may not be optimal because you have to rely on the correct naming of the viewmodels
196
     *
197
     * if you get the data you want, you switch to the specific template by adding the conforming resolver
198
     *
199
     * @param \Laminas\View\ViewEvent $e
200
     */
201
    public function cleanLayout(ViewEvent $e)
202
    {
203
        $result   = $e->getResult();
204
        $response = $e->getResponse();
205
        $model = $e->getModel();
206
        if ($model->hasChildren()) {
207
            $children = $model->getChildren();
208
            $content = null;
209
            foreach ($children as $child) {
210
                if ($child->captureTo() == 'content') {
211
                    $content = $child;
212
                    $this->attachViewResolver();
213
                }
214
            }
215
            if (!empty($content)) {
216
                $e->setModel($content);
217
            }
218
        } else {
219
            // attach the own resolver here too ?
220
            // ...
221
        }
222
    }
223
224
    /**
225
     * Attach an own ViewResolver
226
     */
227
    public function attachViewResolver()
228
    {
229
        if (!$this->viewResolverAttached) {
230
            $this->viewResolverAttached = true;
231
            $resolver = $this->serviceManager->get('ViewResolver');
232
            $resolver->attach($this, 100);
233
        }
234
    }
235
236
    /**
237
     * Transform the HTML to PDF,
238
     * this is a post-rendering-process
239
     *
240
     * put in here everything related to the transforming-process like options
241
     *
242
     * @param \Laminas\View\ViewEvent $e
243
     */
244
    public function attachPDFtransformer(ViewEvent $e)
245
    {
246
247
        //$renderer = $e->getRenderer();
248
        $result   = $e->getResult();
249
        $response = $e->getResponse();
250
251
        // the handles are for temporary files
252
        error_reporting(0);
253
        foreach (array(self::RENDER_FULL, self::RENDER_WITHOUT_PDF, self::RENDER_WITHOUT_ATTACHMENTS ) as $render) {
254
            $handles = array();
255
            try {
256
                $pdf = new Mpdf();
257
                //$pdf->SetImportUse();
258
                // create bookmark list in Acrobat Reader
259
                $pdf->h2bookmarks = array('H1' => 0, 'H2' => 1, 'H3' => 2);
260
                $pdf->WriteHTML($result);
261
262
                // Output of the Images
263
                if (self::RENDER_FULL == $render || self::RENDER_WITHOUT_PDF == $render) {
264
                    if (is_array($this->appendImage) && !empty($this->appendImage)) {
265
                        foreach ($this->appendImage as $imageAttachment) {
266
                            $content = $imageAttachment->getContent();
267
                            $url = 'data:image/' . $imageAttachment->getType() . ';base64,' . base64_encode($content);
268
                            $html = '<a name="attachment_' . $imageAttachment->getId() . '"><img src="' . $url . '" /><br /></a>';
269
                            $pdf->WriteHTML($html);
270
                        }
271
                    }
272
                }
273
274
                // Temp Files PDF
275
                if (self::RENDER_FULL == $render) {
276
                    if (is_array($this->appendPDF) && !empty($this->appendPDF)) {
277
                        foreach ($this->appendPDF as $pdfAttachment) {
278
                            $content = $pdfAttachment->getContent();
279
                            $tmpHandle = tmpfile();
280
                            $handles[] = $tmpHandle;
281
                            fwrite($tmpHandle, $content);
282
                            fseek($tmpHandle, 0);
283
                        }
284
                    }
285
                }
286
287
                // Output of the PDF
288
                foreach ($handles as $handle) {
289
                    $meta_data = stream_get_meta_data($handle);
290
                    $filename = $meta_data["uri"];
291
                    $pdf->WriteHTML($filename);
292
                    $pagecount = $pdf->SetSourceFile($filename);
293
                    for ($pages = 0; $pages < $pagecount; $pages++) {
294
                        $pdf->AddPage();
295
                        $pdf->WriteHTML(' pages: ' . $pagecount);
296
                        $tx = $pdf->ImportPage($pages + 1);
297
                        $pdf->UseTemplate($tx);
298
                    }
299
                }
300
301
                $pdf_result = $pdf->Output();
302
                $e->setResult($pdf_result);
303
304
                // delete all temporary Files again
305
                foreach ($handles as $handle) {
306
                    fclose($handle);
307
                }
308
                break;
309
            } catch (\Exception $e) {
310
            }
311
        }
312
        error_reporting(E_ALL);
313
    }
314
315
    /**
316
     * Look for a template with the Suffix ".pdf.phtml"
317
     *
318
     * @param string $name
319
     * @param \Laminas\View\Renderer\RendererInterface $renderer
320
     * @return string|boolean
321
     */
322
    public function resolve($name, Renderer $renderer = null)
323
    {
324
        if ($this->serviceManager->has('ViewTemplatePathStack')) {
325
            // get all the Pases made up for the zend-provided resolver
326
            // we won't get any closer to ALL than that
327
            $viewTemplatePathStack = $this->serviceManager->get('ViewTemplatePathStack');
328
            $paths = $viewTemplatePathStack->getPaths();
329
            $defaultSuffix = $viewTemplatePathStack->getDefaultSuffix();
330
            if (pathinfo($name, PATHINFO_EXTENSION) != $defaultSuffix) {
331
                ;
332
                $name .= '.pdf.' . $defaultSuffix;
333
            } else {
334
                // TODO: replace Filename by Filename for PDF
335
            }
336
337
            foreach ($paths as $path) {
338
                $file = new SplFileInfo($path . $name);
339
                if ($file->isReadable()) {
340
                    // Found! Return it.
341
                    if (($filePath = $file->getRealPath()) === false && substr($path, 0, 7) === 'phar://') {
342
                        // Do not try to expand phar paths (realpath + phars == fail)
343
                        $filePath = $path . $name;
344
                        if (!file_exists($filePath)) {
345
                            break;
346
                        }
347
                    }
348
                    //if ($this->useStreamWrapper()) {
349
                    //    // If using a stream wrapper, prepend the spec to the path
350
                    //    $filePath = 'zend.view://' . $filePath;
351
                    //}
352
                    return $filePath;
353
                }
354
            }
355
        }
356
        // TODO: Resolving to an PDF has failed, this could have implications for the transformer
357
        return false;
358
    }
359
}
360