Passed
Pull Request — master (#53)
by
unknown
04:11
created

mailEclipse::getMailableViewData()   B

Complexity

Conditions 8
Paths 18

Size

Total Lines 44
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 2
Metric Value
cc 8
eloc 23
c 3
b 1
f 2
nc 18
nop 2
dl 0
loc 44
rs 8.4444
1
<?php
2
3
namespace qoraiche\mailEclipse;
4
5
use RegexIterator;
6
use ErrorException;
7
use ReflectionClass;
8
use ReflectionProperty;
9
use Illuminate\Support\Str;
10
use Illuminate\Mail\Markdown;
11
use RecursiveIteratorIterator;
12
use RecursiveDirectoryIterator;
13
use Illuminate\Support\Collection;
14
use Illuminate\Support\Facades\DB;
15
use Illuminate\Container\Container;
16
use Illuminate\Support\Facades\View;
17
use ReeceM\Mocker\Mocked;
18
use Illuminate\Support\Facades\Artisan;
19
use Illuminate\Database\Eloquent\Factory as EloquentFactory;
20
21
class mailEclipse
22
{
23
    public static $view_namespace = 'maileclipse';
24
25
    /**
26
     * Default type examples for being passed to reflected classes.
27
     * 
28
     * @var array TYPES
29
     */
30
    public const TYPES = [
31
        'int' => 31,
32
        // 'string' => 'test_string', // not needed as it can be cast __toString()
33
        'bool' => false,
34
        'float' => 3.14159
35
    ];
36
37
    public static function getMailables()
38
    {
39
        return self::mailablesList();
40
    }
41
42
    public static function getMailable($key, $name)
43
    {
44
        $filtered = collect(self::getMailables())->where($key, $name);
45
46
        return $filtered;
47
    }
48
49
    public static function deleteTemplate($templateSlug)
50
    {
51
        $template = self::getTemplates()
52
            ->where('template_slug', $templateSlug)->first();
53
54
        if (! is_null($template)) {
55
            self::saveTemplates(self::getTemplates()->reject(function ($value, $key) use ($template) {
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

55
            self::saveTemplates(self::getTemplates()->reject(function ($value, /** @scrutinizer ignore-unused */ $key) use ($template) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
56
                return $value->template_slug == $template->template_slug;
57
            }));
58
59
            $template_view = self::$view_namespace.'::templates.'.$templateSlug;
60
            $template_plaintext_view = $template_view.'_plain_text';
61
62
            if (View::exists($template_view)) {
63
                unlink(View($template_view)->getPath());
64
65
                if (View::exists($template_plaintext_view)) {
66
                    unlink(View($template_plaintext_view)->getPath());
67
                }
68
69
                return true;
70
            }
71
        }
72
73
        return false;
74
    }
75
76
    public static function getTemplatesFile()
77
    {
78
        $file = config('maileclipse.mailables_dir').'templates.json';
79
        if (! file_exists($file)) {
80
            if (! file_exists(config('maileclipse.mailables_dir'))) {
81
                mkdir(config('maileclipse.mailables_dir'));
82
            }
83
            file_put_contents($file, '[]');
84
        }
85
86
        return $file;
87
    }
88
89
    public static function saveTemplates(Collection $templates)
90
    {
91
        file_put_contents(self::getTemplatesFile(), $templates->toJson());
92
    }
93
94
    public static function updateTemplate($request)
95
    {
96
        $template = self::getTemplates()
97
            ->where('template_slug', $request->templateslug)->first();
98
99
        if (! is_null($template)) {
100
            if (! preg_match("/^[a-zA-Z0-9-_\s]+$/", $request->title)) {
101
                return response()->json([
102
                    'status' => 'failed',
103
                    'message' => 'Template name not valid',
104
                ]);
105
            }
106
107
            $templatename = Str::camel(preg_replace('/\s+/', '_', $request->title));
108
109
            // check if not already exists on db
110
            //
111
            //
112
113
            if (self::getTemplates()->contains('template_slug', '=', $templatename)) {
114
                return response()->json([
115
116
                    'status' => 'failed',
117
                    'message' => 'Template name already exists',
118
119
                ]);
120
            }
121
122
            // Update
123
            //
124
            $oldForm = self::getTemplates()->reject(function ($value, $key) use ($template) {
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

124
            $oldForm = self::getTemplates()->reject(function ($value, /** @scrutinizer ignore-unused */ $key) use ($template) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
125
                return $value->template_slug == $template->template_slug;
126
            });
127
            $newForm = array_merge($oldForm->toArray(), [array_merge((array) $template, [
128
                'template_slug' => $templatename,
129
                'template_name' => $request->title,
130
                'template_description' => $request->description,
131
            ])]);
132
133
            self::saveTemplates(collect($newForm));
134
135
            $template_view = self::$view_namespace.'::templates.'.$request->templateslug;
136
            $template_plaintext_view = $template_view.'_plain_text';
137
138
            if (View::exists($template_view)) {
139
                $viewPath = View($template_view)->getPath();
140
141
                rename($viewPath, dirname($viewPath)."/{$templatename}.blade.php");
142
143
                if (View::exists($template_plaintext_view)) {
144
                    $textViewPath = View($template_plaintext_view)->getPath();
145
146
                    rename($textViewPath, dirname($viewPath)."/{$templatename}_plain_text.blade.php");
147
                }
148
            }
149
150
            return response()->json([
151
152
                'status' => 'ok',
153
                'message' => 'Updated Successfully',
154
                'template_url' => route('viewTemplate', ['templatename' => $templatename]),
155
156
            ]);
157
        }
158
    }
159
160
    public static function getTemplate($templateSlug)
161
    {
162
        $template = self::getTemplates()
163
            ->where('template_slug', $templateSlug)->first();
164
165
        if (! is_null($template)) {
166
            $template_view = self::$view_namespace.'::templates.'.$template->template_slug;
167
            $template_plaintext_view = $template_view.'_plain_text';
168
169
            // return $template_plaintext_view;
170
171
            if (View::exists($template_view)) {
172
                $viewPath = View($template_view)->getPath();
173
                $textViewPath = View($template_plaintext_view)->getPath();
174
175
                $templateData = collect([
176
                    'template' => self::templateComponentReplace(file_get_contents($viewPath), true),
177
                    'plain_text' => View::exists($template_plaintext_view) ? file_get_contents($textViewPath) : '',
178
                    'slug' => $template->template_slug,
179
                    'name' => $template->template_name,
180
                    'description' => $template->template_description,
181
                    'template_type' => $template->template_type,
182
                    'template_view_name' => $template->template_view_name,
183
                    'template_skeleton' => $template->template_skeleton,
184
                ]);
185
186
                return $templateData;
187
            }
188
        }
189
190
        // return;
191
    }
192
193
    public static function getTemplates()
194
    {
195
        $template = collect(json_decode(file_get_contents(self::getTemplatesFile())));
196
197
        return $template;
198
    }
199
200
    public static function createTemplate($request)
201
    {
202
        if (! preg_match("/^[a-zA-Z0-9-_\s]+$/", $request->template_name)) {
203
            return response()->json([
204
205
                'status' => 'error',
206
                'message' => 'Template name not valid',
207
208
            ]);
209
        }
210
211
        $view = self::$view_namespace.'::templates.'.$request->template_name;
212
213
        $templatename = Str::camel(preg_replace('/\s+/', '_', $request->template_name));
214
215
        if (! view()->exists($view) && ! self::getTemplates()->contains('template_slug', '=', $templatename)) {
216
            self::saveTemplates(self::getTemplates()
217
                ->push([
218
                    'template_name' => $request->template_name,
219
                    'template_slug' => $templatename,
220
                    'template_description' => $request->template_description,
221
                    'template_type' => $request->template_type,
222
                    'template_view_name' => $request->template_view_name,
223
                    'template_skeleton' => $request->template_skeleton,
224
                ]));
225
226
            $dir = resource_path('views/vendor/'.self::$view_namespace.'/templates');
227
228
            if (! \File::isDirectory($dir)) {
229
                \File::makeDirectory($dir, 0755, true);
230
            }
231
232
            file_put_contents($dir."/{$templatename}.blade.php", self::templateComponentReplace($request->content));
233
234
            file_put_contents($dir."/{$templatename}_plain_text.blade.php", $request->plain_text);
235
236
            return response()->json([
237
238
                'status' => 'ok',
239
                'message' => 'Template created<br> <small>Reloading...<small>',
240
                'template_url' => route('viewTemplate', ['templatename' => $templatename]),
241
242
            ]);
243
        }
244
245
        return response()->json([
246
247
            'status' => 'error',
248
            'message' => 'Template not created',
249
250
        ]);
251
    }
252
253
    public static function getTemplateSkeletons()
254
    {
255
        return collect(config('maileclipse.skeletons'));
256
    }
257
258
    public static function getTemplateSkeleton($type, $name, $skeleton)
259
    {
260
        $skeletonView = self::$view_namespace."::skeletons.{$type}.{$name}.{$skeleton}";
261
262
        if (view()->exists($skeletonView)) {
263
            $skeletonViewPath = View($skeletonView)->getPath();
264
            $templateContent = file_get_contents($skeletonViewPath);
265
266
            return [
267
                'type' => $type,
268
                'name' => $name,
269
                'skeleton' => $skeleton,
270
                'template' => self::templateComponentReplace($templateContent, true),
271
                'view' => $skeletonView,
272
                'view_path' => $skeletonViewPath,
273
            ];
274
        }
275
    }
276
277
    protected static function templateComponentReplace($content, $reverse = false)
278
    {
279
        if ($reverse) {
280
            $patterns = [
281
                '/@component/i',
282
                '/@endcomponent/i',
283
                '/@yield/',
284
                '/@section/',
285
                '/@endsection/',
286
                '/@extends/',
287
                '/@parent/',
288
                '/@slot/',
289
                '/@endslot/',
290
            ];
291
292
            $replacements = [
293
                '[component]: # ',
294
                '[endcomponent]: # ',
295
                '[yield]: # ',
296
                '[section]: # ',
297
                '[endsection]: # ',
298
                '[extends]: # ',
299
                '[parent]: # ',
300
                '[slot]: # ',
301
                '[endslot]: # ',
302
            ];
303
        } else {
304
            $patterns = [
305
                '/\[component]:\s?#\s?/i',
306
                '/\[endcomponent]:\s?#\s?/i',
307
                '/\[yield]:\s?#\s?/i',
308
                '/\[section]:\s?#\s?/i',
309
                '/\[endsection]:\s?#\s?/i',
310
                '/\[extends]:\s?#\s?/i',
311
                '/\[parent]:\s?#\s?/i',
312
                '/\[slot]:\s?#\s?/i',
313
                '/\[endslot]:\s?#\s?/i',
314
            ];
315
316
            $replacements = [
317
                '@component',
318
                '@endcomponent',
319
                '@yield',
320
                '@section',
321
                '@endsection',
322
                '@extends',
323
                '@parent',
324
                '@slot',
325
                '@endslot',
326
            ];
327
        }
328
329
        return preg_replace($patterns, $replacements, $content);
330
    }
331
332
    protected static function markdownedTemplate($viewPath)
333
    {
334
        $viewContent = file_get_contents($viewPath);
335
336
        return self::templateComponentReplace($viewContent, true);
337
338
        // return preg_replace($patterns, $replacements, $viewContent);
339
    }
340
341
    /**
342
     * Markdowned template view.
343
     */
344
    public static function markdownedTemplateToView($save = true, $content = '', $viewPath = '', $template = false)
345
    {
346
        if ($template && View::exists(self::$view_namespace.'::templates.'.$viewPath)) {
347
            $viewPath = View(self::$view_namespace.'::templates.'.$viewPath)->getPath();
348
        }
349
350
        $replaced = self::templateComponentReplace($content);
351
352
        if (! $save) {
353
            return $replaced;
354
        }
355
356
        return file_put_contents($viewPath, $replaced) === false ? false : true;
357
    }
358
359
    public static function previewMarkdownViewContent($simpleview, $content, $viewName, $template = false, $namespace = null)
360
    {
361
        $previewtoset = self::markdownedTemplateToView(false, $content);
362
        $dir = dirname(__FILE__, 2).'/resources/views/draft';
363
        $viewName = $template ? $viewName.'_template' : $viewName;
364
365
        if (file_exists($dir)) {
366
            file_put_contents($dir."/{$viewName}.blade.php", $previewtoset);
367
368
            if ($template) {
369
                $instance = null;
370
            } else {
371
                if (! is_null(self::handleMailableViewDataArgs($namespace))) {
372
                    $instance = self::handleMailableViewDataArgs($namespace);
373
                } else {
374
                    $instance = new $namespace;
375
                }
376
            }
377
378
            return self::renderPreview($simpleview, self::$view_namespace.'::draft.'.$viewName, $template, $instance);
379
        }
380
381
        return false;
382
    }
383
384
    public static function previewMarkdownHtml($instance, $view)
385
    {
386
        return self::renderPreview($instance, $view);
387
    }
388
389
    public static function getMailableTemplateData($mailableName)
390
    {
391
        $mailable = self::getMailable('name', $mailableName);
392
393
        if ($mailable->isEmpty()) {
394
            return false;
395
        }
396
397
        $templateData = collect($mailable->first())->only(['markdown', 'view_path', 'text_view_path', 'text_view', 'view_data', 'data', 'namespace'])->all();
398
399
        $templateExists = ! is_null($templateData['view_path']);
400
        $textTemplateExists = ! is_null($templateData['text_view_path']);
401
402
        if ($templateExists) {
403
            $viewPathParams = collect($templateData)->union([
404
405
                'text_template' => $textTemplateExists ? file_get_contents($templateData['text_view_path']) : null,
406
                'template' => file_get_contents($templateData['view_path']),
407
                'markdowned_template' => self::markdownedTemplate($templateData['view_path']),
408
                'template_name' => ! is_null($templateData['markdown']) ? $templateData['markdown'] : $templateData['data']->view,
409
                'is_markdown' => ! is_null($templateData['markdown']) ? true : false,
410
                // 'text_template' => file_get_contents($templateData['text_view_path']),
411
412
            ])->all();
413
414
            return $viewPathParams;
415
        }
416
417
        return $templateData;
418
    }
419
420
    public static function generateMailable($request = null)
421
    {
422
        $name = ucwords(Str::camel(preg_replace('/\s+/', '_', $request->input('name'))));
423
424
        if (! self::getMailable('name', $name)->isEmpty() && ! $request->has('force')) {
425
            // return redirect()->route('createMailable')->with('error', 'mailable already exists! to overide it enable force option.');
426
            //
427
            return response()->json([
428
                'status' => 'error',
429
                'message' => 'This mailable name already exists. names should be unique! to override it, enable "force" option.',
430
            ]);
431
        }
432
433
        if (strtolower($name) === 'mailable') {
434
            return response()->json([
435
                'status' => 'error',
436
                'message' => 'You cannot use this name',
437
            ]);
438
        }
439
440
        $params = collect([
441
            'name' => $name,
442
        ]);
443
444
        if ($request->input('markdown')) {
445
            $params->put('--markdown', $request->markdown);
446
        }
447
448
        if ($request->has('force')) {
449
            $params->put('--force', true);
450
        }
451
452
        $exitCode = Artisan::call('make:mail', $params->all());
453
454
        if ($exitCode > -1) {
455
456
            // return redirect()->route('mailableList');
457
            //
458
            return response()->json([
459
460
                'status' => 'ok',
461
                'message' => 'Mailable Created<br> <small>Reloading...<small>',
462
463
            ]);
464
        }
465
    }
466
467
    /**
468
     * Get mailables list.
469
     *
470
     * @return array
471
     */
472
    protected static function mailablesList()
473
    {
474
        $fqcns = [];
475
476
        if (! file_exists(config('maileclipse.mailables_dir'))):
477
478
            return; else:
479
480
            $allFiles = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(config('maileclipse.mailables_dir')));
481
        $phpFiles = new RegexIterator($allFiles, '/\.php$/');
482
        $i = 0;
483
484
        foreach ($phpFiles as $phpFile) {
485
            $i++;
486
            $content = file_get_contents($phpFile->getRealPath());
487
            $tokens = token_get_all($content);
488
            $namespace = '';
489
            for ($index = 0; isset($tokens[$index]); $index++) {
490
                if (! isset($tokens[$index][0])) {
491
                    continue;
492
                }
493
                if (T_NAMESPACE === $tokens[$index][0]) {
494
                    $index += 2; // Skip namespace keyword and whitespace
495
                    while (isset($tokens[$index]) && is_array($tokens[$index])) {
496
                        $namespace .= $tokens[$index++][1];
497
                    }
498
                }
499
                if (T_CLASS === $tokens[$index][0] && T_WHITESPACE === $tokens[$index + 1][0] && T_STRING === $tokens[$index + 2][0]) {
500
                    $index += 2; // Skip class keyword and whitespace
501
502
                    [$name, $extension] = explode('.', $phpFile->getFilename());
503
504
                    $mailableClass = $namespace.'\\'.$tokens[$index][1];
505
506
                    if (! self::mailable_exists($mailableClass)) {
507
                        continue;
508
                    }
509
510
                    $mailable_data = self::buildMailable($mailableClass);
511
512
                    if (! is_null(self::handleMailableViewDataArgs($mailableClass))) {
513
                        $mailable_view_data = self::getMailableViewData(self::handleMailableViewDataArgs($mailableClass), $mailable_data);
514
                    } else {
515
                        $mailable_view_data = self::getMailableViewData(new $mailableClass, $mailable_data);
516
                    }
517
518
                    $fqcns[$i]['data'] = $mailable_data;
519
                    $fqcns[$i]['markdown'] = self::getMarkdownViewName($mailable_data);
520
                    $fqcns[$i]['name'] = $name;
521
                    $fqcns[$i]['namespace'] = $mailableClass;
522
                    $fqcns[$i]['filename'] = $phpFile->getFilename();
523
                    $fqcns[$i]['modified'] = $phpFile->getCTime();
524
                    $fqcns[$i]['viewed'] = $phpFile->getATime();
525
                    $fqcns[$i]['view_data'] = $mailable_view_data;
526
                    // $fqcns[$i]['view_data'] = [];
527
                    $fqcns[$i]['path_name'] = $phpFile->getPathname();
528
                    $fqcns[$i]['readable'] = $phpFile->isReadable();
529
                    $fqcns[$i]['writable'] = $phpFile->isWritable();
530
                    $fqcns[$i]['view_path'] = null;
531
                    $fqcns[$i]['text_view_path'] = null;
532
533
                    if (! is_null($fqcns[$i]['markdown']) && View::exists($fqcns[$i]['markdown'])) {
534
                        $fqcns[$i]['view_path'] = View($fqcns[$i]['markdown'])->getPath();
535
                    }
536
537
                    if (! is_null($fqcns[$i]['data'])) {
538
                        if (! is_null($fqcns[$i]['data']->view) && View::exists($fqcns[$i]['data']->view)) {
539
                            $fqcns[$i]['view_path'] = View($fqcns[$i]['data']->view)->getPath();
540
                        }
541
542
                        if (! is_null($fqcns[$i]['data']->textView) && View::exists($fqcns[$i]['data']->textView)) {
543
                            $fqcns[$i]['text_view_path'] = View($fqcns[$i]['data']->textView)->getPath();
544
                            $fqcns[$i]['text_view'] = $fqcns[$i]['data']->textView;
545
                        }
546
                    }
547
548
                    // break if you have one class per file (psr-4 compliant)
549
                    // otherwise you'll need to handle class constants (Foo::class)
550
                    break;
551
                }
552
            }
553
        }
554
555
        $collection = collect($fqcns)->map(function ($mailable) {
556
            return $mailable;
557
        })->reject(function ($object) {
558
            return ! method_exists($object['namespace'], 'build');
559
        });
560
561
        // return $collection->all();
562
        //
563
        return $collection;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $collection returns the type Illuminate\Support\Collection which is incompatible with the documented return type array.
Loading history...
564
565
        endif;
566
    }
567
568
    /**
569
     * Handle Mailable Constructor arguments and pass the fake ones.
570
     */
571
    public static function handleMailableViewDataArgs($mailable)
572
    {
573
        if (method_exists($mailable, '__construct')) {
574
            $reflection = new ReflectionClass($mailable);
575
576
            $params = $reflection->getConstructor()->getParameters();
577
            
578
            DB::beginTransaction();
579
580
            $eloquentFactory = app(EloquentFactory::class);
581
582
            $args = collect($params)->map(function ($param) {
583
                if ($param->getType() !== null) {
584
                    if (class_exists($param->getType()->getName())) {
585
                        $parameters = [
586
                            'is_instance' => true,
587
                            'instance' => $param->getType()->getName(),
588
                        ];
589
                    } elseif ($param->getType()->getName() == 'array') {
590
                        $parameters = [
591
                            'is_array' => true,
592
                            'arg' => $param->getName(),
593
                        ];
594
                    } else {
595
                        $parameters = $param->name;
596
                    }
597
598
                    return $parameters;
599
                }
600
601
                return $param->name;
602
            });
603
604
            $filteredparams = [];
605
606
            foreach ($args->all() as $arg) {
607
                $factoryStates = [];
608
609
                if (is_array($arg)) {
610
                    if (isset($arg['is_instance'])) {
611
                        if (isset($eloquentFactory[$arg['instance']]) && config('maileclipse.factory')) {
612
                            $filteredparams[] = factory($arg['instance'])->states($factoryStates)->make();
613
                        } else {
614
                            $filteredparams[] = app($arg['instance']);
615
                        }
616
                    } elseif (isset($arg['is_array'])) {
617
                        $filteredparams[] = [];
618
                    } else {
619
                        return;
620
                    }
621
                } else {
622
                    $filteredparams[] = self::getMissingParams($arg, $params);
623
                }
624
            }
625
626
            $reflector = new ReflectionClass($mailable);
627
628
            if (! $args->isEmpty()) {
629
                $foo = $reflector->newInstanceArgs($filteredparams);
630
631
                return $foo;
632
            }
633
634
            DB::rollBack();
635
        }
636
    }
637
638
    /**
639
     * Gets any missing params that may not be collectable in the reflection.
640
     * 
641
     * @param string $arg the argument string|array
642
     * @param array $params the reflection param list
643
     * 
644
     * @return array
645
     */
646
    private static function getMissingParams($arg, $params)
647
    {
648
        /**
649
         * Determine if a builtin type can be found.
650
         * Not a string or object as a Mocked::class can work there
651
         * 
652
         * ->getType() needs to be cast to string to get the protected prop.
653
         */
654
        $argType = (string)collect($params)->where('name', $arg)->first()->getType();
655
656
        $argType = self::TYPES[$argType] ?? null;
657
        
658
        try {
659
            return !is_null($argType) 
0 ignored issues
show
Bug Best Practice introduced by
The expression return ! is_null($argTyp...\VarStore::singleton()) also could return the type ReeceM\Mocker\Mocked which is incompatible with the documented return type array.
Loading history...
660
                    ? $argType 
661
                    : new Mocked($arg, \ReeceM\Mocker\Utils\VarStore::singleton());
662
663
        } catch (\Exception $e) {
664
            return $arg;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $arg returns the type string which is incompatible with the documented return type array.
Loading history...
665
        }
666
    }
667
668
669
    private static function getMailableViewData($mailable, $mailable_data)
670
    {
671
        $traitProperties = [];
672
673
        $data = new ReflectionClass($mailable);
674
675
        foreach ($data->getTraits() as $trait) {
676
            foreach ($trait->getProperties(ReflectionProperty::IS_PUBLIC) as $traitProperty) {
677
                $traitProperties[] = $traitProperty->name;
678
            }
679
        }
680
681
        $properties = $data->getProperties(ReflectionProperty::IS_PUBLIC);
682
        $allProps = [];
683
684
        foreach ($properties as $prop) {
685
            if ($prop->class == $data->getName()) {
686
                $allProps[] = $prop->name;
687
            }
688
        }
689
690
        $obj = self::buildMailable($mailable);
691
692
        if (is_null($obj)) {
693
            $obj = [];
694
695
            return collect($obj);
696
        }
697
698
        $classProps = array_diff($allProps, $traitProperties);
699
700
        $withFuncData = collect($obj->viewData)->keys();
701
702
        $mailableData = collect($classProps)->merge($withFuncData);
703
704
        $data = $mailableData->map(function ($parameter) use ($mailable_data) {
705
            return [
706
                'key' => $parameter,
707
                'value' => property_exists($mailable_data, $parameter) ? $mailable_data->$parameter : null,
708
                'data' => property_exists($mailable_data, $parameter) ? self::viewDataInspect($mailable_data->$parameter) : null,
709
            ];
710
        });
711
712
        return $data->all();
713
    }
714
715
    protected static function viewDataInspect($param)
716
    {
717
        if ($param instanceof \Illuminate\Database\Eloquent\Model) {
718
            return [
719
                'type' => 'model',
720
                'attributes' => collect($param->getAttributes()),
721
            ];
722
        } elseif ($param instanceof \Illuminate\Database\Eloquent\Collection) {
723
            return [
724
                'type' => 'elequent-collection',
725
                'attributes' => $param->all(),
726
            ];
727
        } elseif ($param instanceof \Illuminate\Support\Collection) {
728
            return [
729
                'type' => 'collection',
730
                'attributes' => $param->all(),
731
            ];
732
        }
733
    }
734
735
    protected static function mailable_exists($mailable)
736
    {
737
        if (! class_exists($mailable)) {
738
            return false;
739
        }
740
741
        return true;
742
    }
743
744
    protected static function getMarkdownViewName($mailable)
745
    {
746
        if ($mailable === null) {
747
            return;
748
        }
749
750
        $reflection = new ReflectionClass($mailable);
751
752
        $property = $reflection->getProperty('markdown');
753
754
        $property->setAccessible(true);
755
756
        return $property->getValue($mailable);
757
    }
758
759
    public static function buildMailable($instance, $type = 'call')
760
    {
761
        if ($type == 'call') {
762
            if (! is_null(self::handleMailableViewDataArgs($instance))) {
763
                return Container::getInstance()->call([self::handleMailableViewDataArgs($instance), 'build']);
764
            }
765
766
            return Container::getInstance()->call([new $instance, 'build']);
767
        }
768
769
        return Container::getInstance()->make($instance);
770
    }
771
772
    public static function renderPreview($simpleview, $view, $template = false, $instance = null)
773
    {
774
        if (! View::exists($view)) {
775
            return;
776
        }
777
778
        if (! $template) {
779
            $obj = self::buildMailable($instance);
780
            $viewData = $obj->viewData;
781
            $_data = array_merge($instance->buildViewData(), $viewData);
782
783
            foreach ($_data as $key => $value) {
784
                if (! is_object($value)) {
785
                    $_data[$key] = '<span class="maileclipse-key" title="Variable">'.$key.'</span>';
786
                }
787
            }
788
        } else {
789
            $_data = [];
790
        }
791
792
        $_view = $view;
793
794
        try {
795
            if ($simpleview) {
796
                return htmlspecialchars_decode(view($_view, $_data)->render());
0 ignored issues
show
Bug introduced by
It seems like view($_view, $_data)->render() can also be of type array; however, parameter $string of htmlspecialchars_decode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

796
                return htmlspecialchars_decode(/** @scrutinizer ignore-type */ view($_view, $_data)->render());
Loading history...
797
            }
798
799
            $_md = self::buildMailable(Markdown::class, 'make');
800
801
            return htmlspecialchars_decode($_md->render($_view, $_data));
802
        } catch (ErrorException $e) {
803
            $error = '<div class="alert alert-warning">
804
	    	<h5 class="alert-heading">Error:</h5>
805
	    	<p>'.$e->getMessage().'</p>
806
	    	</div>';
807
808
            if ($template) {
809
                $error .= '<div class="alert alert-info">
810
				<h5 class="alert-heading">Notice:</h5>
811
				<p>You can\'t add variables within a template editor because they are undefined until you bind the template with a mailable that actually has data.</p>
812
	    	</div>';
813
            }
814
815
            return $error;
816
        }
817
    }
818
}
819