Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
BernhardBaumrock committed Oct 20, 2024
2 parents 51c778c + aee82a6 commit b425d12
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 137 deletions.
31 changes: 22 additions & 9 deletions RockFrontend.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,15 +121,9 @@ if (typeof RockFrontend === "undefined") var RockFrontend = {};
});

// toggle checkboxes based on enabled state
let checkboxes = document.querySelectorAll(".rf-consent-checkbox");
this.each(checkboxes, (cb) => {
let name = cb.getAttribute("data-name");
if (this.isEnabled(name)) {
cb.setAttribute("checked", "checked");
} else {
cb.removeAttribute("checked");
}
});
setTimeout(() => {
this.toggleCheckboxes();
}, 0);

// debugging
// console.log(C.getStorage());
Expand All @@ -142,6 +136,19 @@ if (typeof RockFrontend === "undefined") var RockFrontend = {};
localStorage.setItem("rockfrontend-consent", JSON.stringify(storage));
};

// toggle checkboxes based on consent state
Consent.prototype.toggleCheckboxes = function () {
let checkboxes = document.querySelectorAll(".rf-consent-checkbox");
this.each(checkboxes, (cb) => {
let name = cb.getAttribute("data-name");
if (this.isEnabled(name)) {
cb.setAttribute("checked", "checked");
} else {
cb.removeAttribute("checked");
}
});
};

// monitor checkbox changes
document.addEventListener("change", function (e) {
let cb = e.target;
Expand Down Expand Up @@ -235,6 +242,12 @@ if (typeof RockFrontend === "undefined") var RockFrontend = {};
// trigger confirmation click
document.querySelector(ask).click();
}

// reload all checkboxes
// this makes sure that all checkboxes on the page have the correct state
// even if, for example, a checkbox is present more than once (eg on a
// regular page and in a modal overlay)
C.toggleCheckboxes();
});

RockFrontend.Consent = C;
Expand Down
5 changes: 3 additions & 2 deletions RockFrontend.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

106 changes: 59 additions & 47 deletions RockFrontend.module.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace ProcessWire;

use ExposeFunctionsExtension;
use HumanDates;
use Latte\Engine;
use Latte\Runtime\Html;
Expand Down Expand Up @@ -173,6 +174,10 @@ public function __construct()

