~xibo-maintainers/xibo/tempel

« back to all changes in this revision

Viewing changes to lib/Widget/ModuleWidget.php

  • Committer: Dan Garner
  • Date: 2016-02-12 10:41:25 UTC
  • mto: (454.4.130)
  • mto: This revision was merged to the branch mainline in revision 484.
  • Revision ID: git-v1:ca673f8ea522eac5f311ed779b0fbfeb35a0e4dd
Handle duration changes in XLF generation. Fixed region option factory.
xibosignage/xibo#721

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 */
21
21
namespace Xibo\Widget;
22
22
 
23
 
use Intervention\Image\ImageManagerStatic as Img;
24
 
use Mimey\MimeTypes;
25
23
use Slim\Slim;
26
 
use Stash\Interfaces\PoolInterface;
27
 
use Stash\Invalidation;
28
 
use Stash\Item;
29
 
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
30
 
use Xibo\Entity\Media;
31
24
use Xibo\Entity\User;
32
25
use Xibo\Exception\ControllerNotImplemented;
33
 
use Xibo\Exception\InvalidArgumentException;
34
26
use Xibo\Exception\NotFoundException;
35
 
use Xibo\Exception\XiboException;
36
 
use Xibo\Factory\CommandFactory;
37
 
use Xibo\Factory\DataSetColumnFactory;
38
 
use Xibo\Factory\DataSetFactory;
39
 
use Xibo\Factory\DisplayFactory;
40
 
use Xibo\Factory\DisplayGroupFactory;
41
 
use Xibo\Factory\LayoutFactory;
42
27
use Xibo\Factory\MediaFactory;
43
 
use Xibo\Factory\ModuleFactory;
44
 
use Xibo\Factory\PermissionFactory;
45
 
use Xibo\Factory\ScheduleFactory;
46
28
use Xibo\Factory\TransitionFactory;
47
 
use Xibo\Factory\UserGroupFactory;
48
 
use Xibo\Factory\WidgetFactory;
49
 
use Xibo\Service\ConfigServiceInterface;
50
 
use Xibo\Service\DateServiceInterface;
51
 
use Xibo\Service\LogServiceInterface;
52
 
use Xibo\Service\SanitizerServiceInterface;
53
 
use Xibo\Storage\StorageServiceInterface;
 
29
use Xibo\Helper\Config;
 
30
use Xibo\Helper\Log;
 
31
use Xibo\Helper\Sanitize;
 
32
use Xibo\Helper\Theme;
54
33
 
55
34
/**
56
35
 * Class ModuleWidget
63
42
    /**
64
43
     * @var Slim
65
44
     */
66
 
    private $app;
 
45
    protected $app;
67
46
 
68
47
    /**
69
48
     * @var \Xibo\Entity\Module $module
92
71
    protected $codeSchemaVersion = -1;
93
72
 
94
73
    /**
95
 
     * @var string A module populated status message set during isValid.
96
 
     */
97
 
    protected $statusMessage;
98
 
 
99
 
    /** @var string|null Cache Key Prefix */
100
 
    private $cacheKeyPrefix = null;
101
 
 
102
 
    //
103
 
    // Injected Factory Classes and Services Follow
104
 
    //
105
 
 
106
 
    /**
107
 
     * @var StorageServiceInterface
108
 
     */
109
 
    private $store;
110
 
 
111
 
    /**
112
 
     * @var PoolInterface
113
 
     */
114
 
    private $pool;
115
 
 
116
 
    /**
117
 
     * @var LogServiceInterface
118
 
     */
119
 
    private $logService;
120
 
 
121
 
    /**
122
 
     * @var ConfigServiceInterface
123
 
     */
124
 
    private $configService;
125
 
 
126
 
    /**
127
 
     * @var DateServiceInterface
128
 
     */
129
 
    private $dateService;
130
 
 
131
 
    /**
132
 
     * @var SanitizerServiceInterface
133
 
     */
134
 
    private $sanitizerService;
135
 
 
136
 
    /** @var  EventDispatcherInterface */
137
 
    private $dispatcher;
138
 
 
139
 
    /** @var ModuleFactory  */
140
 
    protected $moduleFactory;
141
 
 
142
 
    /**
143
 
     * @var MediaFactory
144
 
     */
145
 
    protected $mediaFactory;
146
 
 
147
 
    /**
148
 
     * @var DataSetFactory
149
 
     */
150
 
    protected $dataSetFactory;
151
 
 
152
 
    /**
153
 
     * @var DataSetColumnFactory
154
 
     */
155
 
    protected $dataSetColumnFactory;
156
 
 
157
 
    /**
158
 
     * @var TransitionFactory
159
 
     */
160
 
    protected $transitionFactory;
161
 
 
162
 
    /**
163
 
     * @var DisplayFactory
164
 
     */
165
 
    protected $displayFactory;
166
 
 
167
 
    /**
168
 
     * @var CommandFactory
169
 
     */
170
 
    protected $commandFactory;
171
 
 
172
 
    /** @var  LayoutFactory */
173
 
    protected $layoutFactory;
174
 
 
175
 
    /** @var  WidgetFactory */
176
 
    protected $widgetFactory;
177
 
 
178
 
    /** @var  DisplayGroupFactory */
