ManifestController   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 172
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 65
c 3
b 0
f 0
dl 0
loc 172
rs 10
wmc 12

5 Methods

Rating   Name   Duplication   Size   Complexity  
A get_template_global_variables() 0 4 1
A listIcons() 0 19 3
A index() 0 71 4
A getServiceWorkerCachedPaths() 0 6 1
A getIconsPath() 0 16 3
1
<?php
2
3
namespace LeKoala\SsPwa;
4
5
use SilverStripe\Control\Director;
6
use SilverStripe\Control\Controller;
7
use SilverStripe\SiteConfig\SiteConfig;
0 ignored issues
show
Bug introduced by
The type SilverStripe\SiteConfig\SiteConfig was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use SilverStripe\View\TemplateGlobalProvider;
9
10
/**
11
 * @link https://developer.mozilla.org/en-US/docs/Web/Manifest
12
 * @link https://web.dev/learn/pwa/web-app-manifest/
13
 */
14
class ManifestController extends Controller implements TemplateGlobalProvider, ServiceWorkerCacheProvider
15
{
16
    /**
17
     * @config
18
     * @var string
19
     */
20
    private static $gcm_sender_id = null;
0 ignored issues
show
introduced by
The private property $gcm_sender_id is not used, and could be removed.
Loading history...
21
22
    /**
23
     * @link https://developer.mozilla.org/en-US/docs/Web/Manifest/background_color
24
     * @config
25
     * @var string
26
     */
27
    private static $background_color = '#ffffff';
0 ignored issues
show
introduced by
The private property $background_color is not used, and could be removed.
Loading history...
28
29
    /**
30
     * @link https://developer.mozilla.org/en-US/docs/Web/Manifest/orientation
31
     * @config
32
     * @var string
33
     */
34
    private static $orientation = 'portrait-primary';
0 ignored issues
show
introduced by
The private property $orientation is not used, and could be removed.
Loading history...
35
36
    /**
37
     * @config
38
     * @var string
39
     */
40
    private static $custom_icon_path = '';
41
42
    /**
43
     * @var array<string>
44
     */
45
    private static $allowed_actions = [
0 ignored issues
show
introduced by
The private property $allowed_actions is not used, and could be removed.
Loading history...
46
        'index',
47
    ];
48
49
    /**
50
     * @return mixed
51
     */
52
    public function index()
53
    {
54
        $config = $this->config();
55
        $sc = SiteConfig::current_site_config();
56
57
        $title = $sc->Title;
58
        //@phpstan-ignore-next-line
59
        $desc = $sc->Tagline;
60
        $desc = $desc ?: $title;
61
62
        $icons = self::listIcons();
63
64
        $theme_color = $background_color = $config->get('background_color');
65
        //@phpstan-ignore-next-line
66
        if ($sc->ThemeColor) {
67
            $theme_color = $sc->ThemeColor;
68
        }
69
70
        $manifestContent = [
71
            // Full name of your PWA. It will appear along with the icon in the operating system's home screen, launcher, dock, or menu
72
            'name' => $title,
73
            // Optional, a shorter name of your PWA, used when there is not enough room to display the full value of the name field. Keep it under 12 characters to minimize the possibility of truncation.
74
            'short_name' => $title,
75
            // Array of icon objects with src, type, sizes, and optional purpose fields, describing what images should represent the PWA.
76
            'icons' => $icons,
77
            // The URL the PWA should load when the user starts it from the installed icon.
78
            // An absolute path is recommended, so if your PWA's home page is the root of your site,
79
            // you could set this to ‘/' to open it when your app starts.
80
            // If you don't provide a start URL, the browser can use the URL the PWA was installed from as a start.
81
            // It can be a deep link, such as the details of a product instead of your home screen.
82
            'start_url' => Director::baseURL(),
83
            // One of fullscreen, standalone, minimal-ui, or browser, describing how the OS should draw the PWA window.
84
            // You can read more about the different display modes in the App Design chapter.
85
            // Most use cases implement standalone.
86
            'display' => 'standalone',
87
            // A string that uniquely identifies this PWA against others that may be hosted on the same origin. If it's not set, the start_url will be used as a fallback value.
88
            // Keep in mind that by changing the start_url in the future (such as when changing a query string value) you may be removing the browser's ability to detect that a PWA is already installed.
89
            // @link https://developer.chrome.com/blog/pwa-manifest-id/
90
            'id' => Director::baseURL(),
91
            // The description member is a string in which developers can explain what the application does.
92
            // description is directionality-capable, which means it can be displayed left to right or right to left based on the values of the dir and lang manifest members.
93
            'description' => $desc,
94
            'lang' => 'en',
95
            'dir' => 'ltr',
96
            // The scope member is a string that defines the navigation scope of this web application's application context.
97
            // It restricts what web pages can be viewed while the manifest is applied.
98
            // If the user navigates outside the scope, it reverts to a normal web page inside a browser tab or window.
99
            'scope' => Director::baseURL(),
100
            // https://developer.chrome.com/docs/extensions/mv3/declare_permissions/
101
            'permissions' => [
102
                // https://developer.chrome.com/docs/extensions/reference/gcm/
103
                'gcm',
104
            ],
105
            // The background_color member defines a placeholder background color for the application page to display before its stylesheet is loaded.
106
            // This value is used by the user agent to draw the background color of a shortcut when the manifest is available before the stylesheet has loaded.
107
            'background_color' => $background_color,
108
            // The theme_color member is a string that defines the default theme color for the application.
109
            // This sometimes affects how the OS displays the site (e.g., on Android's task switcher, the theme color surrounds the site).
110
            'theme_color' => $theme_color,
111
            // The orientation member defines the default orientation for all the website's top-level browsing contexts.
112
            'orientation' => $config->get('orientation'),
113
        ];
114
115
        $gcm_sender_id = $config->get('gcm_sender_id');
116
        if ($gcm_sender_id) {
117
            $manifestContent['gcm_sender_id'] = $gcm_sender_id;
118
            $manifestContent['gcm_user_visible_only'] = true;
119
        }
120
121
        $this->getResponse()->addHeader('Content-Type', 'application/manifest+json; charset="utf-8"');
122
        return json_encode($manifestContent);
123
    }
124
125
    /**
126
     * @return array<array{'src':string,'sizes':string,'type':string,'purpose':string}>
127
     */
128
    public static function listIcons(): array
129
    {
130
        $iconsPath = self::getIconsPath();
131
        $sizes = [192, 512];
132
        $purposes = ['any', 'maskable'];
133
        $version = ServiceWorkerController::config()->get('version');
134
135
        $icons = [];
136
        foreach ($sizes as $size) {
137
            foreach ($purposes as $purpose) {
138
                $icons[] = [
139
                    'src' => self::join_links($iconsPath, 'manifest-icon-' . $size . '.maskable.png?' . $version),
140
                    'sizes' => $size . 'x' . $size,
141
                    'type' => 'image/png',
142
                    'purpose' => $purpose,
143
                ];
144
            }
145
        }
146
        return $icons;
147
    }
148
149
    public static function getIconsPath(): string
150
    {
151
        // can be dynamically configured through site config
152
        $sc = SiteConfig::current_site_config();
153
        if ($sc->hasMethod("PwaIconsPath")) {
154
            //@phpstan-ignore-next-line
155
            return $sc->PwaIconsPath();
156
        }
157
        // can use custom override
158
        if (self::config()->custom_icon_path) {
159
            return self::config()->custom_icon_path;
160
        }
161
        // defaults to _resources/app/images/icons
162
        $baseURL = '/';
163
        $iconsPath = self::join_links($baseURL, RESOURCES_DIR, 'app', 'images', 'icons');
164
        return $iconsPath;
165
    }
166
167
    /**
168
     * @return array<string,string>
169
     */
170
    public static function get_template_global_variables()
171
    {
172
        return [
173
            'PwaIconsPath' => 'getIconsPath',
174
        ];
175
    }
176
177
    /**
178
     * @return array<string>
179
     */
180
    public static function getServiceWorkerCachedPaths(): array
181
    {
182
        $icons = self::listIcons();
183
        return array_map(function ($v) {
184
            return $v['src'];
185
        }, $icons);
186
    }
187
}
188