cwsoft
Members-
Posts
167 -
Joined
-
Last visited
-
Days Won
3
Everything posted by cwsoft
-
How to protect files from being downloaded directly via url
cwsoft replied to hintraeger's topic in API & Templates
The line with the readfile command has three dots at the end which seems strange to me and then adds whatever is your $download variable. Have you checked that path e.g. via outputin template and checked if file is readable? -
@BoostGuess stability, security and privacy data protection. I don‘t like my IP send to CDN servers and for some of my customers this would be a no go at all.
-
I do like to refine some of my code in little steps or to prompt the AI for specific questions on my own code, like I did in the past as part of a development team with my human colleagues. Thats where AI is really not so bad in my opinion, at least if you are working alone on projects and there are no human colleagues you could ask.
-
Yepp. No big difference from copying code from Stackoverflow and executing it if you are not really understanding what it is doing or to clone and run stuff from Github repos you don‘t own or trust, or entering the NPM dependency hell for something which just pads a string with leading numbers loading other node packages to do the job for example.
-
@da²Guess Bernhard still checks the generated code for stuff which may break things like rm -rf commands before blindly copying and pasting code to clients projects or executing it blindly on his system with root permissions ?
-
Force guest users to login with no backend access at all [solved]
cwsoft replied to cwsoft's topic in General Support
Have realized my guest login via a custom HTML5 frontend-login form and the PW API $session->login() to log in the user with the provided credentials. Combined this with $session->redirect() to route to the page which requested the authorization via $input->get() param on success or back to the frontend-login page on failure. Finally I used the receipt from @bernhard above in templates/admin.php to send frontend-users identified via $user->hasRole() to the home page when they trying to enter the backend. This allowed me to restrict all or certain pages from non authorized access via a simple method implemented in the default page class. Pretty slick what can be achieved with the great PW API plus core and the power of Latte templates of course. -
Have reworked all my projects with Latte and CustomPage classes and the code is more clean, way easier to read and maintain and more structured now. Definitely recommend diving into Latte and CustomPage classes for new projects to anyone. Both techniques were easy to learn and paid off quite soon in my projects.
-
What's the best consolidated jquery resource today in 2024?
cwsoft replied to gornycreative's topic in Dev Talk
Hi, yepp ChatGPT or Copilot with VSCode are great ways to refactor code or automatically add features by prompting your needs. Don‘t use StackOverflow very often these days. -
Hi, so far worked with Copilot and VSCode. As I have an OpenAI API key as well, I will try out Cursor this weekend. Thanks for sharing the info.
-
Force guest users to login with no backend access at all [solved]
cwsoft replied to cwsoft's topic in General Support
@bernhardThanks for the link and code snippet. Second part is what I had in mind. Your hide from guest method from RockMigration looks like what I am after, thanks for sharing. Need to check if my guest users can have a 40-digit uniqueID as username, than I guess I have all the pieces together to realize the idea I have in mind. -
Hi, as htaccess BasicAuth gets more and more blocked by admins via policy rules, I am searching for an alternative solution to hide a PW site from public, non authorized users and spam bots. The „guest users“ should only be able to see the PW frontend after login, but not be able to see the PW backend. The „guest users“ should not even be able to change their login credentials. Login credentials for the up to 500 „guest users“ will be created by the admin in advance and distributed manually e.g. via Email or public post. What would be the best option to realize something like this with PW core or PW modules? Any tip or hint to point me into the right direction would be highly appreciated. Cheers cwsoft
-
I do the following. Copy all files of the live site via FTP to my local dev environment (e.g, /htdocs/pw-test). Create a backup of the MySQL/MariaDB via phpMyAdmin (online). Open my local dev instance of phpMyAdmin (XAMPP) and import the database. You may need to change the DB settings in your local /site/config.php file in case the DB credentials differ between live and local DB connection.
-
this request was aborted because it appears to be forged
cwsoft replied to joshuag's topic in General Support
Two ideas. Give training to the authors not to submit login twice, or explain the error and how to avoid it. Second option is to apply the code changes you proposed and see how it goes. You should consider not to disable login button on wrong user inputs too, otherwise users may not be able to login at all. -
Ok. I finally followed my initial tutorial step by step based on a clean ProcessWire 3.0.229 with basic blank profile (output strategy Markup Regions) and PHP 8.2.4. Following the steps and copying the code one by one showed no warnings or errors at all. Of course i needed to adapt the events.php template for markup regions to see the output. However I found two possible traps one can step into. First trap is related to the installation process of the Latte composer package. If a default ProcessWire composer.json exists in the root of your installation, composer asks to use this composer.json file. If you answer Yes (default), this would install the Latte files in /root/vendor instead of /root/site/classes/vendor as I assume in my tutorial. This could explain the file not found error you mentioned. In order to install the Latte composer files inside /root/site/classes, one needs to answer NO to the composer question "Should I use the composer.json in the root?". Added a note in my initial post to avoid this trap. Second trap could be your template output strategy. My tutorial assumed you are using delayed output strategy, not markup regions or others. If you use markup regions, you won't see any Latte output in the events.php at all. So I decided to add an example for markup regions for the events.php template too. In your specific case, the error may be related to the fact that you already installed other Latte template implementations like RockFrontend, LatteTemplateEngine module or others, which may affect each other (e.g. namespaces, autoloaders). So I guess if you would start with a blank ProcessWire installation, my initial solution should work out of the box for you as well ?.
-
Seem I lost the overview of all your rockstar modules and snippets ?. Anyway keep on rocking. There is almost all times a useful RockX which fits your needs or solves a problem for you.
-
By bootstrapping Processwire via external PHP script and execute it via console or web browser. Some infos can be found in this topic https://processwire.com/docs/front-end/include/. Another option may be RockMigrations from Bernhard https://processwire.com/modules/rock-migrations/.
-
@maetmarFrom an earlier post it seemed you got my 2nd code example where I include a simple Latte class via _init.php working. That‘s the approach I used for the refactoring of two medium sized sites. Worked great. One site used delayed output the other layout regions before with plain PW PHP templates. Converted the main template to Latte and also used a simple MVC approach with Latte as the view part in those two sites. Very flexible setup and easy to transfer to existing sites or start off right from the beginning for new projects too. I will go with this setup for my next projects until I feel the need for more complex features like PW translations in Latte files available in RockFrontend for example.
-
Yepp, good point about wire object. About 98% of my needs are covered by $page, $pages and $config. As I put my page/template related code/logic into custom page classes, it can be used via $page->method() inside my Latte templates too without extra injection. So my normal PW template files act as controller, my Latte templates as view and Page/Custom Page classes as model (at least sort of).
-
Bernhards RockFrontend is at a complete different level than my two Latte implementations in this thread. If RockFrontend works for you, you may be better of staying with Bernhards module. It‘s by far more advanced than my code example and offers tons of other handy features like hot reload, translation functions from Latte templates and much more.
-
@maetmarThe first error indicates that Latte wasn‘t loaded. Please check the path you‘ve installed Latte. I assume you have the files in /site/templates/classes/vendor/… If those files are at the right spot, you may need absolute pathes in require statements. Maybe you can replace the following line (at the end of DefaultPage.php of my first example). require_once "vendor/autoload.php"; by this line require_once wire('config')->site . 'classes/vendor/autoload.php'; Please also check if you have the /Latte/Engine slash at the beginning of the new statement. It may be, that my code interacts with other code in your site like other template engines or composer autoloaders etc. Regarding your second issue. By default I only added $page, $pages and $config to Latte templates. All other variables or objects you want to use in my Latte templates approach, needs to be manually injected like this wire('latte')->renderTemplate('views/standard.latte', [ 'website_name' => $website_name, ]); Now you could use {$website_name} inside your views/standard.latte file. However you could use {$page->title} to display the title of the actual page in standard.latte without requiring to add $page manually, as I added this object by default. P.S. I tested my code on Apache webserver with PHP 8.2 local and in the web. P.P.S.: I‘ve refactored a medium site project recently from Delayed Output with default PHP Templates to Latte Templates (slightly modified 2nd setup of my tutorial) in combination with PageClasses. This allowed me to use a simple but powerful MVC approach, which made the entire code much more structured and improved readability a lot. I added the namespace cwsoft to my LatteTemplateEngine class, so it won‘t interfere with other template classes out there in the wild and did some code cleanup. I can provide the updated code if needed. I will stick with this approach for my next projects and see how far I can go with this approach. For now I am very happy with what was possible with this simple approach.
-
@d'HinnisdaëlThanks for keeping the module updated. Latte rocks.
-
Alternative solution using your template _init.php file to setup the Latte engine. Another option setting up the Latte engine is to add the required code to your _init.php template file (if file exists depends on your output strategy) and add the Latte instance to the global wire object for convenience. File: /site/classes/ProcessWireLatteEngine.php Note: Based on the DefaultPage class code shown in the first post of this thread, I renamed the class to ProcessWireLatteEngine, removed the extends Page part from it's class definition and changed all occurences of $this->wire->xy by wire()->xy. The rest of the code is unchanged compared to the DefaultPage class. <?php namespace ProcessWire; /** * Class LatteEngine initializes the template engine Latte and implements a method to render Latte templates. * Default PW-API ($page, $pages, $config) can be used in Latte templates without additional configuration. */ class ProcessWireLatteEngine { protected static \Latte\Engine|null $latte = null; private array $latteConfig = []; // Constructor. public function __construct(array $config = []) { $this->setupLatteEngine(); $this->setLatteConfig(); } // Set or update Latte configuration. public function setLatteConfig(array $config = []): void { if (!isset(self::$latte)) return; // Remove unknown keys from user config and merge user config with default config. $config = array_intersect_key($config, $this->getLatteDefaultConfig()); $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' => wire('config')->paths->cache . 'Latte/', 'latteTemplateFolder' => wire('config')->paths->templates, 'pwAPI' => [ 'page' => wire('page'), 'pages' => wire('pages'), 'config' => 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; } } File: /site/templates/_init.php (to setup Latte engine) <?php namespace ProcessWire; // Optional initialization file, called before rendering any template file. // This is defined by $config->prependTemplateFile in /site/config.php. // Use this to define shared variables, functions, classes, includes, etc. // Default config applied if no user config was specified via the constructor. // $latteConfig = [ // 'autoRefresh' => true, // 'cacheFolder' => wire('config')->paths->cache . 'Latte/', // 'latteTemplateFolder' => wire('config')->paths->templates, // 'pwAPI' => [ // 'page' => wire('page'), // 'pages' => wire('pages'), // 'config' => wire('config'), // ], // ]; // Setup Latte template engine and store instance in global wire object. // Access Latte render method via wire('latte')->renderTemplate($template, $data). require_once wire('config')->paths->site . 'classes/ProcessWireLatteEngine.php'; wire()->set('latte', new ProcessWireLatteEngine()); File: /site/templates/events.php (example for output strategy Markup Regions) <?php namespace ProcessWire; // Template file for “events.php” template. // ------------------------------------------------------ // The #content div in this file will replace the #content div in _main.php // when the Markup Regions feature is enabled, as it is by default. // You can also append to (or prepend to) the #content div, and much more. // See the Markup Regions documentation: // https://processwire.com/docs/front-end/output/markup-regions/ ?> <div id="content"> Events page content <?= wire('latte')->renderTemplate('views/events.latte'); ?> </div>
-
@d'HinnisdaëlI reworked my DefaultPage class and made the latte object a protected static member of the DefaultPage class to prevent multiple Latte instances as you suggested together with some other small improvements. Have added the updated DefaultPage class code to my initial post in this thread to keep things clean. Cheers cwsoft
-
Thanks for your feedback. I am aware of this issue. As my normal PW installations deal with 5-10 template files, I didn't run into performance or memory issues so far. However I am working on some code improvements right now, which will address your concerns.
-
Hi, updated my initial post with an example of how to use ProcessWire default translation methods in Latte templates. My solution of course is not as elegant as Bernhards solution in RockFrontend, where you can use translation functions inside Latte templates, but it works for my needs. Cheers cwsoft