179
 
    protected $displayGroupFactory;
180
 
 
181
 
    /** @var  ScheduleFactory */
182
 
    protected $scheduleFactory;
183
 
 
184
 
    /** @var  PermissionFactory */
185
 
    protected $permissionFactory;
186
 
 
187
 
    /** @var  UserGroupFactory */
188
 
    protected $userGroupFactory;
189
 
 
190
 
    /**
191
 
     * ModuleWidget constructor.
192
 
     * @param Slim $app
193
 
     * @param StorageServiceInterface $store
194
 
     * @param PoolInterface $pool
195
 
     * @param LogServiceInterface $log
196
 
     * @param ConfigServiceInterface $config
197
 
     * @param DateServiceInterface $date
198
 
     * @param SanitizerServiceInterface $sanitizer
199
 
     * @param EventDispatcherInterface $dispatcher
200
 
     * @param ModuleFactory $moduleFactory
201
 
     * @param MediaFactory $mediaFactory
202
 
     * @param DataSetFactory $dataSetFactory
203
 
     * @param DataSetColumnFactory $dataSetColumnFactory
204
 
     * @param TransitionFactory $transitionFactory
205
 
     * @param DisplayFactory $displayFactory
206
 
     * @param CommandFactory $commandFactory
207
 
     * @param ScheduleFactory $scheduleFactory
208
 
     * @param PermissionFactory $permissionFactory
209
 
     * @param UserGroupFactory $userGroupFactory
210
 
     */
211
 
    public function __construct($app, $store, $pool, $log, $config, $date, $sanitizer, $dispatcher, $moduleFactory, $mediaFactory, $dataSetFactory, $dataSetColumnFactory, $transitionFactory, $displayFactory, $commandFactory, $scheduleFactory, $permissionFactory, $userGroupFactory)
212
 
    {
213
 
        $this->app = $app;
214
 
        $this->store = $store;
215
 
        $this->pool = $pool;
216
 
        $this->logService = $log;
217
 
        $this->configService = $config;
218
 
        $this->dateService = $date;
219
 
        $this->sanitizerService = $sanitizer;
220
 
        $this->dispatcher = $dispatcher;
221
 
 
222
 
        $this->moduleFactory = $moduleFactory;
223
 
        $this->mediaFactory = $mediaFactory;
224
 
        $this->dataSetFactory = $dataSetFactory;
225
 
        $this->dataSetColumnFactory = $dataSetColumnFactory;
226
 
        $this->transitionFactory = $transitionFactory;
227
 
        $this->displayFactory = $displayFactory;
228
 
        $this->commandFactory = $commandFactory;
229
 
        $this->scheduleFactory = $scheduleFactory;
230
 
        $this->permissionFactory = $permissionFactory;
231
 
        $this->userGroupFactory = $userGroupFactory;
232
 
 
233
 
        $this->init();
234
 
    }
235
 
 
236
 
    /**
237
 
     * Set Child Object Dependencies
238
 
     * @param LayoutFactory $layoutFactory
239
 
     * @param WidgetFactory $widgetFactory
240
 
     * @param DisplayGroupFactory $displayGroupFactory
241
 
     */
242
 
    public function setChildObjectDependencies($layoutFactory, $widgetFactory, $displayGroupFactory)
