cwsoft
Members-
Posts
167 -
Joined
-
Last visited
-
Days Won
3
Everything posted by cwsoft
-
Though about automatic layout loading too, but decided not to implement it yet (Python ZEN says Explizit is better than Implicit). However I may add a method to include custom CSS or Javascript code/files into head/body to the DefaultPage class. If I do, it will most likely be similar to what I implemented in my modules EmailToEncryptedMailto and NoCookieWithoutConsent, just with some more options/parameters. For sure my approach will only add basic stuff and not try to reimplement RockFrontend. As mentioned I may switch to RockFrontend anyway mid to long term. Cheers cwsoft
-
Hi Bernhard, thanks for your feedback. Fully agree, custom page classes and Latte templates are really awesome features and help to keep custom projects structured and clean. Regarding your suggestion about ProcessWire translate functions. So far all my custom projects are German only sites, so I had no need to implement this feature yet. However a great suggestion as usual, which may find it‘s way into a follow up writing. Wished I knew about the potential of page classes an Latte already in my first project. However in future projects I will make use of page classes and Latte right from the beginning. And if I find some spare time, maybe I will switch to RockFrontend mid to long term. Regards cwsoft
-
This tutorial is about making the Latte template engine available in ProcessWire template files via the use of ProcessWires Custom Page Classes. Based on some inspiring posts from @bernhard, I wanted to use custom page classes and Latte templates in my own projects. I know there are modules like RockFrontend and others available to integrate template engines like Latte or Twig . However I wanted to start with a small, flexible and reusable code base as playground for my next projects without module dependencies as starting point. Please note: The template part of this tutorial assumes you are using the Site profile Default profile (standard/intermediate edition), which can be downloaded from the ProcessWire Github repository. Here a technique called delayed output strategy is used. I also posted an alternative Latte implementation some posts below, using a normal class file for implementing Latte via your template _init.php file. Step 1: Enable ProcessWire Custom Page Classes PageClasses were added with ProcessWire 3.0.152. To use page classes open site/config.php and enable the feature if needed via $config->usePageClasses = true;. After that create the folder site/classes in your site installation and add the PHP file DefaultPage.php inside with the following content for now. <?php namespace ProcessWire; class DefaultPage extends Page {} The DefaultPage class is used whenever a ProcessWire template like site/templates/your-template.php has no page class associated with it. In other words, if no site/classes/YourTemplatePage.php exists, the default page class site/classes/DefaultPage.php is used as fallback. Step 2: Install PHP Dependency Manager Composer As we are using the Latte Composer package, we first need to install Composer on our computer if not yet available. Visit the Composer webiste and install Composer on your system. On Windows just grab the Composer-Setup.exe file and execute it. Once Composer is installed, open a new terminal and type the command composer. You should see some Composer output in your console. If so, proceed with Step 3. If an error occurs, please read and follow the Docs on the Composer website to get Composer installed on your system before proceeding with this tutorial. Step 3: Install Latte Composer Package In the next step, we install the Latte template engine files as Composer package in our site folder. Open a terminal and switch into your local site/classes folder created in Step 1. From inside the site/classes folder type the following command into your terminal composer require latte/latte. Please note: If your installation has a composer.json file in the root, you will get asked if you want to use the composer.json in the root. As this tutorial assumes to install the composer files inside our site/classes folder, you MUST answer no. Otherwise the Latte files will be installed inside /root/vendor not /root/site/classes/vendor as expected in this tutorial. Once done, your site classes folder should contain a vendor folder with the Latte composer files, the two Composer files composer.json and composer.lock and our DefaultPage.php file created in Step 1. site/ classes/ vendor/ bin/ composer/ latte/ autoload.php composer.json composer.lock DefaultPage.php (implements Latte logic inherited by other PageClasses) EventsPage.php (implements logic for /templates/events.php) // Note this part is setup and explained later in this tutorial templates/ views/ events.latte your-template.php (associated with fallback classes/DefaultPage.php) events.php (associated with classes/EventsPage.php) Please note: The files located under site/templates are explained later in this tutorial. I just thought it would be a good idea to show the relevant file structure at one spot. Step 4: Make Latte available from PageClasses Now we need to make Latte available in our custom PageClasses. Open site/classes/DefaultPage.php and change the code as follows: <?php namespace ProcessWire; /** * The DefaultPage class implements methods to render Latte templates as string. This page class serves as * fallback for PW templates inside site/templates not implementing their own page class inside site/classes. */ class DefaultPage extends Page { protected static \Latte\Engine|null $latte = null; private array $latteConfig = []; // Constructor. public function __construct(Template $tpl = null) { parent::__construct($tpl); $this->setupLatteEngine(); $this->setLatteConfig(); } // Set or update Latte configuration. public function setLatteConfig(array $config = []): void { if (!isset(self::$latte)) return; // Remove keys from user config not available in Latte defaults, except for 'pwAPI'. $config = array_intersect_key($config, $this->getLatteDefaultConfig()); // Merge user config with Latte defaults. $this->latteConfig = array_merge($this->getLatteDefaultConfig(), $config); // Apply updated configuration to actual Latte instance. self::$latte->setAutoRefresh($this->latteConfig['autoRefresh']); self::$latte->setTempDirectory($this->latteConfig['cacheFolder']); } // Render given Latte template as string, injecting ProcessWire API and $data. public function renderTemplate(string $template, array $data = []): string { if (!isset(self::$latte) || !$this->latteConfig) return ''; // Ensure Latte template exists within specified template folder. $latteTemplateFolder = realpath($this->latteConfig['latteTemplateFolder']); $templatePath = realpath($latteTemplateFolder . '/' . $template); if ($templatePath === false || stripos($templatePath, $latteTemplateFolder) !== 0) { throw new \Exception("Latte template '$template' not found or outside 'latteTemplateFolder'."); } // Render Latte template and inject ProcessWire API and $data. return self::$latte->renderToString($templatePath, array_merge($data, $this->latteConfig['pwAPI'])); } // Returns associative array with Latte default configuration. protected function getLatteDefaultConfig(): array { return [ 'autoRefresh' => true, 'cacheFolder' => $this->wire('config')->paths->cache . 'Latte/', 'latteTemplateFolder' => $this->wire('config')->paths->templates, 'pwAPI' => [ 'page' => $this, 'pages' => $this->wire('pages'), 'config' => $this->wire('config'), ], ]; } // Initiate Latte template engine. private function setupLatteEngine(): void { if (isset(self::$latte)) return; require_once "vendor/autoload.php"; self::$latte = new \Latte\Engine; } } The DefaultPage class assumes the Latte template files to be stored inside path site/templates/. By default we can access the PW-API $page, $pages and $config inside our Latte templates. You can add more ProcessWire APIs like $sanitizer or template specific data via the setLatteConfig() method or via the optional associative array $data of the renderTemplate() method. Assume we have another PageClass in site/classes/EventsPage.php, which implements the complex method hello(). To make the Latte render methods available in the EventsPage class, we need to extend from our DefaultPage class instead of the ProcessWire Page class. This way we can create as many page classes with logic for specific templates as needed, while keeping code structured and organized. <?php namespace ProcessWire; class EventsPage extends DefaultPage { public function hello() { return "Hello World!"; } } Step 5: Add Latte template (acting as View) Next we add a Latte template file to site/templates/views/events.latte with the following content. <div> <h2>{$page->title|capitalize}</h2> <p>PageId: {$page->id}</p> <p n:if="$config->useFunctionsAPI"> Using Functions API and Latte is fun. </p> {* This will be translated based on the default PW language or users language preference *} <p>{$lang['Please select a date']}</p> <ul n:if="$page"> <li n:foreach="$page->getFields() as $field"> $page->{$field}: {$page->$field} </li> </ul> </div> Step 6: Render Latte template from ProcessWire templates (acting as Controller) The code below shows how custom methods and the Latte render method can be invoked within normal ProcessWire templates like site/templates/events.php. The first code line appends the output from the method hello() implemented in the associated PageClass site/classes/EventsPage.php to our template $output variable. Please note: In this example the ProcessWire template file uses a technique called Delayed Output Strategy. You can read more about this strategy in the linked ProcessWire blog post from Ryan. <?php namespace ProcessWire; /** * Template: "events.php" * Using Processwire delayed output strategy * https://processwire.com/docs/tutorials/how-to-structure-your-template-files/ */ // Append output from method hello() implemented in `site/classes/EventPage.php`. $content .= $page->hello(); // Add needed translations here. You can access them via $lang inside your Latte template. // The translation for 'Please select a date' can be added via the ProcessWire backend. // For details see https://processwire.com/docs/multi-language-support/code-i18n/. $data = ['lang' => [ 'Please select a date' => __('Please select a date!'), ], ]; // Append output of rendered Latte template located in `site/templates/views/events.latte`. $content .= $page->renderTemplate('views/events.latte', $data); At the bottom of our template file site/templates/events.php we call the render method implemented in site/classes/DefaultPage.php to render the specified Latte template in site/templates/views/events.latte. The ProcessWire API $page, $pages, $config is available in all Latte templates by default. As the EventsPage class extends the DefaultPage class, it inherents it's render methods This way we need to implement the Latte template code once, but can use it in all our custom PageClasses and default ProcessWire template files located in /site/templates. Note: If you are using the output strategy Markup regions, the Events template file would look as follows: <?php namespace ProcessWire; /** * Template: "events.php" * Using Processwire delayed output strategy * https://processwire.com/docs/tutorials/how-to-structure-your-template-files/ */ // Append output from method hello() implemented in `site/classes/EventPage.php`. // Add needed translations here. You can access them via $lang inside your Latte template. // The translation for 'Please select a date' can be added via the ProcessWire backend. // For details see https://processwire.com/docs/multi-language-support/code-i18n/. $data = [ 'lang' => [ 'Please select a date' => __('Please select a date!'), ], ]; ?> <div id="content"> <?= $page->hello(); ?> <?= $page->renderTemplate('views/events.latte', $data); ?> </div> Have fun. cwsoft Please note: Edited the initial post to include the code suggestions from member @d'Hinnisdaël some posts below. Thanks for your suggestions.
-
Is storing an API secret in a Hidden Page's field recommended ?
cwsoft replied to protro's topic in General Support
Hi, if it‘s save depends on your setup and user permissions. The secret would be contained in the PHP file and on save in the PW database and may find it‘s way into Github or server/user backups some time. If users have access to FTP they can extract the secret from files on your server. Users with access to templates fields may add a template exposing your secret using your API etc. So I would say it depends on your setup and use case.- 1 reply
-
- 1
-
Tutorial: How to show all speakers in a speakers block.
cwsoft replied to bernhard's topic in RockPageBuilder
Thanks for sharing. Seems I need to learn more about MVC and PHP/Latte templates for my next PW project. For small sites I am using the delayed output strategy (main.inc.php etc.). But as projects grow, I start to structure stuff in subfolders inside site/template folder. -
Than I would just upload via Ftp or PW assets and create a template to display them with a download link on page. A google search showed me this topic, which may come handy too.
-
Hi, depends on your needs. Do the Pdf docs contain sensible data, are the docs restricted to users or groups? Can the docs easily guessed and accessed by changing a simple URL parameter like doc_001.pdf, doc_002.pdf etc? Depending on your needs, there are several options to implement it like simple .htaccess with Index listing, a restricted page with non guessable links … So some more infos would be useful here.
-
Hi, if you want to hide/protect your entire ProcessWire page from unwanted visitors (and bots), you could add the following lines to the end of your .htaccess file in your PW web root to force basic auth protection. In addition I commented out some lines in the default .htaccess file to force HTTPS and non-www like https://domain.com. # 9A. To redirect HTTP requests to HTTPS, uncomment the lines below (also see note above): # ----------------------------------------------------------------------------------------------- # Comment out the two lines below to force HTTPS requests. RewriteCond %{HTTPS} !=on RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] # 13C. Redirect www.domain.com to domain.com (do not combine with 13A or 13B): # ----------------------------------------------------------------------------------------------- # Comment out the two line below to rewrite URL to non-www. RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] RewriteRule ^ %{ENV:PROTO}://%1%{REQUEST_URI} [R=301,L] ################################################################################################# # END PROCESSWIRE HTACCESS DIRECTIVES ################################################################################################# ################################################################################################# # Basic auth protection to hide site from unwanted guests, search engines and bots. # To not ask credentials twice, we allow non HTTPS and WWW first. After ProcessWire redirected # request to non-www HTTPS, we prompt for credential for the basic auth once. ################################################################################################# # Detect LOCALHOST env or WWW subdomain. SetEnvIf HOST ^localhost LOCALHOST SetEnvIf HOST ^www\. WWW # Basic authentification AuthType Basic AuthName "Restricted area" AuthUserFile /kunden/path_to_your_webroot/.htusers # Deny access to all, except for LOCALHOST, WWW, HTTP or valid-user. Order Deny,Allow Deny from all Satisfy any Allow from env=LOCALHOST Allow from env=WWW Allow from env=!HTTPS require valid-user You can create the password hash for the .htusers file (username:hashed_password) with the PHP commands below. Don't forget to adapt the path in AuthUserFile to match your .htusers file in your .htaccess file too. <?php // Create a password hash for Basic Auth. $user = "your-username"; $plain = 'your-password'; $hash = password_hash($plain, PASSWORD_BCRYPT); // Output required .htusers data on screen. echo '<h2>Data for .htusers file in PW webroot</h2>'; echo '<p><strong>PATH</strong>: ' . __DIR__ . DIRECTORY_SEPARATOR . '.htusers</p>'; echo '<p><strong>username:hash</strong>: ' . "$user:$hash"; Have fun. cwsoft
-
I am just using VSCode and node modules to compile my SCSS and Typescript files into CSS and Javascript and esbuild if needed to bundle/minify files before commit. Basically all my local site/template and site/module folders are git repos. The server structure contain just the created CSS/JS files without the git repo and node modules.
-
Hello, I have released version v1.1.1 of my EmailToEncryptedMailto module, providing the following new features and bugfixes: Skipped emails entered in input fields from encryption (bugfix, thanks to @Thomas -Allwinds Webstudio) Preserved optional attributes like id, class, data-attributes in mailto links (feature) Added option to specify pageIDs of pages to skip from obfuscation via module config (feature) You can download the latest version from the Processwire module repository as usual. Have fun cwsoft
-
@Thomas -Allwinds WebstudioThanks for your feedback. If you disable the code line you mentioned, no text based email like test@domain.com will be obfuscated on any of your pages. However, regular mailto links will still work just fine. The regex used to extract text mails and mailto links are as follows: $patternEmail = '#<a [^>]+>.*?</a>(*SKIP)(*FAIL)|(?<email>[\._a-z0-9-]+@[\._a-z0-9-]+)#i'; $patternMailto = '#<a href=([\'"])mailto:(?<email>.*?)\1>(?<text>.*?)</a>#i' One workaround would be to use an email pattern not recognized by the two regex (which won´t help in your case), or to modify the regex for $patternEmail to skip text emails inside link tags AND input fields. So you could try to change this line inside EmailToEncryptedMailto.module.php as follows: // Regex to find text emails in text excluding emails inside link tags and input fields. private $patternEmail = '#<a [^>]+>.*?</a>(*SKIP)(*FAIL)|<input [^>]+>(*SKIP)(*FAIL)|(?<email>[\._a-z0-9-]+@[\._a-z0-9-]+)#i'; I already planned an option to disable obfuscation based on user defined pageIDs, which may be handy for form or newsletters pages with emails. Not too sure if I want to add an option to skip obfuscation for mailto links with a certain data-attribute/class or text mails e.g. wrapped in a span tag with a certain class too. But an option to skip obfuscation by pageIDs and or turn on/off mailto/email obfuscation may be an handy option for the next release together with the modified regex to exclude emails from input fields too. Will add some of those features with the next release.
-
Dear all, just released version 1.0.1 of my ProcessWire site module NoCookieWithoutConsent on the ProcessWire module repository. Added the option to specify URL segments for the optional imprint and privacy policy page via the module configuration in the backend. If the URL segments are set, the link to the specified page will be shown in the footer of the cookie consent dialogue. If no URL segments are specified, no links are shown at all (default). As the module runs without issues on some client sides already, I pumped the version from v0.0.2 to v1.0.0 (quickly followed by v1.0.1 fixing an overseen hardcoded URL). Have fun.
-
Yeah, my module was approved and is now listed in the ProcessWire module catalog https://processwire.com/modules/email-to-encrypted-mailto/. Thanks to all and have fun.
-
Yeah, my module was approved and is now listed in the ProcessWire module catalog https://processwire.com/modules/no-cookie-without-consent/. Thanks to all and have fun.
-
Have you tried with a clean default PW installation with a default template and just Tracy installed? If that works try to install your two rock modules in two steps and check if console lags still occur. Thats what I would try to narrow down the possible error sources. If you can find a reproducible setup it‘s easier to spot the error for others like Adrian too.
-
Dear all, just to let you know. I uploaded my module EmailToEncryptedMailto to the ProcessWire modules directory: https://processwire.com/modules/email-to-encrypted-mailto/ Please note: Module needs to pass the official approval before it will show up in the modules directory for others too. Cheers cwsoft
-
Dear all, just to let you know. I uploaded my module NoCookieWithoutConsent to the ProcessWire modules directory: https://processwire.com/modules/no-cookie-without-consent/. Please note: Module needs to pass the official approval before it will show up in the modules directory for others too. Cheers cwsoft
-
@cpx3Are there any Javascript errors in the console? Seems you are using jQuery for the Ajax request. Maybe there are some conflicts with other JS libs.
-
Hi and welcome, How does your PHP script look like, what does it return as result on success or failure?
-
Hi and welcome, maybe you can provide some more details. Do you have a HTML template already? How many products do you need, what kind of categories, filters etc. How should products be added and by whom? Do you have a link to a eCommerce Shop looking similar to what you want? Have you tried any other shop systems already? Have you checked the PW module directory for solutions yet and checked if they include all the stuff you need like https://processwire.com/blog/posts/padloper-brings-ecommerce-to-processwire/?
-
Just for some further reading https://dev.to/walternascimentobarroso/dotenv-in-php-45mn
-
@Bernhard. Maybe a sort of never change a running/known system. Guess it‘s hard to leave an area where you have some profound knowledge for something new before the known systems shows it‘s limitations or starts to get annoying. Another big driver are customers, which are used to Drupals backend and workflow and avoid a change to something new as well.
-
Hello! Looking to choose a CMS to replace an old Drupal install.
cwsoft replied to Roadwolf's topic in Getting Started
Would also go with one PW install and one DB per website. PW is easy to update by just replacing the core files located in /wire (and .htaccess, index.php in the root), while keeping untouched all the stuff in your /site folder. DB migration is easy too compared to older WordPress sites, as no hard coded page links with fixed domains are stored in the DB. Really like how easy you can deploy a site developed locally to a live server. -
Hi, you can bootstrap processwire in own PHP scripts following this howto https://processwire.com/docs/front-end/include/. For sure you could include the PW index.php script in your PHP app to check if a user has logged into the PW part of your site. But it wouldn‘t provide lot of features to access non PW user credential infos like login data of your App outside PW etc. Unfortunately the infos are a bit weak so I can‘t become more precise as I haven‘t fully understood what you want to achieve or what data you want to access from the non PW part.
-
Dear all, just released v0.0.5 of my EmailToEncryptedMailto module. The latest release adds support for regular mailto links. So with v0.0.5 all text emails and regular mailto links will be converted into encrypted mailto link variants on the fly. You can add a subject to your mailto links by adding "mailto:info@domain.com?subject=Your Subject" at the end of the email in the mailto part. Apart from that some further code cleanup. Have fun P.S.: The Github release section contains a ZIP-file containing just the ProcessWire module files without the DEV stuff included. The attached ZIP-file is the preferred installation option for end users, while cloning the git repo is the preferred option for devs wanting to adapt/modify the module code. P.P.S: Encrypted mailto links do not yet preserve class or id attributes. That will maybe added in a future release depending on customers needs.