public function init()
{
// load composer autoloader as early as possible
// this is so that anyone can create custom latte extensions
// without having to require the autoloader in their extension
require_once $this->path . "vendor/autoload.php";
$this->wire->classLoader->addNamespace("RockFrontend", __DIR__ . "/classes");

// if settings are set in config.php we make sure to use these settings
Expand Down Expand Up @@ -732,11 +737,21 @@ private function ajaxFormatted($raw, $endpoint): string

private function ajaxPublic($endpoint): string
{
try {
// return function to keep code DRY
$return = function ($endpoint) {
$raw = $this->ajaxResponse($endpoint);
$response = $this->ajaxFormatted($raw, $endpoint);
header('Content-Type: ' . $this->contenttype);
return $response;
};

// for debugging we don't catch errors
if (wire()->config->debug) return $return($endpoint);

// public endpoints return a generic error message
// to avoid leaking information
try {
return $return($endpoint);
} catch (\Throwable $th) {
$this->log($th->getMessage());
return "Error in AJAX endpoint - error has been logged";
Expand Down Expand Up @@ -1210,23 +1225,13 @@ public function editorLink($path)
}

/**
* Get field via short name (useful for prefixed fields)
*
* For convenient use with Latte this will return a HTML object if possible.
*
* Options for type:
* e (default) = edit
* u = unformatted
* f = formatted
* s = string
* h = latte html object
* a = array
* [] = array
* first = single item
* Get field via short name (useful for prefixed fields) and define return type
*
* Example:
* field = my_prefix_myfield
* echo $page->field('myfield', 'u');
*
* See possible type values from the switch statement below
*/
public function field(
Page $page,
Expand All @@ -1242,37 +1247,41 @@ public function field(

// the noEdit flag prevents rendering editable fields
if ($type === 'e' && $this->noEdit) $type = 'f';

// edit field
if ($type === 'e') return $this->html($page->edit($fieldname));

// force string
if ($type === 's') {
return (string)$page->getFormatted($fieldname);
switch ($type) {
case 'e':
case 'edit':
// edit field
return $this->html($page->edit($fieldname));
case 'f':
case 'formatted':
// formatted
return $page->getFormatted($fieldname);
case 'u':
case 'unformatted':
// unformatted
return $page->getUnformatted($fieldname);
case 's':
case 'string':
// string
return (string)$page->getFormatted($fieldname);
case 'h':
case 'html':
// latte html object
return $this->html((string)$page->getFormatted($fieldname));
case 'i':
case 'int':
// integer
// using (string) to convert pages to ids
return (int)(string)$page->getFormatted($fieldname);
case 'a':
case 'array':
case '[]':
// formatted as array (eg pageimages)
return $page->getFormatted("$fieldname.[]");
case 'first':
// formatted as single item (eg pageimage)
return $page->getFormatted("$fieldname.first");
}

// formatted
if ($type === 'f') {
return $page->getFormatted($fieldname);
}

// latte html object
if ($type === 'h') {
return $this->html((string)$page->getFormatted($fieldname));
}

// formatted as array (eg pageimages)
if ($type === 'a' || $type === '[]') {
return $page->getFormatted("$fieldname.[]");
}

// formatted as single item (eg pageimage)
if ($type === 'first') {
return $page->getFormatted("$fieldname.first");
}

// unformatted
if ($type === 'u') return $page->getUnformatted($fieldname);
}

/**
Expand Down Expand Up @@ -2002,15 +2011,18 @@ public function ___loadLatte($withLayout = false)
if ($this->latte) return $this->latte;

try {
require_once __DIR__ . "/translate.php";
require_once $this->path . "vendor/autoload.php";

$latte = new Engine;
$latte->setTempDirectory($this->wire->config->paths->cache . "Latte");
if ($this->wire->modules->isInstalled("TracyDebugger")) {
$latte->addExtension(new \Latte\Bridges\Tracy\TracyExtension());
}

// make processwire functions like wire() available in latte
// see https://processwire.com/talk/topic/30449-questions-and-syntax-latte-template-engine-by-nette/?do=findComment&comment=244743
// and https://forum.nette.org/en/36678-add-namespace-to-compiled-latte-files
require_once __DIR__ . "/latte/ExposeFunctionsExtension.php";
$latte->addExtension(new ExposeFunctionsExtension());

// add custom filters
// you can set $config->noLatteFilters = true to prevent loading of
// custom filters.
Expand Down
32 changes: 0 additions & 32 deletions docs/template-engines/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,38 +28,6 @@ $wire->addHookAfter("RockFrontend::loadLatte", function ($event) {

You created a useful filter? Share it with us in the forum!

### Translatable Strings

Since version 2.24.0 RockFrontend supports translatable strings in latte files!! 😎🥳

You just need to make sure that latte files are enabled in PW's translation system. In your PW backend search for "translator" and go to the module settings of the "Language Translator" module:

<img src=translator.png class=blur>

These are the three versions that you can use to translate strings in your LATTE files - choose whatever you prefer.

```latte
<p>{=__('This is a test')}</p>
<p>{=_x('foo bar', 'context')}</p>
<p>{=_n('Found one item', 'Found multiple items', 1)}</p>
<p>{=_n('Found one item', 'Found multiple items', 2)}</p>
<p>{$rf->_('This is a test')}</p>
<p>{$rf->_x('foo bar', 'context')}</p>
<p>{$rf->_n('Found one item', 'Found multiple items', 1)}</p>
<p>{$rf->_n('Found one item', 'Found multiple items', 2)}</p>
<p>{$rockfrontend->_('This is a test')}</p>
<p>{$rockfrontend->_x('foo bar', 'context')}</p>
<p>{$rockfrontend->_n('Found one item', 'Found multiple items', 1)}</p>
<p>{$rockfrontend->_n('Found one item', 'Found multiple items', 2)}</p>
```

Note that when using the function-syntax you must prepend the function call with an equal sign! While the translation will - in theory - also work without the equal sign you will not be able to translate the string in the backend, because the regex will not find it!

### setTextdomain

TBD

## Twig

Expand Down
24 changes: 24 additions & 0 deletions latte/ExposeFunctionsExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

use Latte\Extension;

final class ExposeFunctionsExtension extends Extension
{
/**
* This method will create a list of all defined PHP functions
* It will return an array where the key will be the function name
* (without the namespace) and the value will be a callback to that
* function.
*/
public function getFunctions(): array
{
$functions = get_defined_functions()['user'];
$result = [];
foreach ($functions as $function) {
if (!str_starts_with($function, 'processwire\\')) continue;
$name = str_replace('processwire\\', '', $function);
$result[$name] = $function;
}
return $result;
}
}
30 changes: 17 additions & 13 deletions livereload.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ setTimeout(() => {
let isModal = !!document.querySelector("body.modal");
if (isModal) return;
let reloading = false;
let warningShown = false;

// dont load in iframes
if (window.self !== window.top) return;
Expand Down Expand Up @@ -45,19 +46,22 @@ setTimeout(() => {
} else {
// check if we are in the admin and have unsaved changes
if (document.querySelectorAll(".InputfieldStateChanged").length) {
console.log("detected change - unsaved changes prevent reload");
// show notification
// delay of 200ms prevents that the notification is shown
// when a page is saved that creates files in the background
setTimeout(() => {
UIkit.notification({
message:
"Unsaved changes prevent reload - use $config->livereloadForce to force reload.",
status: "warning",
pos: "top-center",
timeout: 0,
});
}, 200);
if (!warningShown) {
console.log("detected change - unsaved changes prevent reload");
// show notification
// delay of 200ms prevents that the notification is shown
// when a page is saved that creates files in the background
setTimeout(() => {
UIkit.notification({
message:
"Unsaved changes prevent reload - use $config->livereloadForce to force reload.",
status: "warning",
pos: "top-center",
timeout: 0,
});
}, 200);
warningShown = true;
}
return;
}
if (document.querySelectorAll("#pw-panel-shade").length) {
Expand Down
Loading

0 comments on commit b425d12

Please sign in to comment.