243
 
    {
244
 
        $this->layoutFactory = $layoutFactory;
245
 
        $this->widgetFactory = $widgetFactory;
246
 
        $this->displayGroupFactory = $displayGroupFactory;
 
74
     * Create the controller
 
75
     */
 
76
    public function __construct()
 
77
    {
 
78
        $this->app = Slim::getInstance();
247
79
    }
248
80
 
249
81
    /**
252
84
     */
253
85
    protected function getApp()
254
86
    {
255
 
        if ($this->app == null)
256
 
            throw new \RuntimeException(__('Module Widget Application not set'));
257
 
 
258
87
        return $this->app;
259
88
    }
260
89
 
261
90
    /**
262
 
     * Get Cache Pool
263
 
     * @return \Stash\Interfaces\PoolInterface
264
 
     */
265
 
    protected function getPool()
266
 
    {
267
 
        return $this->pool;
268
 
    }
269
 
 
270
 
    /**
271
 
     * Get Store
272
 
     * @return StorageServiceInterface
273
 
     */
274
 
    protected function getStore()
275
 
    {
276
 
        return $this->store;
277
 
    }
278
 
 
279
 
    /**
280
 
     * Get Log
281
 
     * @return LogServiceInterface
282
 
     */
283
 
    protected function getLog()
284
 
    {
285
 
        return $this->logService;
286
 
    }
287
 
 
288
 
    /**
289
 
     * Get Config
290
 
     * @return ConfigServiceInterface
291
 
     */
292
 
    public function getConfig()
293
 
    {
294
 
        return $this->configService;
295
 
    }
296
 
 
297
 
    /**
298
 
     * Get Date
299
 
     * @return DateServiceInterface
300
 
     */
301
 
    protected function getDate()
302
 
    {
303
 
        return $this->dateService;
304
 
    }
305
 
 
306
 
    /**
307
 
     * Get Sanitizer
308
 
     * @return SanitizerServiceInterface
309
 
     */
310
 
    protected function getSanitizer()
311
 
    {
312
 
        return $this->sanitizerService;
313
 
    }
314
 
 
315
 
    /**
316
 
     * @inheritdoc
317
 
     */
318
 
    protected function getDispatcher()
319
 
    {
320
 
        return $this->dispatcher;
321
 
    }
322
 
 
323
 
    //
324
 
    // End of Injected Factories and Services
325
 
    //
326
 
 
327
 
    /**
328
 
     * Any initialisation code
329
 
     */
330
 
    public function init()
331
 
    {
332
 
 
333
 
    }
334
 
 
335
 
    /**
336
 
     * Make a cache key
337
 
     * @param $id
338
 
     * @return string
339
 
     */
340
 
    public function makeCacheKey($id)
341
 
    {
342
 
        return $this->getCacheKeyPrefix() . '/' . $id;
343
 
    }
344
 
 
345
 
    /**
346
 
     * Get the cache prefix, including the leading /
347
 
     * @return null|string
348
 
     */
349
 
    private function getCacheKeyPrefix()
350
 
    {
351
 
        if ($this->cacheKeyPrefix == null) {
352
 
            $className = get_class($this);
353
 
            $this->cacheKeyPrefix = '/widget/' . substr($className, strrpos($className, '\\') + 1);
354
 
        }
355
 
 
356
 
        return $this->cacheKeyPrefix;
357
 
    }
358
 
 
359
 
    /**
360
 
     * Dump the cache for this module
361
 
     */
362
 
    public function dumpCacheForModule()
363
 
    {
364
 
        $this->getPool()->deleteItem($this->getCacheKeyPrefix());
365
 
    }
366
 
 
367
 
    // <editor-fold desc="request locking">
368
 
 
369
 
    /** @var  Item */
370
 
    private $lock;
371
 
 
372
 
    /**
373
 
     * Hold a lock on concurrent requests
374
 
     *  blocks if the request is locked
375
 
     * @param string|null $key
376
 
     * @param int $ttl seconds
377
 
     * @param int $wait seconds
378
 
     * @param int $tries
379
 
     * @throws XiboException
380
 
     */
381
 
    public function concurrentRequestLock($key = null, $ttl = 900, $wait = 5, $tries = 100)
382
 
    {
383
 
        // If the key is null default to the widgetId
384
 
        if ($key === null)
385
 
            $key = $this->widget->widgetId;
386
 
 
387
 
        $this->lock = $this->getPool()->getItem('locks/widget/' . $key);
388
 
 
389
 
        // Set the invalidation method to simply return the value (not that we use it, but it gets us a miss on expiry)
390
 
        $this->lock->setInvalidationMethod(Invalidation::VALUE);
391
 
 
392
 
        // Get the lock
393
 
        // other requests will wait here until we're done, or we've timed out
394
 
        $this->lock->get();
395
 
 
396
 
        // Did we get a lock?
397
 
        // if we're a miss, then we're not already locked
398
 
        if ($this->lock->isMiss()) {
399
 
            // so lock now
400
 
            $this->lock->set(true);
401
 
            $this->lock->expiresAfter($ttl);
402
 
            $this->lock->save();
403
 
 
404
 
            //sleep(30);
405
 
        } else {
406
 
            // We are a hit - we must be locked
407
 
            $this->getLog()->debug('LOCK hit for ' . $key);
408
 
 
409
 
            // Try again?
410
 
            $tries--;
411
 
 
412
 
            if ($tries <= 0) {
413
 
                // We've waited long enough
414
 
                throw new XiboException('Concurrent record locked, time out.');
415
 
            } else {
416
 
                $this->getLog()->debug('Unable to get a lock, trying again. Remaining retries: ' . $tries);
417
 
 
418
 
                // Hang about waiting for the lock to be released.
419
 
                sleep($wait);
420
 
 
421
 
                // Recursive request (we've decremented the number of tries)
422
 
                $this->concurrentRequestLock($key, $ttl, $wait, $tries);
423
 
            }
424
 
        }
425
 
    }
426
 
 
427
 
    /**
428
 
     * Release a lock on concurrent requests
429
 
     */
430
 
    public function concurrentRequestRelease()
431
 
    {
432
 
        if ($this->lock !== null) {
433
 
            // Release lock
434
 
            $this->lock->set(false);
435
 
            $this->lock->expiresAfter(1); // Expire straight away
436
 
 
437
 
            $this->getPool()->saveDeferred($this->lock);
438
 
        }
439
 
    }
440
 
 
441
 
    // </editor-fold>
442
 
 
443
 
    /**
444
91
     * Set the Widget
445
92
     * @param \Xibo\Entity\Widget $widget
446
93
     */
592
239
 
593
240
    /**
594
241
     * Clear Media
595
 
     * should only be used on media items that do not automatically assign new media from the feed
596
242
     */
597
243
    final protected function clearMedia()
598
244
    {
599
 
        $this->widget->clearCachedMedia();
 
245
        $this->widget->clearMedia();
600
246
    }
601
247
 
602
248
    /**
654
300
            'real' => false
655
301
        ], $options);
656
302
 
657
 
        if ($options['real']) {
 
303
        if ($options['real'] && $this->widget->duration === 0) {
658
304
            try {
659
305
                // Get the duration from the parent media record.
660
306
                return $this->getMedia()->duration;
661
307
            }
662
308
            catch (NotFoundException $e) {
663
 
                $this->getLog()->error('Tried to get real duration from a widget without media. widgetId: %d', $this->getWidgetId());
 
309
                Log::debug('Tried to get real duration from a widget without media. widgetId: %d', $this->getWidgetId());
664
310
                // Do nothing - drop out
665
311
            }
666
 
        } else if ($this->widget->duration === null && $this->module !== null) {
667
 
            return $this->module->defaultDuration;
668
312
        }
669
313
 
670
314
        return $this->widget->duration;
680
324
    }
681
325
 
682
326
    /**
683
 
     * Gets the calculated duration of this widget
684
 
     * @return int
685
 
     */
686
 
    final public function getCalculatedDurationForGetResource()
687
 
    {
688
 
        return ($this->widget->useDuration == 0) ? $this->getModule()->defaultDuration : $this->widget->duration;
689
 
    }
690
 
 
691
 
    /**
692
327
     * Save the Widget
693
328
     */
694
329
    final protected function saveWidget()
709
344
     */
710
345
    public function edit()
711
346
    {
712
 
        $this->setDuration($this->getSanitizer()->getInt('duration', $this->getDuration()));
713
 
        $this->setUseDuration($this->getSanitizer()->getCheckbox('useDuration'));
714
 
        $this->setOption('name', $this->getSanitizer()->getString('name'));
715
 
 
716
 
        $this->widget->save();
 
347
        // Nothing to do
717
348
    }
718
349
 
719
350
    /**
734
365
        if ($this->getOption('name') != '')
735
366
            return $this->getOption('name');
736
367
 
737
 
        $this->getLog()->debug('Media assigned: ' . count($this->widget->mediaIds));
 
368
        Log::debug('Media assigned: ' . count($this->widget->mediaIds));
738
369
 
739
370
        if ($this->getModule()->regionSpecific == 0 && count($this->widget->mediaIds) > 0) {
740
 
            $media = $this->getMedia();
 
371
            $media = MediaFactory::getById($this->widget->mediaIds[0]);
741
372
            $name = $media->name;
742
373
        } else {
743
374
            $name = $this->module->name;
767
398
     */
768
399
    public function previewIcon()
769
400
    {
770
 
        return '<div style="text-align:center;"><img alt="' . $this->getModuleType() . ' thumbnail" src="' . $this->getConfig()->uri('img/' . $this->getModule()->imageUri) . '" /></div>';
 
401
        return '<div style="text-align:center;"><img alt="' . $this->getModuleType() . ' thumbnail" src="' . Theme::uri('img/' . $this->getModule()->imageUri) . '" /></div>';
771
402
    }
772
403
 
773
404
    /**
795
426
    {
796
427
        // Default Hover window contains a thumbnail, media type and duration
797
428
        $output = '<div class="well">';
798
 
        $output .= '<div class="preview-module-image"><img alt="' . __($this->module->name) . ' thumbnail" src="' . $this->getConfig()->uri('img/' . $this->module->imageUri) . '" /></div>';
 
429
        $output .= '<div class="preview-module-image"><img alt="' . __($this->module->name) . ' thumbnail" src="' . Theme::uri('img/' . $this->module->imageUri) . '" /></div>';
799
430
        $output .= '<div class="info">';
800
431
        $output .= '    <ul>';
801
432
        $output .= '    <li>' . __('Type') . ': ' . $this->module->name . '</li>';
822
453
 
823
454
    /**
824
455
     * Gets a Tab
825
 
     * @param string $tab
826
456
     * @return mixed
827
457
     * @throws ControllerNotImplemented
828
458
     */
832
462
    }
