champion-8.x-3.1-no-core/modules/contrib/hax/hax.module
modules/contrib/hax/hax.module
<?php
/**
* @file
* Headless Authoring eXperience, accept calls and make things haxable.
*/
use Drupal\hax\HaxService;
/**
* Implements hook_preprocess_hook().
*
* Add cms-hax tag and related markup as wrapper to body field.
*/
function hax_preprocess_field(&$vars) {
// Supporting attachments handled in hax_page_attachments().
// Allow for cache variability based on route name so this can be handled
// evaluated separately for the view and the hax mode tabs.
$vars['#cache']['contexts'][] = 'route.name';
if (!hax_is_current_route_supported()) {
return;
}
$entity_type = $vars['element']['#object']->getEntityTypeId();
$view_mode = $vars['element']['#view_mode'];
// @todo we could do this to other things too but this is the piece that forces it to body only
if ($vars['field_name'] == 'body' && $entity_type == 'node' && $view_mode == 'full'
&& \Drupal::config('hax.settings')->get('hax_autoload_element_node_view')) {
$appStoreConnection = json_encode([
'url' => base_path() . 'hax-app-store/' . \Drupal::csrfToken()->get(),
]);
// Get the NID from current path.
$request = \Drupal::request();
$current_path = $request->getPathInfo();
$path_args = explode('/', $current_path);
$node_id = $path_args[2];
// @todo this is clunky but works
$redirect = str_replace('//', '/', base_path() . str_replace('/hax', '', $current_path));
// TODO Not ideal, but we've fallen back to using the body text instead of
// prefix/suffix due to filtering. This will go through the node's selected
// text format for render.
// @todo: convert to string replacement function or template.
$vars['items'][0]['content']['#text'] = '<cms-hax redirect-location="' . $redirect . '" open-default end-point="' . base_path() . 'hax-node-save/' . $node_id . '/' . \Drupal::csrfToken()
->get() . '" app-store-connection=' . "'" . $appStoreConnection . "'" . '><template>'
. $vars['items'][0]['content']['#text'] . '</template></cms-hax>';
}
}
/**
* Implements hook_hax_app_store().
*/
function hax_hax_app_store() {
$config = \Drupal::config('hax.settings');
$hax = new HaxService();
$apikeys = [];
$baseApps = $hax->baseSupportedApps();
foreach ($baseApps as $key => $app) {
if ($config->get('hax_' . $key . '_key') != '') {
$apikeys[$key] = $config->get('hax_' . $key . '_key');
}
}
$json = $hax->loadBaseAppStore($apikeys);
// Pull in the core ones we supply.
if (\Drupal::moduleHandler()->moduleExists('file')) {
$tmp = json_decode(_hax_site_connection());
array_push($json, $tmp);
}
return $json;
}
/**
* Implements hook_hax_blox().
*/
function hax_hax_blox() {
$hax = new HAXService();
$blox = $hax->loadBaseBlox();
return $blox;
}
/**
* Implements hook_hax_stax().
*/
function hax_hax_stax() {
$hax = new HAXService();
$stax = $hax->loadBaseStax();
return $stax;
}
/**
* Implements hook_hax_autoloader().
*/
function hax_hax_autoloader() {
// Generate autoload list.
$autoloaderstring = \Drupal::config('hax.settings')
->get('hax_autoload_element_list');
// Blow up based on space.
$autoloader = explode(' ', $autoloaderstring);
return $autoloader;
}
/**
* Hax site connection.
*
* Connection details for this site. This is where all the really important
* stuff is that will make people freak out.
*/
function _hax_site_connection() {
global $base_url;
$parts = explode('://', $base_url);
// Built in support when file_entity and restws is in place.
$title = t('Internal files');
$json = '{
"details": {
"title": "' . $title . '",
"icon": "perm-media",
"color": "light-blue",
"author": "Drupal",
"description": "Drupal site integration for HAX",
"tags": ["media", "drupal"]
},
"connection": {
"protocol": "' . $parts[0] . '",
"url": "' . $parts[1] . '",
"operations": {
"browse": {
"method": "GET",
"endPoint": "file.json",
"pagination": {
"style": "link",
"props": {
"first": "page.first",
"next": "page.next",
"previous": "page.previous",
"last": "page.last"
}
},
"search": {
},
"data": {
},
"resultMap": {
"defaultGizmoType": "image",
"items": "list",
"preview": {
"title": "name",
"details": "mime",
"image": "url",
"id": "uuid"
},
"gizmo": {
"source": "url",
"id": "uuid",
"title": "name",
"type": "type"
}
}
},
"add": {
"method": "POST",
"endPoint": "hax-file-save/' . \Drupal::csrfToken()->get() . '",
"acceptsGizmoTypes": [
"image",
"video",
"audio",
"pdf",
"svg",
"document",
"csv"
],
"resultMap": {
"item": "data.file",
"defaultGizmoType": "image",
"gizmo": {
"source": "url",
"id": "uuid"
}
}
}
}
}
}';
return $json;
}
/**
* Implements hook_page_bottom().
*
* Load all attachments for this page.
*/
function hax_page_bottom(array &$page_bottom) {
$location = \Drupal::config('hax.settings')->get('hax_project_location');
// account for custom locations
if ($location == 'other') {
$location = \Drupal::config('hax.settings')->get('hax_project_location_other');
}
// append base_path if this site has a url to start it
if (strpos($location, 'http') === FALSE) {
$location = base_path() . $location;
}
$wc = new WebComponentsService();
$page_bottom['hax'] = [
'#type' => 'inline_template',
'#template' => '{{ somecontent|raw }}',
'#context' => [
'somecontent' => $wc->applyWebcomponents($location)
]
];
}
/**
* Identify whether the current route is supported for HAX deployment.
*
* @return bool
* TRUE if the current route is supported.
*/
function hax_is_current_route_supported() {
$route_name = \Drupal::routeMatch()->getRouteName();
if ($route_name == 'hax.node_form') {
return TRUE;
}
return FALSE;
}
/**
* Class for implementing web component polyfills and other header aspects in a uniform manner
*/
class WebComponentsService {
/**
* This applies all pieces of a standard build appended to the header
*/
public function applyWebcomponents($directory = '/', $files = array('build.js')) {
return
$this->getBuild($directory, $files);
}
/**
* Front end logic for ES5-AMD, ES6-AMD, ES6 version to deliver
*/
public function getBuild($directory = '/', $files = array('build.js')) {
$es5 = array();
$es6Amd = array();
$es6 = array();
foreach ($files as $file) {
array_push($es5, 'cdn + "build/es5-amd/' . $file . '"');
array_push($es6Amd, 'cdn + "build/es6-amd/' . $file . '"');
array_push($es6, 'import "' . $directory . 'build/es6/' . $file . '";');
}
return '<script>var cdn="' . $directory . '";var old=false;
try { new Function(\'import("")\'); } catch (err) {
if (typeof Symbol == "undefined") { // IE 11, at least try to serve the components
if (!(window.ActiveXObject) && "ActiveXObject" in window) {
"use strict"; (function () { function a(a, b, c) { var d = a; if (d.state = b, d.stateData = c, 0 < d.onNextStateChange.length) { var e = d.onNextStateChange.slice(); d.onNextStateChange.length = 0; for (var f, g = 0, h = e; g < h.length; g++)f = h[g], f() } return d } function b(b) { function d() { try { document.head.removeChild(f) } catch (a) { } } var e = a(b, "Loading", void 0), f = document.createElement("script"); return f.src = b.url, f.onload = function () { var a, b, f; void 0 === r ? (b = [], f = void 0) : (a = r(), b = a[0], f = a[1]), c(e, b, f), d() }, f.onerror = function () { g(b, new TypeError("Failed to fetch " + b.url)), d() }, document.head.appendChild(f), e } function c(b, c, e) { var f = d(b, c), g = f[0], h = f[1]; return a(b, "WaitingForTurn", { args: g, deps: h, moduleBody: e }) } function d(a, c) { for (var e, f = [], g = [], i = 0, j = c; i < j.length; i++) { if (e = j[i], "exports" === e) { f.push(a.exports); continue } if ("require" === e) { f.push(function (b, c, e) { var f = d(a, b), g = f[0], i = f[1]; h(i, function () { c && c.apply(null, g) }, e) }); continue } if ("meta" === e) { f.push({ url: !0 === a.isTopLevel ? a.url.substring(0, a.url.lastIndexOf("#")) : a.url }); continue } var l = k(n(a.urlBase, e)); f.push(l.exports), g.push(l), "Initialized" === l.state && b(l) } return [f, g] } function e(b) { var c = a(b, "WaitingOnDeps", b.stateData); return h(b.stateData.deps, function () { return f(c) }, function (a) { return g(c, a) }), c } function f(b) { var c = b.stateData; if (null != c.moduleBody) try { c.moduleBody.apply(null, c.args) } catch (a) { return g(b, a) } return a(b, "Executed", void 0) } function g(b, c) { return !0 === b.isTopLevel && setTimeout(function () { throw c }), a(b, "Failed", c) } function h(a, b, c) { var d = a.shift(); return void 0 === d ? void (b && b()) : "WaitingOnDeps" === d.state ? (!1, void h(a, b, c)) : void i(d, function () { h(a, b, c) }, c) } function i(a, b, c) { switch (a.state) { case "WaitingForTurn": return e(a), void i(a, b, c); case "Failed": return void (c && c(a.stateData)); case "Executed": return void b(); case "Loading": case "WaitingOnDeps": return void a.onNextStateChange.push(function () { return i(a, b, c) }); case "Initialized": throw new Error("All dependencies should be loading already before pressureDependencyToExecute is called."); default: throw new Error("Impossible module state: " + a.state); } } function j(a, b) { switch (a.state) { case "Executed": case "Failed": return void b(); default: a.onNextStateChange.push(function () { return j(a, b) }); } } function k(a) { var b = q[a]; return void 0 === b && (b = q[a] = { url: a, urlBase: m(a), exports: Object.create(null), state: "Initialized", stateData: void 0, isTopLevel: !1, onNextStateChange: [] }), b } function l(a) { return v.href = a, v.href } function m(a) { return a = a.split("?")[0], a = a.split("#")[0], a.substring(0, a.lastIndexOf("/") + 1) } function n(a, b) { return -1 === b.indexOf("://") ? l("/" === b[0] ? b : a + b) : b } function o() { return document.baseURI || (document.querySelector("base") || window.location).href } function p() { var b = document.currentScript; if (!b) return u; if (window.HTMLImports) { var c = window.HTMLImports.importForElement(b); return c ? c.href : u } var d = b.ownerDocument.createElement("a"); return d.href = "", d.href } if (!window.define) { var q = Object.create(null), r = void 0, s = 0, t = void 0, u = o(); window.define = function (a, b) { var d = !1; r = function () { return d = !0, r = void 0, [a, b] }; var f = p(); setTimeout(function () { if (!1 == d) { r = void 0; var g = f + "#" + s++, h = k(g); h.isTopLevel = !0; var i = c(h, a, b); void 0 === t ? e(i) : j(k(t), function () { e(i) }), t = g } }, 0) }, window.define._reset = function () { for (var a in q) delete q[a]; r = void 0, s = 0, t = void 0, u = o() }; var v = document.createElement("a") } })();
var defs = [
cdn + "build/es5-amd/node_modules/web-animations-js/web-animations-next-lite.min.js",
cdn + "build/es5-amd/node_modules/promise-polyfill/dist/polyfill.min.js",
cdn + "build/es5-amd/node_modules/fetch-ie8/fetch.js",
cdn + "babel/babel-top.js"
];
defs.push(' . implode(',', $es5) . ');
define(defs, function () { "use strict" });
define([cdn + "build/es5-amd/node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"], function () { "use strict" });
}
}
else {
"use strict"; (function () { function a(a, b, c) { var d = a; if (d.state = b, d.stateData = c, 0 < d.onNextStateChange.length) { var e = d.onNextStateChange.slice(); d.onNextStateChange.length = 0; for (var f, g = 0, h = e; g < h.length; g++)f = h[g], f() } return d } function b(b) { function d() { try { document.head.removeChild(f) } catch (a) { } } var e = a(b, "Loading", void 0), f = document.createElement("script"); return f.src = b.url, f.onload = function () { var a, b, f; void 0 === r ? (b = [], f = void 0) : (a = r(), b = a[0], f = a[1]), c(e, b, f), d() }, f.onerror = function () { g(b, new TypeError("Failed to fetch " + b.url)), d() }, document.head.appendChild(f), e } function c(b, c, e) { var f = d(b, c), g = f[0], h = f[1]; return a(b, "WaitingForTurn", { args: g, deps: h, moduleBody: e }) } function d(a, c) { for (var e, f = [], g = [], i = 0, j = c; i < j.length; i++) { if (e = j[i], "exports" === e) { f.push(a.exports); continue } if ("require" === e) { f.push(function (b, c, e) { var f = d(a, b), g = f[0], i = f[1]; h(i, function () { c && c.apply(null, g) }, e) }); continue } if ("meta" === e) { f.push({ url: !0 === a.isTopLevel ? a.url.substring(0, a.url.lastIndexOf("#")) : a.url }); continue } var l = k(n(a.urlBase, e)); f.push(l.exports), g.push(l), "Initialized" === l.state && b(l) } return [f, g] } function e(b) { var c = a(b, "WaitingOnDeps", b.stateData); return h(b.stateData.deps, function () { return f(c) }, function (a) { return g(c, a) }), c } function f(b) { var c = b.stateData; if (null != c.moduleBody) try { c.moduleBody.apply(null, c.args) } catch (a) { return g(b, a) } return a(b, "Executed", void 0) } function g(b, c) { return !0 === b.isTopLevel && setTimeout(function () { throw c }), a(b, "Failed", c) } function h(a, b, c) { var d = a.shift(); return void 0 === d ? void (b && b()) : "WaitingOnDeps" === d.state ? (!1, void h(a, b, c)) : void i(d, function () { h(a, b, c) }, c) } function i(a, b, c) { switch (a.state) { case "WaitingForTurn": return e(a), void i(a, b, c); case "Failed": return void (c && c(a.stateData)); case "Executed": return void b(); case "Loading": case "WaitingOnDeps": return void a.onNextStateChange.push(function () { return i(a, b, c) }); case "Initialized": throw new Error("All dependencies should be loading already before pressureDependencyToExecute is called."); default: throw new Error("Impossible module state: " + a.state); } } function j(a, b) { switch (a.state) { case "Executed": case "Failed": return void b(); default: a.onNextStateChange.push(function () { return j(a, b) }); } } function k(a) { var b = q[a]; return void 0 === b && (b = q[a] = { url: a, urlBase: m(a), exports: Object.create(null), state: "Initialized", stateData: void 0, isTopLevel: !1, onNextStateChange: [] }), b } function l(a) { return v.href = a, v.href } function m(a) { return a = a.split("?")[0], a = a.split("#")[0], a.substring(0, a.lastIndexOf("/") + 1) } function n(a, b) { return -1 === b.indexOf("://") ? l("/" === b[0] ? b : a + b) : b } function o() { return document.baseURI || (document.querySelector("base") || window.location).href } function p() { var b = document.currentScript; if (!b) return u; if (window.HTMLImports) { var c = window.HTMLImports.importForElement(b); return c ? c.href : u } var d = b.ownerDocument.createElement("a"); return d.href = "", d.href } if (!window.define) { var q = Object.create(null), r = void 0, s = 0, t = void 0, u = o(); window.define = function (a, b) { var d = !1; r = function () { return d = !0, r = void 0, [a, b] }; var f = p(); setTimeout(function () { if (!1 == d) { r = void 0; var g = f + "#" + s++, h = k(g); h.isTopLevel = !0; var i = c(h, a, b); void 0 === t ? e(i) : j(k(t), function () { e(i) }), t = g } }, 0) }, window.define._reset = function () { for (var a in q) delete q[a]; r = void 0, s = 0, t = void 0, u = o() }; var v = document.createElement("a") } })();
var defs = [
cdn + "build/es6-amd/node_modules/web-animations-js/web-animations-next-lite.min.js",
cdn + "babel/babel-top.js"
];
if (window.customElements) { // certain FF / Safari versions
defs.push(cdn + "build/es6-amd/node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js");
}
else {
defs.push(cdn + "build/es6-amd/node_modules/promise-polyfill/dist/polyfill.min.js");
defs.push(cdn + "build/es6-amd/node_modules/fetch-ie8/fetch.js");
defs.push(cdn + "build/es6-amd/node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js");
}
defs.push(' . implode(',', $es6Amd) . ');
define(defs, function () { "use strict" });
}
old=true;
}
</script>
<script>if(old)document.write(\'<!--\');</script>
<script async defer type="module">
' . implode("\n", $es6) . '
</script>
<script async src="' . $directory . 'build/es6/node_modules/web-animations-js/web-animations-next-lite.min.js">
//<!--! do not remove -->
</script>';
}
}