Browse Source

Merge branch 'master' of https://github.com/unaio/una

roman.lesnikov@gmail.com 3 năm trước cách đây
mục cha
commit
fa2a3682ca

+ 34 - 9
inc/classes/BxDolPreloader.php

@@ -32,15 +32,15 @@ class BxDolPreloader extends BxDolFactory implements iBxDolSingleton
 
         $this->_aEntries = $this->_oDb->getEntries();
 
-        $this->_aTypes = array(
-            BX_PRELOADER_TYPE_CSS => '',
-            BX_PRELOADER_TYPE_JS => '', 
-            BX_PRELOADER_TYPE_JS_OPTION => '',
-            BX_PRELOADER_TYPE_JS_TRANSLATION => '',
-            BX_PRELOADER_TYPE_JS_IMAGE => ''
-        );
+        $this->_aTypes = [
+            BX_PRELOADER_TYPE_CSS => ['get' => 'getCssUrl'],
+            BX_PRELOADER_TYPE_JS => ['get' => 'getJsUrl'],
+            BX_PRELOADER_TYPE_JS_OPTION => [],
+            BX_PRELOADER_TYPE_JS_TRANSLATION => [],
+            BX_PRELOADER_TYPE_JS_IMAGE => []
+        ];
         foreach($this->_aTypes as $sType => $sValue)
-            $this->_aTypes[$sType] = 'add' . bx_gen_method_name($sType);
+            $this->_aTypes[$sType]['add'] = 'add' . bx_gen_method_name($sType);
 
         $this->_aMarkers = array(
             'dir_plugins_public' => BX_DIRECTORY_PATH_PLUGINS_PUBLIC,
@@ -78,9 +78,34 @@ class BxDolPreloader extends BxDolFactory implements iBxDolSingleton
             if(empty($sContent))
                 continue;
 
-            $oTemplateSystem->{$this->_aTypes[$sType]}($sContent);
+            $oTemplateSystem->{$this->_aTypes[$sType]['add']}($sContent);
         }
     }
+
+    public function getSystemAssets($oTemplateSystem)
+    {
+        $aResults = [];
+
+        $aEntries = $this->_oDb->getEntriesSystem();
+        foreach($aEntries as $aEntry) {
+            $sType = $aEntry['type'];
+
+            if(BxDolService::isSerializedService($aEntry['content']))
+                $aEntry['content'] = BxDolService::callSerialized($aEntry['content']);
+
+            $sContent = bx_replace_markers($aEntry['content'], $this->_aMarkers);
+            if(empty($sContent))
+                continue;
+
+            $sEntry = $oTemplateSystem->{$this->_aTypes[$sType]['get']}($sContent);
+            if(empty($sEntry))
+                $sEntry = $sContent;
+
+            $aResults[] = str_replace([BX_DOL_URL_ROOT, BX_DIRECTORY_PATH_ROOT], '/', $sEntry);
+        }
+
+        return $aResults;
+    }
 }
 
 /** @} */

+ 10 - 1
inc/classes/BxDolPreloaderQuery.php

@@ -26,7 +26,16 @@ class BxDolPreloaderQuery extends BxDolDb
 
         return $GLOBALS[$sKey];
     }
-    
+
+    public function &getEntriesSystem()
+    {
+        $sKey = 'bx_dol_cache_memory_preloader_entries_system';
+
+        if(!isset($GLOBALS[$sKey]))
+            $GLOBALS[$sKey] = $this->fromCache('sys_preloader_entries_system', 'getAll', "SELECT * FROM `sys_preloader` WHERE `type` IN ('css_system', 'js_system') AND `active`='1' ORDER BY `type`, `order`");
+
+        return $GLOBALS[$sKey];
+    }
 }
 
 /** @} */

+ 1 - 1
inc/classes/BxDolSession.php

@@ -64,7 +64,7 @@ class BxDolSession extends BxDolFactory implements iBxDolSingleton
 
     function start()
     {
-        if (defined('BX_DOL_CRON_EXECUTE') || defined('BX_MANIFEST'))
+        if (defined('BX_DOL_CRON_EXECUTE') || defined('BX_MANIFEST') || defined('BX_SERVICE_WORKER'))
             return true;
 
         if (getParam('sys_session_auth')) {

+ 97 - 0
sw.js.php

@@ -0,0 +1,97 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaCore UNA Core
+ * @{
+ */
+
+define('BX_SERVICE_WORKER', true);
+
+require_once('./inc/header.inc.php');
+
+$aAssets = BxDolPreloader::getInstance()->getSystemAssets(BxDolTemplate::getInstance());
+
+header("Content-Type: text/javascript");
+?>
+
+// Core assets
+let coreAssets = <?php echo json_encode($aAssets); ?>;
+
+// On install, cache core assets
+self.addEventListener('install', function (event) {
+    // Cache core assets
+    event.waitUntil(caches.open('app').then(function (cache) {
+        for (let asset of coreAssets) {
+            cache.add(new Request(asset));
+        }
+        return cache;
+    }));
+});
+
+// Listen for request events
+self.addEventListener('fetch', function (event) {
+
+    // Get the request
+    let request = event.request;
+
+    // Bug fix
+    // https://stackoverflow.com/a/49719964
+    if (event.request.cache === 'only-if-cached' && event.request.mode !== 'same-origin') return;
+
+    // HTML files
+    // Network-first
+    if (request.headers.get('Accept').includes('text/html')) {
+        event.respondWith(
+            fetch(request).then(function (response) {
+                // Create a copy of the response and save it to the cache
+                let copy = response.clone();
+                event.waitUntil(caches.open('app').then(function (cache) {
+                    return cache.put(request, copy);
+                }));
+
+                // Return the response
+                return response;
+            }).catch(function (error) {
+                // If there's no item in cache, respond with a fallback
+                return caches.match(request).then(function (response) {
+                    return response || caches.match('/offline.html');
+                });
+            })
+        );
+    }
+
+    // CSS & JavaScript
+    // Offline-first
+    if (request.headers.get('Accept').includes('text/css') || request.headers.get('Accept').includes('text/javascript')) {
+        event.respondWith(
+            caches.match(request).then(function (response) {
+                return response || fetch(request).then(function (response) {
+                    // Return the response
+                    return response;
+                });
+            })
+        );
+        return;
+    }
+
+    // Images
+    // Offline-first
+    if (request.headers.get('Accept').includes('image')) {
+        event.respondWith(
+            caches.match(request).then(function (response) {
+                return response || fetch(request).then(function (response) {
+                    // Save a copy of it in cache
+                    let copy = response.clone();
+                    event.waitUntil(caches.open('app').then(function (cache) {
+                        return cache.put(request, copy);
+                    }));
+
+                    // Return the response
+                    return response;
+                });
+            })
+        );
+    }
+});

+ 4 - 0
template/_header_js.html

@@ -7,6 +7,10 @@
         bx_redirect_for_external_links($('.bx-def-vanilla-html'));
     });
 
+    if (navigator && navigator.serviceWorker) {
+        navigator.serviceWorker.register('sw.js.php');
+    }
+
     (function(w) {
         var dpr = (w.devicePixelRatio === undefined ? 1 : Math.round(w.devicePixelRatio));
         if ($.cookie('devicePixelRatio') == dpr || dpr < 2 || (typeof(bIgnorePixelRatio) != "undefined" && bIgnorePixelRatio) || !navigator.cookieEnabled)