833
463
 
834
464
    /**
835
 
     * Get File URL
836
 
     * @param Media $file
837
 
     * @param string|null $type
838
 
     * @return string
839
 
     */
840
 
    protected function getFileUrl($file, $type = null)
841
 
    {
842
 
        $isPreview = ($this->getSanitizer()->getCheckbox('preview') == 1);
843
 
        $params = ['id' => $file->mediaId];
844
 
 
845
 
        if ($type !== null) {
846
 
            $params['type'] = $type;
847
 
        }
848
 
 
849
 
        if ($isPreview) {
850
 
            return $this->getApp()->urlFor('library.download', $params) . '?preview=1"';
851
 
        } else {
852
 
            $url = $file->storedAs;
853
 
        }
854
 
 
855
 
        return $url;
856
 
    }
857
 
 
858
 
    /**
859
465
     * Get Resource Url
860
 
     * @param string $uri The file name
861
 
     * @param string|null $type
 
466
     * @param $uri
862
467
     * @return string
863
468
     */
864
 
    protected function getResourceUrl($uri, $type = null)
 
469
    protected function getResourceUrl($uri)
865
470
    {
866
 
        $isPreview = ($this->getSanitizer()->getCheckbox('preview') == 1);
867
 
 
868
 
        // Local clients store all files in the root of the library
869
 
        $uri = basename($uri);
870
 
 
871
 
        if ($isPreview) {
872
 
            // Use the URI to get this media record
873
 
            try {
874
 
                $media = $this->mediaFactory->getByName($uri);
875
 
                $params = ['id' => $media->mediaId];
876
 
 
877
 
                if ($type !== null) {
878
 
                    $params['type'] = $type;
879
 
                }
880
 
 
881
 
                return $this->getApp()->urlFor('library.download', $params) . '?preview=1';
882
 
 
883
 
            } catch (NotFoundException $notFoundException) {
884
 
                $this->getLog()->info('Widget referencing a resource that doesnt exist: ' . $this->getModuleType() . ' for ' . $uri);
885
 
 
886
 
                // Return a URL which will 404
887
 
                return '/' . $uri;
888
 
            }
889
 
        }
 
471
        $isPreview = (Sanitize::getCheckbox('preview') == 1);
 
472
 
 
473
        if ($isPreview)
 
474
            $uri = $this->getApp()->rootUri . 'modules/' . $uri;
 
475
        else
 
476
            $uri = basename($uri);
890
477
 
891
478
        return $uri;
892
479
    }
