ViewComposer::findSubPath()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 2
1
<?php
2
/**
3
 * @link https://github.com/vuongxuongminh/laravel-mobile-first
4
 *
5
 * @copyright (c) Vuong Xuong Minh
6
 * @license [MIT](https://opensource.org/licenses/MIT)
7
 */
8
9
namespace VXM\MobileFirst;
10
11
use Illuminate\View\View;
12
use Jenssegers\Agent\Agent;
13
use InvalidArgumentException;
14
use Illuminate\Filesystem\Filesystem;
15
16
/**
17
 * @author Vuong Minh <[email protected]>
18
 * @since  1.0.0
19
 */
20
class ViewComposer
21
{
22
    /**
23
     * Agent help to detect user device.
24
     *
25
     * @var Agent
26
     */
27
    protected $agent;
28
29
    /**
30
     * An array with key's device type mapping with sub dir of it.
31
     *
32
     * @var array
33
     */
34
    protected $deviceSubDirs;
35
36
    /**
37
     * Resolved path cached.
38
     *
39
     * @var array
40
     */
41
    protected $resolvedPaths = [];
42
43
    /**
44
     * Helpful resolve path.
45
     *
46
     * @var Filesystem
47
     */
48
    protected $files;
49
50
    /**
51
     * Create a new ViewComposer instance.
52
     *
53
     * @param Agent $agent
54
     * @param array $deviceSubDirs
55
     * @param Filesystem $files
56
     */
57
    public function __construct(Agent $agent, array $deviceSubDirs, Filesystem $files)
58
    {
59
        $this->agent = $agent;
60
        $this->deviceSubDirs = $deviceSubDirs;
61
        $this->files = $files;
62
    }
63
64
    /**
65
     * Compose given View instance.
66
     *
67
     * @param View $view
68
     */
69
    public function compose(View $view): void
70
    {
71
        $path = $view->getPath();
72
73
        if (isset($this->resolvedPaths[$path])) {
74
            $resolvedPath = $this->resolvedPaths[$path];
75
        } else {
76
            $resolvedPath = $this->resolvePath($view);
77
        }
78
79
        if ($resolvedPath) {
80
            $view->setPath($this->resolvedPaths[$path] = $resolvedPath);
81
        } else {
82
            $this->resolvedPaths[$path] = false;
83
        }
84
    }
85
86
    /**
87
     * Resolve path by end-user device.
88
     *
89
     * @param View $view
90
     * @return string|null
91
     */
92
    protected function resolvePath(View $view): ?string
93
    {
94
        foreach ($this->deviceSubDirs as $device => $subDir) {
95
            if ($this->isDevice($device) && $path = $this->findSubPath($view, $subDir)) {
96
                return $path;
97
            }
98
        }
99
100
        return null;
101
    }
102
103
    /**
104
     * Checking current device of end-user by given value.
105
     *
106
     * @param $device
107
     * @return bool
108
     */
109
    protected function isDevice($device): bool
110
    {
111
        switch ($device) {
112
            case 'phone':
113
                return $this->agent->isPhone();
114
            case 'tablet':
115
                return $this->agent->isTablet();
116
            case 'mobile':
117
                return $this->agent->isMobile();
118
            default:
119
                return $this->agent->is($device);
120
        }
121
    }
122
123
    /**
124
     * Find sub path.
125
     *
126
     * @param View $view
127
     * @param string $subDir
128
     * @return string|null
129
     */
130
    protected function findSubPath(View $view, string $subDir): ?string
131
    {
132
        if ($view->getName() !== $view->getPath()) {
133
            return $this->findSubViewPath($view, $subDir);
134
        } else {
135
            return $this->findSubNativePath($view, $subDir);
136
        }
137
    }
138
139
    /**
140
     * Find sub view path.
141
     *
142
     * @param View $view
143
     * @param string $subDir
144
     * @return string|null
145
     */
146
    protected function findSubViewPath(View $view, string $subDir): ?string
147
    {
148
        $rawPath = str_replace('.', '/', $view->getName());
149
        $base = $this->files->dirname($rawPath);
150
        $name = $this->files->name($rawPath);
151
        $path = ltrim($base.'.'.$subDir.'.'.$name, '.');
152
        $factory = $view->getFactory();
153
154
        try {
155
            $path = $factory->getFinder()->find($path);
156
        } catch (InvalidArgumentException $exception) {
157
            return null;
158
        }
159
160
        if ($view->getEngine() === $factory->getEngineFromPath($path)) {
161
            return $path;
162
        }
163
164
        return null;
165
    }
166
167
    /**
168
     * Find sub native path.
169
     *
170
     * @param View $view
171
     * @param string $subDir
172
     * @return string|null
173
     */
174
    protected function findSubNativePath(View $view, string $subDir): ?string
175
    {
176
        $path = $view->getPath();
177
        $dirname = $this->files->dirname($path);
178
        $basename = $this->files->basename($path);
179
180
        if ($this->files->exists($path = $dirname.'/'.$subDir.'/'.$basename)) {
181
            return $path;
182
        }
183
184
        return null;
185
    }
186
}
187