Search the Community
Showing results for 'runtime'.
-
You can either register your own api variable, eg in ready.php $wire->wire('contact', $yourpage); Or you simply add whatever property you need at runtime to the rockfrontend object: $rockfrontend->foo = 'Foo!'; $rockfrontend->bar = 'Bar!'; Then you can simply access those variables in your latte files: {$contact->title} {$rockfrontend->foo} {$rockfrontend->bar}
-
Just released Wireframe 0.7.0. This version is all about caching: when requesting Controller methods from view (<?= $this->some_controller_method ?> etc.) the return value is now cached (runtime cache). Additionally if method names are added to protected $cacheable_methods property of the controller class, along with an applicable expire time (i.e. "protected $cacheable_methods = [ 'method_name' => 3600 ]"), Wireframe automatically caches the value using WireCache (persistent cache). Caching is usually a good thing, but not always preferred, which is why runtime caching can be prevented by adding the method name to (protected) Controller property $uncacheable_methods (protected $uncacheable_methods = [ 'method_name' ]). Persistent caching is always opt-in. Changelog: ### Added - Runtime caching support for Controller method return values. Values are cached *unless* the name of the method is found from Controller::$uncacheable_methods. - Persistent caching support for Controller method return values. Values are cached only when found from the Controller::$cacheable_methods array. ### Changed - In the View class all internal requests for Controller properties are routed through View::getFromController().
-
Hi everyone, Processwire is in the following folder in my server: var/www/html/project/processwire I've got the following configuration in my .htaccess: ################################################################################################# # START PROCESSWIRE HTACCESS DIRECTIVES # @version 2.2 ################################################################################################# # ----------------------------------------------------------------------------------------------- # Don't show directory indexes, but do follow symbolic links # ----------------------------------------------------------------------------------------------- Options -Indexes Options +FollowSymLinks # ----------------------------------------------------------------------------------------------- # Let ProcessWire handle 404s # ----------------------------------------------------------------------------------------------- ErrorDocument 404 /index.php # ----------------------------------------------------------------------------------------------- # Handle request for missing favicon.ico/robots.txt files (no ending quote for Apache 1.3) # ----------------------------------------------------------------------------------------------- <Files favicon.ico> ErrorDocument 404 "The requested file favicon.ico was not found. </Files> <Files robots.txt> ErrorDocument 404 "The requested file robots.txt was not found. </Files> # ----------------------------------------------------------------------------------------------- # Protect ProcessWire system files (part 1) # ----------------------------------------------------------------------------------------------- <FilesMatch "\.(inc|info|module|sh|sql)$|^(\..*)$"> Order allow,deny </FilesMatch> # ----------------------------------------------------------------------------------------------- # Override a few PHP settings that can't be changed at runtime (not required) # ----------------------------------------------------------------------------------------------- <IfModule mod_php5.c> php_flag magic_quotes_gpc off php_flag magic_quotes_sybase off php_flag register_globals off </IfModule> # ----------------------------------------------------------------------------------------------- # Set default directory index files # ----------------------------------------------------------------------------------------------- DirectoryIndex index.php index.html index.htm # ----------------------------------------------------------------------------------------------- # ProcessWire requires mod_rewrite # ----------------------------------------------------------------------------------------------- <IfModule mod_rewrite.c> RewriteEngine On # ----------------------------------------------------------------------------------------------- # Set an environment variable so the installer can detect that mod_rewrite is active. # ----------------------------------------------------------------------------------------------- SetEnv HTTP_MOD_REWRITE On # ----------------------------------------------------------------------------------------------- # Optional: Set a rewrite base if rewrites aern't working properly on your server. # And if your site directory starts with a "~" you will most likely have to use this. # ----------------------------------------------------------------------------------------------- # RewriteBase / # RewriteBase /pw/ # RewriteBase /~user/ # ----------------------------------------------------------------------------------------------- # Access Restrictions: Keep web users out of dirs that begin with a period # ----------------------------------------------------------------------------------------------- RewriteRule "(^|/)\." - [F] # ----------------------------------------------------------------------------------------------- # Optional: Redirect users to the 'www.' version of the site (uncomment to enable). # For example: http://processwire.com/ would be redirected to http://www.processwire.com/ # ----------------------------------------------------------------------------------------------- # RewriteCond %{HTTP_HOST} !^www\. [NC] # RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301] # ----------------------------------------------------------------------------------------------- # Access Restrictions: Protect ProcessWire system files (part 2) # ----------------------------------------------------------------------------------------------- RewriteCond %{REQUEST_URI} (^|/)\.htaccess$ [NC,OR] RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/assets/(cache|logs|backups|sessions|config|install)($|/.*$) [OR] RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/install($|/.*$) [OR] RewriteCond %{REQUEST_URI} (^|/)(wire|site|site-[^/]+)/(config|index\.config|config-dev)\.php$ [OR] RewriteCond %{REQUEST_URI} (^|/)(wire|site|site-[^/]+)/templates-admin($|/|/.*\.(php|html?|tpl|inc))$ [OR] RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/templates($|/|/.*\.(php|html?|tpl|inc))$ [OR] RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/assets($|/|/.*\.php)$ [OR] RewriteCond %{REQUEST_URI} (^|/)wire/(core|modules)/.*\.(php|inc|tpl|module)$ [OR] RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/modules/.*\.(php|inc|tpl|module)$ [OR] RewriteCond %{REQUEST_URI} (^|/)(COPYRIGHT|INSTALL|README|htaccess)\.txt$ [OR] RewriteCond %{REQUEST_URI} (^|/)site-default/ RewriteRule ^.*$ - [F,L] # ----------------------------------------------------------------------------------------------- # Ensure that the URL follows the name-format specification required by ProcessWire # ----------------------------------------------------------------------------------------------- RewriteCond %{REQUEST_URI} "^/~?[-_.a-zA-Z0-9/]*$" # ----------------------------------------------------------------------------------------------- # If the request is for a file or directory that physically exists on the server, # then don't give control to ProcessWire, and instead load the file # ----------------------------------------------------------------------------------------------- RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !(favicon\.ico|robots\.txt) # ----------------------------------------------------------------------------------------------- # Optional: Don't send missing image requests to ProcessWire (uncomment below to enable). # This might be helpful if you are launching a new site and lots of images have moved. # It will reduce the load on the server not to have ProcessWire trying to serve those requests. # ----------------------------------------------------------------------------------------------- # RewriteCond %{REQUEST_URI} !\.(gif|jpg|png|ico)$ [NC] # ----------------------------------------------------------------------------------------------- # Pass control to ProcessWire if all the above directives allow us to this point. # For regular VirtualHosts (most installs) # ----------------------------------------------------------------------------------------------- RewriteRule ^(.*)$ index.php?it=$1 [L,QSA] # ----------------------------------------------------------------------------------------------- # If using VirtualDocumentRoot: comment out the one above and use this one instead. # ----------------------------------------------------------------------------------------------- # RewriteRule ^(.*)$ /index.php?it=$1 [L,QSA] </IfModule> ################################################################################################# # END PROCESSWIRE HTACCESS DIRECTIVES ################################################################################################# and the following on my Apache server config: <VirtualHost *:80> ServerAdmin webmaster@localhost DocumentRoot /var/www/html/project/processwire <Directory /var/www/html/project/> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined <IfModule mod_dir.c> DirectoryIndex index.php index.pl index.cgi index.html index.xhtml index.htm </IfModule> </VirtualHost> My website opens normally, but when I try something broken like https://mywebsite.com/dfvjdbvknbk it opens a standard apache 404 page and not my custom one. My custom 404 page is inside processwire/site/templates Can anyone help me understand what is broken here? Thanks in advance!
-
@kongondo I've installed the latest version and I'm getting an issue whereby there are now 2 sets of Padloper Modules (Directories). One located at site/modules/PadLoper/ and one at site/modules/ProcessPadLoper/ So I have to specify which version of the duplicate files I want to use for each of the individual modules (please see the couple of attached screenshots for example). To view the new details tab for the Runtime Markup field I have to specify the version located at /site/modules/ProcessPadloper/FieldtypePadloperRuntimeMarkup/FieldtypePadloperRuntimeMarkup.module
-
Just a quick one ... This is two questions in one. Integration: Probably not the answer you are looking for but literally any JavaScript library can be integrated into the PW backend. There are various options here including a dedicated ProcessModule or an Inputfield (e.g. a runtime one). Update data in real time. Any JavaScript and newer libs like HTMX can easily do this. The bottom line is this: (a) An action happens on the client (b) JS listens to that action/event (c) optionally but ideally, check if the action is valid (e.g. was this field completed) (d) send the info to the backend - usually via ajax for the type of app you are building (e) the backend processes the action you have sent including validation + sanitization. If these pass, it takes an action, e.g. 'create a page' or 'update a field' (f) the server sends the response back to the client which is listening for a response from the ajax request. Traditionally/usually, the response is JSON but with HTMX, the response is HTML. (g) The client handles the response, in many cases, updating the DOM. That's it. Yes. Media Manager, for instance. You drop files and it will upload the files then create media pages off of that. Yes. ProcessWire itself to be honest. Basically $input, $sanitizer, $config->ajax and $pages are the usual tools. Not a reuse per se answer. Listening to drag and drop using JavaScript used to be a chore. With modern browsers, APIs exist to do it easily in vanilla JavaScript. If you wish to get a ready made solution searching for JavaScript drag and drop will yield some results. Personally, I'd go for htmx + vanilla JS drag and drop, or htmx + sortable combo (here's a Python example).
-
@olafgleba Edit your /site/config.php file and look for: $config->httpHost and/or $config->httpHosts. In most cases the $config->httpHost should not be present (since PW will set it automatically at runtime), but the $config->httpHosts (plural) should be present, and it should be an array of http hosts ProcessWire is allowed to auto-detect and use. It will pick one of the hosts in that array to use for the request, so long as it matches the $_SERVER[HTTP_HOST]. If it can't find one that matches the $_SERVER[HTTP_HOST] then it will simply use the first one in your httpHosts array: $config->httpHosts = [ 'www.company.com', 'dev.company.com', 'localhost:8888' ]; If it just contains one host then it'll always use that one, regardless of what's in $_SERVER[HTTP_HOSTS] … $config->httpHosts = [ 'www.company.com' ]; If you do have the non-plural $config->httpHost present (like below), then it forces use of that hostname, rather than letting PW auto-detect from your httpHosts array. Though if there's only one host in your httpHosts array (like above) then of course the effect would be the same. $config->httpHost = 'www.company.com'; My best guess is that you either have $config->httpHost or httpHosts set with '127.0.0.1', or that you have httpHost/httpHosts undefined in your /site/config.php file. To fix it you need to add your www.host.tld to a $config->httpHosts array and preferably as the first item in it. If you do see a $config->httpHost (non-plural) in your config.php them I would remove it.
-
@Matzn Your TestModuleChild.module is overriding the getModuleConfigInputfields() of the TestModule.module and replacing it. In PHP, if you want the parent method to run, then you need to either omit the method completely in your child class, or call the method parent::method() so that it will run (like what you are doing with your __construct method). What you are doing currently is replacing the method with one that has no code in it. What I think you are wanting is this in your TestModuleChild.module: public function getModuleConfigInputfields(InputfieldWrapper $inputfields) { parent::getModuleConfigInputfields($inputfields); } After doing the above, now it will inherit the code of the parent class. And after calling that parent::method() maybe you want to add another configuration setting to it, i.e. public function getModuleConfigInputfields(InputfieldWrapper $inputfields) { parent::getModuleConfigInputfields($inputfields); $f = $this->wire()->modules->get('InputfieldText'); $f->attr('name', 'test_field'); $f->label = 'Test field'; $f->val($this->test_field); $inputfields->add($f); } But if you don't want to add anything new to the getModuleConfigInputfields() then just leave the method out of your TestModuleChild.module completely, and it will inherit automatically. Also, module configuration data should be defined with runtime calls, so I recommend you remove this: public $field_1 = "parent module property 1"; and replace it with this in your __construct(): $this->set('field_1', 'parent module property 1'); I see you are using static getModuleInfo() methods in your classes. In cases where you've got one module extending another, unless the child module literally does an include() at the top of the parent module's file, then you should define your child module's info in a ModuleName.info.php file like I described in my previous message (including the 'requires' statement), and omit the getModuleInfo() static method. Otherwise, if PHP/PW happens to include() the child module before the parent module, you'll get a fatal class error. By using a separate ModuleName.info.php, PW can learn about the module without having to load the class file, and it can see from your 'requires' statement that it needs to load the parent module before your child module, ensuring no fatal errors. If you can't do this, or don't want to, then make sure your child module does an include() or require() of the parent module's file, somewhere before your "class TestModuleChild ...".
-
https://blog.gskinner.com/archives/2020/07/introducing-flokk-a-desktop-app-built-with-flutter.html https://blog.gskinner.com/archives/2020/09/flokk---how-we-built-a-desktop-app-using-flutter.html "Rive takes advantage of cutting-edge technologies such as Flutter and WebAssembly to create native desktop and web apps." https://rive.app "Bring Your Apps and Games to Life with Real-Time Animation" https://blog.rive.app/rives-web-runtime/ "Learn how Rive's web runtime works under the hood and how to embed a Rive animation in a web page."
- 35 replies
-
- 2
-
-
When you do a $pages->find($selector) operation your selector is translated by PW into an SQL query. It's a bit of a simplification (because there some exceptions for things like "count"), but essentially this means that you can only sort by values that correspond to columns in the database. So for example you can sort by "title" because that corresponds to a column in the database. But you can't use some logic at runtime to conditionally build up a custom value based on various properties of each page and then sort by that because there is no corresponding column for that custom value. So your options are... 1. If the only way to work out the sort is to iterate over all the pages in a PageArray and you then want to paginate that sorted PageArray, you can do something like this: // $results is a PageArray that you have applied some custom sorting to at runtime $total = $results->count(); $limit = 10; // Convert page number to be zero-based $page_num = $input->pageNum - 1; $start = $page_num * $limit; // Get the slice of results for the current pagination $results = $results->slice($start, $limit); $results->setStart($start)->setLimit($limit)->setTotal($total); foreach($results as $result) { // Output result } echo $results->renderPager(); But because you have to load all the results into memory in order to sort them, this strategy is not going to scale well with large numbers of results. 2. If the sorting doesn't actually depend on dynamic input you can think about using an integer field in the template to store a weighting that you can sort by in a $pages->find() selector. You would use a saveReady hook to populate this sort_weighting field according to other field values in the page. You can use the API to loop over all your book pages to set a sort_weighting value initially. The sorting in your code didn't quite make sense to me so you'll probably need to adapt this to suit, but the general idea is this: // In /site/ready.php $pages->addHookAfter('saveReady', function(HookEvent $event) { $page = $event->arguments(0); if($page->template == 'book') { $sort_weighting = 0; if(!$page->subject) $sort_weighting = -1; if(!$page->subject && !$page->author) $sort_weighting = -2; $page->sort_weighting = $sort_weighting; } }); // In your template code $results = $pages->find("template=book, sort=sort_weighting, sort=subject, sort=cleanauthor, sort=cleantitle, limit=50");
-
I followed some sample modules to start my first project. The module installs/uninstalls fine but when I click the module's page I get the following error: Fatal Error: Uncaught TypeError: Argument 1 passed to ProcessWire\ProcessController::getProcessMethodName() must be an instance of ProcessWire\Process, instance of ProcessWire\GoodNews given, called in /Users/mgartner/ProjekteWEB/processwire/wire/core/ProcessController.php on line 324 and defined in /Users/mgartner/ProjekteWEB/processwire/wire/core/ProcessController.php:260 Stack trace: #0 /Users/mgartner/ProjekteWEB/processwire/wire/core/ProcessController.php(324): ProcessWire\ProcessController->getProcessMethodName(Object(ProcessWire\GoodNews)) #1 /Users/mgartner/ProjekteWEB/processwire/wire/core/Wire.php(380): ProcessWire\ProcessController->___execute() #2 /Users/mgartner/ProjekteWEB/processwire/wire/core/WireHooks.php(723): ProcessWire\Wire->_callMethod('___execute', Array) #3 /Users/mgartner/ProjekteWEB/processwire/wire/core/Wire.php(442): ProcessWire\WireHooks->runHooks(Object(ProcessWire\ProcessController), 'execute', Array) #4 /Users/mgartner/ProjekteWEB/processwire/wire/core/admin.php(135): ProcessWire\Wire->__ca (line 260 of /Users/mgartner/ProjekteWEB/processwire/wire/core/ProcessController.php) This error message was shown because: you are logged in as a Superuser. Error has been logged. Here is the full source: <?php namespace ProcessWire; /** * GoodNews module * * An integrated group and newsletter mailing system for Processwire. * * This file is licensed under the MIT license * https://processwire.com/about/license/mit/ * * ProcessWire 3.x, Copyright 2016 by Ryan Cramer * https://processwire.com * */ class GoodNews extends WireData implements Module { const debug = false; const pageName = 'goodnews'; const minVersionPHP = '5.6.37'; /** * Required by all modules to tell ProcessWire about them * * @return array */ public static function getModuleinfo() { return array( // The module's title, typically a little more descriptive than the class name 'title' => 'GoodNews', // A brief description of what this module is 'summary' => 'An integrated group and newsletter mailing system.', // Module version number: use 1 for 0.0.1 or 100 for 1.0.0, and so on 'version' => 1, // Name of module author 'author' => 'Martin Gartner, bitego', // Optional URL to more information about the module 'href' => 'http://modules.processwire.com/goodnews', // singular=true: indicates that only one instance of the module is allowed. // This is usually what you want for modules that attach hooks. //'singular' => true, // autoload=true: indicates the module should be started with ProcessWire. // This is necessary for any modules that attach runtime hooks, otherwise those // hooks won't get attached unless some other code calls the module on it's own. // Note that autoload modules are almost always also 'singular' (seen above). //'autoload' => true, // For more options that you may specify here, see the file: /wire/core/Process.php // and the file: /wire/core/Module.php ); } public function execute() { if (version_compare(PHP_VERSION, self::minVersionPHP) >= 0) { // good } else { $this->error("Please note that your current PHP version (" . PHP_VERSION . ") is not adequate to run this module."); } $out = 'Test'; return $out; } /** * Executed on install */ public function ___install() { // Create the page the module will be assigned to $page = new Page(); $page->template = 'admin'; $page->name = self::pageName; // Installs to the admin main menu $page->parent = $this->pages->get($this->config->adminRootPageID); //->child('name=setup'); $page->process = $this; // Page title is the same as our module title $info = self::getModuleInfo(); $page->title = $info['title']; // Save the page $page->save(); // Tell the user we created this page $this->message("Created Page: {$page->path}"); } /** * Executed on uninstall */ public function ___uninstall() { // Find the page we installed, locating it by the process field (which has the module ID) // It would probably be sufficient just to locate by name, but this is just to be extra sure. $moduleID = $this->modules->getModuleID($this); $page = $this->pages->get("template=admin, process=$moduleID, name=" . self::pageName); if($page->id) { // If we found the page, let the user know and delete it $this->message("Deleting Page: {$page->path}"); $page->delete(); } } } Any hints? Thanks, Martin
-
Background I'm creating a module to integrate https://pushalert.co/ into ProcessWire. You actually don't even need a module. You could just use the "Other Websites" javascript provided by PushAlert for basic functionality, ie send a broadcast notification to all subscribers. This is essentially what all the other integrations, including WordPress, do. The WP integration installs a widget with a form enabling the admin to enter details such as title, message, etc from a blog post. It does not: collect any statistics within the CMS about the notification enable audience fine tuning to eg a particular subscriber or subscriber segment within WP. The admin needs to use the PA dashboard for that functionality PushAlert has a javascript and REST API. It's intended that this module will use both. https://pushalert.co/documentation What my module does so far: associate a subscription with a user. FE user clicks a button on the website front end to subscribe and/or agrees to the browser popup to accept notifications from this site send broadcast push alerts from a page within admin It doesn't have a 'widget' but easy enough to create a fieldsetpage with the relevant fields and add that fs page to any appropriate templates, then with a hook, send the notification. Need to be careful that once published/sent, the notification is not automatically re-sent on subsequent page edits. Looking for help/collaboration on how best: to send a notification, eg from a blog post, then track the statistics. Dilemma is that the push notification must come from the admin page. Responses go to the sending page which, as it's an admin page, is restricted and will not accept the https response. This is where the other CMS integrations stop. The only json response from PushAlert is the status, eg 'success', and the notification id. There is no opportunity at this point to capture the sending page id. handle, 'once sent on page publish', do not automatically resend on future page edits Am thinking along the lines that FS Page will have a @kongondo runtime markup field https://modules.processwire.com/modules/fieldtype-runtime-markup/ to pull the stats from PushAlert. Every time an admin visits the page, the stats will update. Once an admin checks the 'Send notification on page publish' checkbox, a hook creates new front end page that records the 'sender page', sends the notification request to PA, which then uses that newly created frontend page, as the response endpoint. Another rook re-associates the front end page with the admin page (eg blog post), to update the stats. Potential use cases: Notify individual and/or users with a particular role of an event, eg "New work opportunity" for job seekers; new blog post published; entries now open, etc... Looking for help/ideas/collaboration on this module. Please let me know if you're interested and as I do, believe this would be a great addition to ProcessWire
- 15 replies
-
- 6
-
-
- push
- notifications
-
(and 1 more)
Tagged with:
-
I have indeed – and I dig it from the perspective of rapid development. As I understand it though, it comes with a runtime that contains things that may or may not be used. Sure, the Alpine runtime is small, but the build file I have in Svelte is looking a bit smaller (so far). That aside, enjoying Svelte so far – this is the first time I'm exploring all of its features.
-
Module Module: RuntimeMarkup Fieldtype & Inputfield
MarkE replied to kongondo's topic in Modules/Plugins
Great module, but I'm having a couple of minor issues (unrelated, I think). The first issue seems intermittent and I can't work out why : In some cases, I can't get the inclusion of .js and .css to work. I've triple-checked all the naming etc. but the files just don't seem to load. My work-round (easy enough) is just to load the files in the php. The second issue may be because I am stretching the fieldtype's capability! I am using it within a PageTable field as follows. The PageTable field ("panelled_carousel") has a template "Panelled_carousel" which has fields "title", "imagePages" (a page reference field linking to a page with template "Image" and an image field "image_single") and "runtime_markup_images" (a runtime markup field with php file "RuntimeMarkup/Images.php"). The php file is (including a bit of debugging): $imagePages = $page->imagePages; bd($page, 'page with carousel'); $out = ''; wire()->log->save('debug', 'Page is ' . $page->title); foreach ($imagePages as $imagePage) { bd($imagePage, 'imagePage'); foreach ($imagePage->image_single as $image) { bd($image, 'image'); if (is_a($image, '\ProcessWire\Pageimage')) $out .= '<img src="' . $image->pia("width=200")->url . '"/>'; } } return $out; The RM field is updated when the imagePages field changes by javascript/AJAX : When editing the Page Table field, this all works well - any changes in the imagePages (add/re-order/delete etc) are immediately reflected in the RM field. However, when saving the Page Table Field and returning to the host page, the RM PHP throws an error unless I catch it with the condition - is_a($image, '\ProcessWire\Pageimage') - in the code above. The reason is that in some cases $image seems to be taking a string, integer or boolean value, even though $imagePage has class Page and the dump shows it is the right page. Trapping this error means that the images in the table are all blank after the save. However refreshing the page puts everything right again. So not a deal-breaker but a bit odd. To illustrate, here is the top page with the page table (including images): Clicking on "Blue" to edit an item we get: Then, clicking save and returning to the top page, the images do not render: The debugging shows that this is not because Images.php has not run, but because $image is of the wrong type (as described above). Refreshing the page restores the images. Any ideas? EDIT: I should add that the problem does not seem to be related to my .js script, or even RuntimeMarkup specifically as exactly the same issue happens in a Page Table with @Robin S's RuntimeOnly module with no js attached to it. So it seems to be something to do with how the runtime markup is interacting with the page table display. -
Please don't use this module any more. I think in the end it just adds more complexity (and dependencies) than benefits. See this tutorial how simple it is to create a custom runtime-only Inputfield: WHY? I've started building this module because the existing solutions by @kongondo and @kixe (https://modules.processwire.com/modules/fieldtype-runtime-markup/ and https://github.com/kixe/FieldtypeMarkup) did not exactly fit my needs. Actually this module is aimed to be a base module that can easily be extended by other modules. It takes care of the heavy lifting that has to be done when working with custom fieldtypes in ProcessWire (injecting scripts and styles, handling JS events, doing translations). See RockTabulator as an example. I'm quite sure more will follow (eg ChartJS)... WHAT? This module helps you injecting ANY php/html/js/css into any PW backend form (either on a page or in custom process modules). It also comes with a sandbox process module that helps you setup your fields and provides handy shortcuts that integrate with TracyDebugger and your IDE: WHERE ...to get it? At the moment the module is released as early alpha and available only on github: https://github.com/BernhardBaumrock/RockMarkup2 If you have any questions or ideas please let me know ? PS: This module shows how easy it is to extend this module for your very own needs. All you need to do is providing the module's info arrays and then overwrite any methods that you have to modify (eg the InputField's render() method): https://github.com/BernhardBaumrock/RockMarkupExtensionExample
- 17 replies
-
- 12
-
-
// example 1: modify page title (runtime) for a specific template in Page Edit Interface $this->addHookBefore('ProcessPageEdit::execute', function($e) { $id = wire('input')->get->id; if (!$id) return; $page = wire('pages')->get($id); if ($page->template != 'specific') return; $page->title = "I am a runtime title for pages using template 'specific'"; }); // example 2: modify fields in Profile $this->addHookBefore('ProcessProfile::execute', function($e) { // not for superuser if (wire('user')->isSuperuser()) return; // the user should check 2 checkboxes in its profile // after checking and saving the related checkbox disappears // if both are checked a markup field 'info' is shown $profileFields = $e->object->profileFields; if (wire('user')->checkbox && wire('user')->checkbox_2) $profileFields[] = 'info'; else { if (wire('user')->checkbox != 1) $profileFields[] = 'checkbox'; if (wire('user')->checkbox_2 != 1) $profileFields[] = 'checkbox_2'; } // update profile fields $e->object->profileFields = array_unique($profileFields); });
-
https://github.com/horst-n/WireMailSmtp/issues/14 "I" get them too, in php 7.4 In php 7.4 get_magic_quotes_runtime() is deprecated but still exists, so function_exists("get_magic_quotes_runtime") has no effect to stop the deprication message from appearing. https://www.php.net/manual/en/function.get-magic-quotes-runtime.php "REMOVED as of PHP 8.0.0." so function_exists("get_magic_quotes_runtime") bit works as expected in PHP 8 and up.
-
@horst could you please have a look at this issue? https://www.php.net/manual/en/function.get-magic-quotes-runtime.php Thx!
-
Module Module: RuntimeMarkup Fieldtype & Inputfield
bernhard replied to kongondo's topic in Modules/Plugins
Hey @psy I'd create a custom runtime module, it's not too hard: 1) Create the fieldtype: 2) Create the inputfield: RockMarkup is deprecated because I don't plan to use it as base module for other Fieldtypes in the future. I think it makes things more complicated and that's not worth it. Building custom fieldtypes + inputfields is easy once you know how things work. Especially runtime fields are easy because you don't need all the DB related parts. If you need any help just ask. -
ProcessWire 3.0.193 resolves 6 issues, makes improvements to the template and module editors, adds new hooks, adds improvements the $pages->find() findRaw method, and more. We covered some of these updates in last week's post, so we'll focus on what's new this week. First off we have a new advanced mode feature that lets you edit the raw configuration data for a module. This can be useful for various reasons, especially for module developers. If you have $config->advanced = true; in your /site/config.php file, you'll see a new option on your module information screen that enables you to directly edit the raw JSON configuration data for the module. There's also an option that lets you view the raw JSON module information data. Unlike the configuration data, this isn't editable. That's because it comes from the module directly (overtime you do a Modules > Refresh) or is generated at runtime, so there's little point in editing it here. In my case, I've found these new tools helpful for clearing out old and/or irrelevant configuration data during module development. In some cases, having the ability to edit this data may help to identify or fix issues that previously would have been difficult to do without using the API. If there's interest, I may move this into a dedicated (non-core) module that also lets you directly edit field and template configuration data too. But for now the feature is in the core, but just requires advanced mode before it appears. A few new hooks were added this week: Fieldgroups::fieldRemoved($fieldgroup, $field) Called after a field has been removed from a fieldgroup/template. Fieldgroups::fieldAdded($fieldgroup, $field) Called after a new field has been added to a fieldgroup/template. Fieldgroups::renameReady($template, $oldName, $newName) Called before a fieldgroup is about to be renamed. Fieldgroups::renamed($template, $oldName, $newName) Called after a fieldgroup has been renamed. Templates::renameReady($template, $oldName, $newName) Called before a template is about to be renamed. Templates::renamed($template, $oldName, $newName) Called after a template has been renamed. Fields::renameReady($field, $oldName, $newName) Called before a field is about to be renamed. Fields::renamed($field, $oldName, $newName) Called after a field has been renamed. These accompany the existing addReady(), added(), deleteReady(), deleted(), cloneReady(), cloned(), saveReady() and saved() hooks available for fields, templates and fieldgroups. Last week a couple people asked about versioning and migration of stuff in PW (like fields, templates, modules, etc.) and if there were any plans to provide additional tools for that. For the projects I work on at least, this part of the development process consumes so little time that it doesn't warrant developing more stuff for it. But I understand others might find it useful, so for those that would, I'd rather keep the core lean and instead leave that to tools/modules built by experts like Bernhard and others around here. I think it's important that whoever develops and maintains such features also be the same one(s) that would use them. But if any kind of core updates would be helpful to developers looking to implement more features here, I'm on board. Whether that means adding more hooks to specific events (see above as examples), maintaining field/template/module data in files in addition to the current DB tables, or anything else that helps such modules, this is all possible and likely simple for us to support in the core. So just let me know what I can do to help. While not full-featured migration tools, we do have useful field, template and page export/import tools in the core already, and those will of course continue to be maintained and improved, and may be expanded to include modules too. Thanks for reading and have a great weekend!
- 26 replies
-
- 16
-
-
We're in the last steps of phasing out the project I was using it on. Most parts had been replaced years ago since we moved away from processwire with that project. The module's approach to access is nice, but iirc there were some bugs in the master implementation and we actually would've needed a bit more flexibility out of it (still needed code to create those dynamic roles). I'd still suggest it over expensive runtime access checks if it aligns to a projects access setup. We've been using it because our access was not only scoped by roles, but also by customers. So a manager would only have access to manager pages, which belonged to a customer assigned to that manager. Customers weren't static, but also defined by pages within the system. Things also weren't segmented into individual page trees, though iirc the modules for segmenting by page tree didn't exist at that time as well.
-
Markup regions - how to include files in _main.php
rafaoski replied to JayGee's topic in API & Templates
I don't know if I understood correctly, but it looks like you can also use $files->include() or $files->render() methods in your _main.php file. A simple example from the Regular Uikit 3 profile, which we will include the _header.php inside file _main.php with some variables: <?php namespace ProcessWire; // _main.php template file, called after a page’s template file $home = pages()->get('/'); // homepage $siteTitle = 'Regular'; $siteTagline = $home->summary; // as a convenience, set location of our 3rd party resources (Uikit and jQuery)... urls()->set('uikit', 'wire/modules/AdminTheme/AdminThemeUikit/uikit/dist/'); urls()->set('jquery', 'wire/modules/Jquery/JqueryCore/JqueryCore.js'); // ...or if you prefer to use CDN hosted resources, use these instead: // urls()->set('uikit', 'https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.0-beta.40/'); // urls()->set('jquery', 'https://code.jquery.com/jquery-2.2.4.min.js'); ?> <!-- HEADER --> <?php $files->include('_header', ['home' => $home, 'siteTitle' => $siteTitle, 'siteTagline' => $siteTagline]); // echo $files->render('_header', ['home' => $home, 'siteTitle' => $siteTitle, 'siteTagline' => $siteTagline]); ?> _header.php: <?php namespace ProcessWire; // _header.php file ?> <!DOCTYPE html> <html lang='en'> <head id='html-head'> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title id='html-title'><?=page()->title?></title> <meta name="description" content="<?=page()->summary?>"> <link rel="stylesheet" href="<?=urls()->uikit?>css/uikit.min.css" /> <link rel="stylesheet" href="<?=urls()->templates?>styles/main.css"> <script src="<?=urls()->jquery?>"></script> <script src="<?=urls()->uikit?>js/uikit.min.js"></script> <script src="<?=urls()->uikit?>js/uikit-icons.min.js"></script> </head> <body id='html-body'> <!-- MASTHEAD --> <header class='uk-background-muted'> <div id='masthead' class="uk-container"> <h2 id='masthead-logo' class='uk-text-center uk-margin-medium-top uk-margin-small-bottom'> <a href='<?=urls()->root?>'> <img src='<?=urls()->templates?>styles/images/coffee4.svg' alt='coffee'><br /> </a> <?=$siteTitle?> </h2> <p id='masthead-tagline' class='uk-text-center uk-text-small uk-text-muted uk-margin-remove'> <?=$siteTagline?> </p> <nav id='masthead-navbar' class="uk-navbar-container" uk-navbar> <div class="uk-navbar-center uk-visible@m"> <?=ukNavbarNav($home->and($home->children), [ 'dropdown' => [ 'basic-page', 'categories' ] ])?> </div> </nav> </div> </header> It is also important to include <?php namespace ProcessWire; ?> in each of template files. Sometimes it also helps to enable $config->useFunctionsAPI in the config.php file ( Allow most API variables to be accessed as functions? ), this will be more useful in your custom functions, where for example you can call page()->title instead of $page->title, which will not work inside a your custom function if you do not enter any arguments, as in the example below: <?php function showTitle() { echo '<h1>' . page()->title . '</h1>'; // This work // echo $page->title; // This not work } // Show Title showTitle(); ?> The setting() helper function is a good addition to the _init.php file, to which I usually attach the most important page options, which are also available in custom functions without entering arguments such as the init.php file: <?php namespace ProcessWire; /** * * This _init.php file is called automatically by ProcessWire before every page render * * Get or set a runtime site setting * @link https://processwire.com/api/ref/functions/setting/ * */ /** @var ProcessWire $wire */ // set or replace multiple settings setting([ 'siteTitle' => 'ProcessWire CMS / CMF', 'siteDescription' => 'ProcessWire is like a power tool for your website, able to deliver any output, at any scale, to any number of people. ', ]); // Your custom functions that are better placed in the _func.php or _uikit.php file (this is just an example) function siteBranding() { echo "<h1>" . setting('siteTitle') . "</h1>"; echo "<h2>" . setting('siteDescription') . "</h2>"; } include_once('./_uikit.php'); Now you can display the function wherever you want: <?php siteBranding() ?> For example, in this Site Profile I have put site options or translations inside file _init.php: <?php namespace ProcessWire; /** * * This _init.php file is called automatically by ProcessWire before every page render * * Get or set a runtime site setting * @link https://processwire.com/api/ref/functions/setting/ * */ // as a convenience, set location of our 3rd party resources (jQuery)... urls()->set('jquery', 'https://code.jquery.com/jquery-3.4.1.min.js'); $home = pages('/'); $blog = pages()->get("template=blog"); $options = pages()->get('/options/'); // Basic Settings setting([ // Custom html classes 'htmlClasses' => WireArray([ 'template-' . page()->template->name, 'page-' . page()->id, ]), // Basic 'home' => $home, 'privacyPolicy' => pages()->get("template=privacy"), 'options' => $options, 'siteName' => $options->text, 'logo' => $options->logo, 'favicon' => $options->favicon, 'socialProfiles' =>$options->social_profiles, 'metaTitle' => page('meta_title|title'), 'metaDescription' => page()->meta_description, 'noindex' => false, 'poweredUrl' => 'https://processwire.com', // Home Sections 'hero' => $home, 'about' => pages()->get("template=about"), 'projects'=> pages()->get("template=projects"), 'recent' => $blog->child(), // Path to template parts 'homeParts' => 'parts/home', 'blogParts' => 'parts/blog', // Blog 'blog' => $blog, 'disableComments' => $options->more_options->get("name=disable-comments"), // Contact Page 'saveMessages' => $options->more_options->get("name=save-messages"), // Images 'img' => page()->images && page()->images->count() ? page()->images : '', // Main 'mainTitle' => page('title'), 'mainImage' => true, // Set basic background image for all pages // Bottom Panel 'bottomPanel' => $options->bottom_panel, // Basic Translations 'lang' => __('en'), 'edit' => __('Edit'), 'next' => __('Next'), 'previous' => __('Previous'), 'search' => __('Search'), 'search-site' => __('Search the entire site'), 'found-matches' => __('Found %d page(s)'), 'no-results' => __('Sorry, no results were found.'), 'maintenance-mode' => __('Maintenance Mode'), 'site-disabled' => __('Our site is currently disabled.'), 'to-top' => __('To top'), 'we-sociable' => __('We are sociable'), 'powered' => __('Probably supported by ProcessWire CMS'), // Contact Page Translate 'message-error' => __('Some errors, please update your form'), 'message-success' => __('Success, your message has been sent'), 'txt-from' => __('From'), 'form-legend' => __('Contact Us'), 'form-name' => __('Name'), 'form-email' => __('Email'), 'form-privacy' => __('I agree with the %s terms.'), 'form-message' => __('Message'), 'form-spam' => __('To help prevent automated spam, please answer this question'), 'fs-placeholder' => __('* Using only numbers, what is 10 plus 15?'), 'fs-error' => __('Fill out the spam prevention box correctly'), 'form-submit' => __('Submit'), // Blog Translate 'in-blog' => __('In the blog'), 'posted-in' => __('Posted in'), 'all-posts' => __('All posts'), 'recent-posts' => __('Recent posts'), 'read-more' => __('Read More'), 'written-on' => __('Written on'), 'byline-text' => __('Posted by %1$s on %2$s'), 'also-like' => __('You might also like:'), 'author' => __('Author'), 'authors' => __('Authors'), // is also url segments ( blog/authors/author-mame ) 'category' => __('Category'), 'tag' => __('Tag'), 'author-checkbox' => __('You probably need to check the author checkbox in your user profile'), 'rss' => __('RSS'), 'recent-entries' => __('Recent entries'), // Comments Form Translate 'previous-comments' => __('Previous Comments'), 'next-comments' => __('Next Comments'), 'post-comment' => __('Post a comment'), 'comment' => __('Comment'), 'comments' => __('Comments'), 'no-comments' => __('No Comments'), 'comments-closed' => __('Comments are closed'), 'comment-header' => __('Posted by {cite} on {created}'), 'success-message' => __('Thank you, your comment has been posted.'), 'pending-message' => __('Your comment has been submitted and will appear once approved by the moderator.'), 'error-message' => __('Your comment was not saved due to one or more errors.') . ' ' . __('Please check that you have completed all fields before submitting again.'), 'comment-cite' => __('Your Name'), 'comment-email' => __('Your E-Mail'), 'comment-website' => __('Website'), 'comment-stars' => __('Your Rating'), 'submit' => __('Submit'), 'stars-required' => __('Please select a star rating'), 'reply' => __('Reply') ]); include_once('./_func.php'); -
Hi, this is not so clear to me in part "pass variable to hidden input"? If need to save image path value to hidden input, than maybe it's better to go with hook in backend (after page save or other). Another option coud be to save image path value to hidden input in runtime (???), if that is the case, than try something like this: <?php foreach($page->dev_repeater as $repeater) { $image_field = $repeater->image_field; foreach($repeater->dev_child_repeater as $url) { // some other stuff, link etc... // check and save hidden_field value inside runtime (???) if($url->hidden_field == ""){ $url->of(false); // $url->save(); uncomment if save on second reload $url->hidden_field = $image_field->url; // <= this? $url->save('hidden_field'); } else { // hidden_field has some value echo $url->hidden_field; } } } ?> But also if there is any option to avoid nested repeater that would be better, and also try to think about using hooks in backend to avoid save in runtime. To me it's ok when need to save "page view counters" or some other events triggered by front-end users/vistors. Sorry if I don't understand your question well. Regards.
-
Fieldtype that just displays HTML, nothing else
MarkE replied to DrQuincy's topic in Getting Started
https://processwire.com/modules/inputfield-runtime-only/ ? -
Hi @Abe Cube I you are talking about ProcessPageEdit screen, that you can add runtime fields via hook. You can find some info there
-
Determining the context a page is being created in [solved]
FireWire replied to FireWire's topic in API & Templates
I think your solution works for a bigger context of where a lot of data on a page would be dependent on the context it was created in. I just needed to make sure that the hook for one field can determine at runtime whether the field was filled by a user in the PW admin or the Page API. Your solution from the PW admin side did make me think bigger picture which is also a possible solution for my application. This field is being used on pages that can be created/edited in the ProcessWire admin, but they can also be created/modified by a website REST API that other systems- in our case Salesforce- can use to create/modify data on the site. Calls to this website API are authenticated using ProcessWire users which have an API key assigned and a role of web-api-access. So rather than focus on verifying where the the page was created at the field level, I could check that the user creating the field is an API user at the page level. I got a little more into the weeds with that description, but your idea helped me think of a different approach.