907
494
     * Get the the Transition for this media
908
495
     * @param string $type Either "in" or "out"
909
496
     * @return string
910
 
     * @throws InvalidArgumentException
911
497
     */
912
498
    public function getTransition($type)
913
499
    {
921
507
                break;
922
508
 
923
509
            default:
924
 
                throw new InvalidArgumentException(__('Unknown transition type'), 'type');
 
510
                $code = '';
 
511
                trigger_error(_('Unknown transition type'), E_USER_ERROR);
925
512
        }
926
513
 
927
514
        if ($code == '')
929
516
 
930
517
        // Look up the real transition name
931
518
        try {
932
 
            $transition = $this->transitionFactory->getByCode($code);
 
519
            $transition = TransitionFactory::getByCode($code);
933
520
            return __($transition->transition);
934
521
        }
935
522
        catch (NotFoundException $e) {
936
 
            $this->getLog()->error('Transition not found with code %s.', $code);
 
523
            Log::error('Transition not found with code %s.', $code);
937
524
            return 'None';
938
525
        }
939
526
    }
941
528
    /**
942
529
     * Default behaviour for install / upgrade
943
530
     * this should be overridden for new modules
944
 
     * @param ModuleFactory $moduleFactory
945
 
     * @throws ControllerNotImplemented
946
531
     */
947
 
    public function installOrUpdate($moduleFactory)
 
532
    public function installOrUpdate()
948
533
    {
949
534
        if ($this->module->renderAs != 'native')
950
535
            throw new ControllerNotImplemented(__('Module must implement InstallOrUpgrade'));
964
549
     */
965
550
    public function installModule()
966
551
    {
967
 
        $this->getLog()->notice('Request to install module with name: ' . $this->module->name, 'module', 'InstallModule');
 
552
        Log::notice('Request to install module with name: ' . $this->module->name, 'module', 'InstallModule');
968
553
 
969
554
        // Validate some things.
970
555
        if ($this->module->type == '')
1003
588
    }
1004
589
 
1005
590
    /**
1006
 
     * Module settings buttons to be displayed on the module admin page
1007
 
     * @return array
1008
 
     */
1009
 
    public function settingsButtons()
1010
 
    {
1011
 
        return [];
1012
 
    }
1013
 
 
1014
 
    /**
1015
 
     * Configure any additional module routes
1016
 
     *  these are available through the api and web portal
1017
 
     */
1018
 
    public function configureRoutes()
1019
 
    {
1020
 
 
1021
 
    }
1022
 
 
1023
 
    /**
1024
591
     * Default view for add form
1025
592
     */
1026
593
    public function addForm()
1060
627
    }
1061
628
 
1062
629
    /**
1063
 
     * Count Library Media
1064
 
     * @return int
1065
 
     */
1066
 
    public function countLibraryMedia()
1067
 
    {
1068
 
        return 0;
1069
 
    }
1070
 
 
1071
 
    /**
1072
630
     * Get Media Id
1073
631
     * @return int
1074
632
     * @throws NotFoundException
1075
633
     */
1076
634
    public function getMediaId()
1077
635
    {
1078
 
        return $this->widget->getPrimaryMediaId();
 
636
        Log::debug('Getting first MediaID for Widget: %d', $this->getWidgetId());
 
637
 
 
638
        if (count($this->widget->mediaIds) <= 0)
 
639
            throw new NotFoundException(__('No file to return'));
 
640
 
 
641
        return $this->widget->mediaIds[0];
1079
642
    }
1080
643
 
1081
644
    /**
1085
648
     */
1086
649
    public function getMedia()
1087
650
    {
1088
 
        $media = $this->mediaFactory->getById($this->getMediaId());
1089
 
        $media->setChildObjectDependencies($this->layoutFactory, $this->widgetFactory, $this->displayGroupFactory, $this->displayFactory, $this->scheduleFactory);
1090
 
        return $media;
 
651
        return MediaFactory::getById($this->getMediaId());
1091
652
    }
1092
653
 
1093
654
    /**
1095
656
     */
1096
657
    protected function download()
1097
658
    {
1098
 
        $media = $this->mediaFactory->getById($this->getMediaId());
1099
 
 
1100
 
        $this->getLog()->debug('Download for mediaId ' . $media->mediaId);
1101
 
 
1102
 
        // Are we a preview or not?
1103
 
        $isPreview = ($this->getSanitizer()->getCheckbox('preview') == 1);
1104
 
 
1105
 
        // The file path
1106
 
        $libraryPath = $this->getConfig()->GetSetting('LIBRARY_LOCATION') . $media->storedAs;
1107
 
 
1108
 
        // Set the content length
1109
 
        $headers = $this->getApp()->response()->headers();
1110
 
        $headers->set('Content-Length', filesize($libraryPath));
1111
 
 
1112
 
        // Different behaviour depending on whether we are a preview or not.
1113
 
        if ($isPreview) {
1114
 
            // correctly grab the MIME type of the file we want to serve
1115
 
            $mimeTypes = new MimeTypes();
1116
 
            $ext = explode('.', $media->storedAs);
1117
 
            $headers->set('Content-Type', $mimeTypes->getMimeType($ext[count($ext) - 1]));
1118
 
        } else {
1119
 
            // This widget is expected to output a file - usually this is for file based media
1120
 
            // Get the name with library
1121
 
            $attachmentName = $this->getSanitizer()->getString('attachment', $media->storedAs);
1122
 
 
1123
 
            // Issue some headers
1124
 
            $this->getApp()->etag($media->md5);
1125
 
            $this->getApp()->expires('+1 week');
1126
 
 
1127
 
            $headers->set('Content-Type', 'application/octet-stream');
1128
 
            $headers->set('Content-Transfer-Encoding', 'Binary');
1129
 
            $headers->set('Content-disposition', 'attachment; filename="' . $attachmentName . '"');
1130
 
        }
1131
 
 
1132
 
        // Output the file
1133
 
        if ($this->getConfig()->GetSetting('SENDFILE_MODE') == 'Apache') {
1134
 
            // Send via Apache X-Sendfile header?
1135
 
            $headers->set('X-Sendfile', $libraryPath);
1136
 
        }
1137
 
        else if ($this->getConfig()->GetSetting('SENDFILE_MODE') == 'Nginx') {
1138
 
            // Send via Nginx X-Accel-Redirect?
1139
 
            $headers->set('X-Accel-Redirect', '/download/' . $media->storedAs);
 
659
        $media = MediaFactory::getById($this->getMediaId());
 
660
 
 
661
        // This widget is expected to output a file - usually this is for file based media
 
662
        // Get the name with library
 
663
        $libraryLocation = Config::GetSetting('LIBRARY_LOCATION');
 
664
        $libraryPath = $libraryLocation . $media->storedAs;
 
665
        $attachmentName = Sanitize::getString('attachment', $media->storedAs);
 
666
 
 
667
        $size = filesize($libraryPath);
 
668
 
 
669
        // Issue some headers
 
670
        $this->getApp()->etag($media->md5);
 
671
        $this->getApp()->expires('+1 week');
 
672
        header('Content-Type: application/octet-stream');
 
673
        header('Content-Transfer-Encoding: Binary');
 
674
        header('Content-disposition: attachment; filename="' . $attachmentName . '"');
 
675
        header('Content-Length: ' . $size);
 
676
 
 
677
        // Send via Apache X-Sendfile header?
 
678
        if (Config::GetSetting('SENDFILE_MODE') == 'Apache') {
 
679
            header("X-Sendfile: $libraryPath");
 
680
        }
 
681
        // Send via Nginx X-Accel-Redirect?
 
682
        else if (Config::GetSetting('SENDFILE_MODE') == 'Nginx') {
 
683
            header("X-Accel-Redirect: /download/" . $attachmentName);
1140
684
        }
1141
685
        else {
1142
686
            // Return the file with PHP
1167
711
 
1168
712
            // Check that this mediaId exists and get some information about it
1169
713
            try {
1170
 
                $entry = $this->mediaFactory->getById($mediaId);
 
714
                $entry = MediaFactory::getById($mediaId);
1171
715
 
1172
716
                // Assign it
1173
717
                $this->assignMedia($entry->mediaId);
1179
723
                $parsedContent = str_replace($sub, $replace, $parsedContent);
1180
724
            }
1181
725
            catch (NotFoundException $e) {
1182
 
                $this->getLog()->info('Reference to Unknown mediaId %d', $mediaId);
 
726
                Log::info('Reference to Unknown mediaId %d', $mediaId);
1183
727
            }
1184
728
        }
1185
729
 
1187
731
    }
1188
732
 
1189
733
    /**
1190
 
     * Get templatesAvailable
1191
 
     * @param bool $loadImage Should the image URL be loaded?
1192
 
     * @return array
1193
 
     */
1194
 
    public function templatesAvailable($loadImage = true)
1195
 
    {
1196
 
        if (!isset($this->module->settings['templates'])) {
1197
 
 
1198
 
            $this->module->settings['templates'] = [];
1199
 
 
1200
 
            // Scan the folder for template files
1201
 
            foreach (glob(PROJECT_ROOT . '/modules/' . $this->module->type . '/*.template.json') as $template) {
1202
 
                // Read the contents, json_decode and add to the array
1203
 
                $template = json_decode(file_get_contents($template), true);
1204
 
 
1205
 
                if (isset($template['image'])) {
1206
 
                    $template['fileName'] = $template['image'];
1207
 
 
1208
 
                    if ($loadImage) {
1209
 
                        // We ltrim this because the control is expecting a relative URL
1210
 
                        $template['image'] = ltrim($this->getApp()->urlFor('module.getTemplateImage', ['type' => $this->module->type, 'templateId' => $template['id']]), '/');
1211
 
                    }
1212
 
                } else {
1213
 
                    $template['fileName'] = '';
1214
 
                    $template['image'] = '';
1215
 
                }
1216
 
 
1217
 
                $this->module->settings['templates'][] = $template;
1218
 
            }
1219
 
        }
1220
 
 
1221
 
        return $this->module->settings['templates'];
1222
 
    }
1223
 
 
1224
 
    /**
1225
 
     * Get by Template Id
1226
 
     * @param int $templateId
1227
 
     * @return array|null
1228
 
     */
1229
 
    public function getTemplateById($templateId)
1230
 
    {
1231
 
        $templates = $this->templatesAvailable(false);
1232
 
        $template = null;
1233
 
 
1234
 
        if (count($templates) <= 0)
1235
 
            return null;
1236
 
 
1237
 
        foreach ($templates as $item) {
1238
 
            if ($item['id'] == $templateId) {
1239
 
                $template = $item;
1240
 
                break;
1241
 
            }
1242
 
        }
1243
 
 
1244
 
        return $template;
1245
 
    }
1246
 
 
1247
 
    /**
1248
734
     * Set template data
1249
735
     * @param array $data
1250
736
     * @return array
1255
741
    }
1256
742
 
1257
743
    /**
1258
 
     * Download an image for this template
1259
 
     * @param int $templateId
1260
 
     * @throws NotFoundException
1261
 
     */
1262
 
    public function getTemplateImage($templateId)
1263
 
    {
1264
 
        $template = $this->getTemplateById($templateId);
1265
 
 
1266
 
        if ($template === null || !isset($template['fileName']) || $template['fileName'] == '')
1267
 
            throw new NotFoundException();
1268
 
 
1269
 
        // Output the image associated with this template
1270
 
        echo Img::make(PROJECT_ROOT . '/' . $template['fileName'])->response();
1271
 
    }
1272
 
 
1273
 
    /**
1274
744
     * Determine duration
1275
745
     * @param string|null $fileName
1276
746
     * @return int
1277
747
     */
1278
748
    public function determineDuration($fileName = null)
1279
749
    {
1280
 
        return $this->getModule()->defaultDuration;
 
750
        return 0;
1281
751
    }
1282
752
 
1283
753
    /**
1284
754
     * Pre-processing
1285
 
     *  this is run before the media item is created.
1286
755
     * @param string|null $fileName
1287
756
     */
1288
 
    public function preProcessFile($fileName = null)
1289
 
    {
1290
 
        $this->getLog()->debug('No pre-processing rules for this module type');
1291
 
    }
1292
 
 
1293
 
    /**
1294
 
     * Pre-process
1295
 
     *  this is run before the media item is saved
1296
 
     * @param Media $media
1297
 
     * @param string $filePath
1298
 
     */
1299
 
    public function preProcess($media, $filePath) {
1300
 
 
1301
 
    }
1302
 
 
1303
 
    /**
1304
 
     * Post-processing
1305
 
     *  this is run after the media item has been created and before it is saved.
1306
 
     * @param Media $media
1307
 
     */
1308
 
    public function postProcess($media)
1309
 
    {
1310
 
 
 
757
    public function preProcess($fileName = null)
 
758
    {
 
759
        Log::debug('No pre-processing rules for this module type');
1311
760
    }
1312
761
 
1313
762
    /**
1315
764
     */
1316
765
    public function setDefaultWidgetOptions()
1317
766
    {
1318
 
        $this->getLog()->debug('Default Widget Options: Setting use duration to 0');
1319
 
        $this->setUseDuration(0);
1320
 
    }
1321
 
 
1322
 
    /**
1323
 
     * Get Status Message
1324
 
     * @return string
1325
 
     */
1326
 
    public function getStatusMessage()
1327
 
    {
1328
 
        return $this->statusMessage;
1329
 
    }
1330
 
 
1331
 
    /**
1332
 
     * Get the modified date of this Widget
1333
 
     * @param int $displayId
1334
 
     * @return null|int
1335
 
     */
1336
 
    public function getModifiedTimestamp($displayId)
1337
 
    {
1338
 
        return null;
1339
 
    }
1340
 
 
1341
 
    //<editor-fold desc="GetResource Helpers">
1342
 
 
1343
 
    private $data;
1344
 
 
1345
 
    /**
1346
 
     * Initialise getResource
1347
 
     * @return $this
1348
 
     */
1349
 
    protected function initialiseGetResource()
1350
 
    {
1351
 
        $this->data['isPreview'] = ($this->getSanitizer()->getCheckbox('preview') == 1);
1352
 
        $this->data['javaScript'] = '';
1353
 
        $this->data['styleSheet'] = '';
1354
 
        $this->data['head'] = '';
1355
 
        $this->data['body'] = '';
1356
 
        $this->data['controlMeta'] = '';
1357
 
        $this->data['options'] = '{}';
1358
 
        $this->data['items'] = '{}';
1359
 
        return $this;
1360
 
    }
1361
 
 
1362
 
    /**
1363
 
     * @return bool Is Preview
1364
 
     */
1365
 
    protected function isPreview()
1366
 
    {
1367
 
        return $this->data['isPreview'];
1368
 
    }
1369
 
 
1370
 
    /**
1371
 
     * Finalise getResource
1372
 
     * @param string $templateName an optional template name
1373
 
     * @return string the rendered template
1374
 
     */
1375
 
    protected function finaliseGetResource($templateName = 'get-resource')
1376
 
    {
1377
 
        $this->data['javaScript'] = '<script type="text/javascript">var options = ' . $this->data['options'] . '; var items = ' . $this->data['items'] . ';</script>' . PHP_EOL . $this->data['javaScript'];
1378
 
        return $this->renderTemplate($this->data, $templateName);
1379
 
    }
1380
 
 
1381
 
    /**
1382
 
     * Append the view port width - usually the region width
1383
 
     * @param int $width
1384
 
     * @return $this
1385
 
     */
1386
 
    protected function appendViewPortWidth($width)
1387
 
    {
1388
 
        $this->data['viewPortWidth'] = ($this->data['isPreview']) ? $width : '[[ViewPortWidth]]';
1389
 
        return $this;
1390
 
    }
1391
 
 
1392
 
    /**
1393
 
     * Append Font CSS
1394
 
     * @return $this
1395
 
     */
1396
 
    protected function appendFontCss()
1397
 
    {
1398
 
        $this->data['styleSheet'] .= '<link href="' . (($this->isPreview()) ? $this->getApp()->urlFor('library.font.css') : 'fonts.css') . '" rel="stylesheet" media="screen" />' . PHP_EOL;
1399
 
        return $this;
1400
 
    }
1401
 
 
1402
 
    /**
1403
 
     * Append CSS File
1404
 
     * @param string $uri The URI, according to whether this is a CMS preview or not
1405
 
     * @return $this
1406
 
     */
1407
 
    protected function appendCssFile($uri)
1408
 
    {
1409
 
        $this->data['styleSheet'] .= '<link href="' . $this->getResourceUrl($uri) . '" rel="stylesheet" media="screen" />' . PHP_EOL;
1410
 
        return $this;
1411
 
    }
1412
 
 
1413
 
    /**
1414
 
     * Append CSS content
1415
 
     * @param string $css
1416
 
     * @return $this
1417
 
     */
1418
 
    protected function appendCss($css)
1419
 
    {
1420
 
        if (!empty($css)) {
1421
 
            if (stripos($css, '<style') !== false)
1422
 
                $this->data['styleSheet'] .= $css . PHP_EOL;
1423
 
            else
1424
 
                $this->data['styleSheet'] .= '<style type="text/css">' . $css . '</style>' . PHP_EOL;
1425
 
        }
1426
 
 
1427
 
        return $this;
1428
 
    }
1429
 
 
1430
 
    /**
1431
 
     * Append JavaScript file
1432
 
     * @param string $uri
1433
 
     * @return $this
1434
 
     */
1435
 
    protected function appendJavaScriptFile($uri)
1436
 
    {
1437
 
        $this->data['javaScript'] .= '<script type="text/javascript" src="' . $this->getResourceUrl($uri) . '"></script>' . PHP_EOL;
1438
 
        return $this;
1439
 
    }
1440
 
 
1441
 
    /**
1442
 
     * Append JavaScript
1443
 
     * @param string $javasScript
1444
 
     * @return $this
1445
 
     */
1446
 
    protected function appendJavaScript($javasScript)
1447
 
    {
1448
 
        if (!empty($javasScript))
1449
 
            $this->data['javaScript'] .= '<script type="text/javascript">' . $javasScript . '</script>' . PHP_EOL;
1450
 
 
1451
 
        return $this;
1452
 
    }
1453
 
 
1454
 
    /**
1455
 
     * Append Body
1456
 
     * @param string $body
1457
 
     * @return $this
1458
 
     */
1459
 
    protected function appendBody($body)
1460
 
    {
1461
 
        if (!empty($body))
1462
 
            $this->data['body'] .= $body . PHP_EOL;
1463
 
 
1464
 
        return $this;
1465
 
    }
1466
 
 
1467
 
    /**
1468
 
     * Append Options
1469
 
     * @param array $options
1470
 
     * @return $this
1471
 
     */
1472
 
    protected function appendOptions($options)
1473
 
    {
1474
 
        $this->data['options'] = json_encode($options);
1475
 
        return $this;
1476
 
    }
1477
 
 
1478
 
    /**
1479
 
     * Append Items
1480
 
     * @param array $items
1481
 
     * @return $this
1482
 
     */
1483
 
    protected function appendItems($items)
1484
 
    {
1485
 
        $this->data['items'] = json_encode($items);
1486
 
        return $this;
1487
 
    }
1488
 
 
1489
 
    /**
1490
 
     * Append raw string
1491
 
     * @param string $key
1492
 
     * @param string $item
1493
 
     * @return $this
1494
 
     */
1495
 
    protected function appendRaw($key, $item)
1496
 
    {
1497
 
        $this->data[$key] .= $item . PHP_EOL;
1498
 
        return $this;
1499
 
    }
1500
 
 
1501
 
    //</editor-fold>
 
767
        Log::debug('No default options for this module type');
 
768
    }
1502
769
}