Leaderboard
Popular Content
Showing content with the highest reputation on 03/27/2021 in all areas
-
This week I've been working on something a little different for the core. Specifically, ProcessWire's database class (WireDatabasePDO) has been rewritten to support separate read-only and read-write database connections. Jan, who administers the processwire.com server, asked if I could implement it. I looked into it and thought it had significant benefits for ProcessWire users, so it worked out that now was a good time to implement it. The rewritten database class is actually complete and now running on a live test installation, but I have not yet committed it to the core dev branch because I want to fully document it first. This will happen next week in a blog post. By then I'll have processwire.com using it too. But I can already say that it's a cool thing watching the graphs in AWS show the difference it makes when we start hitting the site with crawlers. You might be wondering what the benefits are in having separate read-only and read-write database connections. I'll get into some of the details next week. But essentially, read-only database connections can scale in a way (and at much lower cost) than read-write connections can. And when using a service like Amazon Aurora, they can scale on-the-fly automatically according to traffic and demand for resources. Not only does it open up the ability for a ProcessWire-powered site to scale much further than before, but it has potential to reduce the costs of doing so by perhaps 50% or more. If you are interested in reading more, we are currently testing the features using Amazon Aurora and RDS Read Replicas (see also Replication with Aurora). However, the ProcessWire core support for this feature is not bound to anything AWS specific and will work with any platform supporting a similar ability. Thanks for reading, I'll have more on this next week, and also have it ready to use should you want to try it out yourself.7 points
-
I've realized that I've been jumping back and forth between the PW API docs and the source code for site modules far too much. The idea to hold all necessary documentation locally in one place has occurred to me before, but getting PHPDocumentor et al set up and running reliably (and producing readable output) as always been too much of a hassle. Today I was asked how I find the right hooks and their arguments, and that inspired me to finally get my backside down on the chair and whip something up, namely the Module Api Doc Viewer ProcessModuleApiDoc It lets you browse the inline documentation and public (optionally also protected) class/method/property information for all modules, core classes and template files in the ProcessWire instance. The documentation is generated on the fly, so you don't have to remember to update your docs whenever you update a module. The module is quite fresh, so expect some bugs there. Behind the scenes it uses PHP-Parser together with a custom class that extracts the information I needed, and the core TextformatterMarkdownExtra module for rendering the description part in the phpdoc style comments. This is not a replacement / competitor to the API Viewer included in the commercial ProDevTools package. There is quite some information included in the inline documentation that my module can't (and won't) parse, but which makes up parts of the official ProcessWire API docs. This, instead, is a kind of Swiss army knife to view PHPDoc style information and get a quick class or function reference. If you feel daring and want to give it a spin, or if you just want to read a bit more, visit the module's GitHub repository. This is the overview page under "Setup" -> "Module API Docs": And this is what the documentation for an individual class looks like: The core module documentation can of course be found online, but it didn't make sense not to include them. Let me know what you think!6 points
-
@MrSnoozles @teppo This is not a limiting factor in scalability at least. First off, at least here, the file-based assets are delivered by Cloudfront CDN, so they aren't part of the website traffic in the first place (other than to feed the CDN). If you wanted scalability then you'd likely want a CDN serving your assets whether using S3 or not. But a CDN isn't a necessary part of the equation in our setup either. File systems can be replicated just like databases. That's how this site runs on a load balancer on any number of nodes. Requests that upload files are routed to node A (primary), but all other requests can hit any node that the load balancer decides to route it to. The other nodes are exact copies of the node A file system that update in real time. This is very similar to what's happening with the DB reader (read-only) and writer (read-write) connection I posted about above, where the writer would be node A and there can be any number of readers. Something like S3 doesn't enhance the scalability of any of this. Implementing S3 as a storage option for PW is still part of the plan here, but more for the convenience and usefulness than scalability. You can already use S3 as a storage option in PW if you use one of the methods of mapping directories in your file system to it. But I'm looking to support for it in PW more natively than that. It is admittedly more complex than the DB stuff mentioned above. For instance, we use PHP's PDO class that all DB requests go through, so intercepting and routing them is relatively simple. Whereas in PHP, there is no PDO-type class that the file system API is built around, and instead it is dozens of different procedural functions (which is just fine, until you need to change their behavior). In addition, calls to S3 are more expensive than a file system access, so doing something as simple as getting an image dimensions is no longer a matter of a simple php getimagesize() call. Instead, it's more like making an FTP connection somewhere, FTP'ing the file to your computer, getting the image dimensions, storing them somewhere else, then deleting the image. So meta data like image dimensions needs to be stored somewhere else. PW actually implemented this ability last year (meta data and stored image dimensions). So we've already been making small steps towards S3-type storage, but because the big picture is still pretty broad in scope to implement, it's more of a long term plan. Though maybe one of my clients will tell me they need it next week, in which case it'll become a short term plan. ?6 points
-
4 points
-
With help from Elabx, I'm now able to see it again on FF. The HTTP was being redirected to HTTPS so it was failing to load. Problem solved.4 points
-
Hello @creativeguy, First, my condolences to you and his family. I applaud you for carrying on with the sites you and he built together. Second, don't worry about the adult theme. I have a number of client sites that are adult only. (Also nothing dark :D) Lastly, since you are versed in PHP, why don't we see if we can get you up and running. This forum is full of knowledgeable people that are more than willing to help get you set up. Let's start at the beginning. When you say that you cannot make a local copy work. Did you "copy" all of the files from document root to your localhost? What error message(s) are you getting when you attempt to access localhost? Do the messages indicate a problem connecting to the database? Do you stay in an endless loop trying to login? Also, an FYI, The config.php will be different on localhost than on the server, and possibly the .htaccess file as well. Give us some more information to go on so we know where to look. Best regards,4 points
-
Okay, so, this is the pickle I'm in: My friend, business partner and development teacher - also a member of this community - passed away last year (not of COVID). I'm not sure what his PW handle was but his name was Anthony Taylor. I know a lot now about PHP, HTML and CSS because of him, and for that reason, I feel like I owe it to him to learn and maintain the sites he's built with me. My dilemma is that the site exists and is online, doing it's thing. But, I can't make a local copy work. I've compared the config.php to other sites I have in my local, but this one is more robust due to the nature of the site and it's features. I can't diagnose why it won't fire on localhost. And to make matters more difficult, he was the only person I knew and know with PW experience. No one here knows me or has any reason to help me. 2020 took a hit out of my bank account as well, so I can't even hire someone. What I'm asking I guess, is anyone out there willing to spend a little time looking at the code to see if there's something obvious to a knowledgeable person, or if it needs further effort. I can pay for time, but it might take a few installments. Anyway, I'll also mention a suitability warning: the site is adult-themed. Not illegal or something dark, it's a legit site with affiliations and a fanbase. I'd just want someone to know that before even responding. Let me know if there's anyone willing to give me a hand getting past this pot-hole.3 points
-
Also interested in this. My impression is that offloading assets to Amazon S3 / Google Cloud Storage etc. is a relatively common need, and there's currently no bulletproof solution. Some third party modules have attempted to, but I'm not sure if any of them really solve all the related needs (image management etc.) — and while remote filesystems such as EFS are easier to work with, they also come with certain downsides (such as a higher price point). I seem to recall that Ryan mentioned something about this a while ago too ?3 points
-
This is a great feature for larger sites. Really excited about this. Speaking of scaling: I would imagine a limiting factor right now would be, that the uploaded assets are bound to the local drive. Is that a problem for your setup / would proccesswire.com benefit if it was possible to store files on S3? And is there a post somewhere explaining your setup on AWS?3 points
-
@monollonom I knew there was a reported PDO issue pending, but didn't remember the details so was going to be looking for it this coming week to make sure it was included (along with any others), thanks for pointing me to it.2 points
-
I registered for check it, but confirmation mail didn't come. I wrote a Fieldtype Module like this. I am using this private module for managing hotel rooms availabilities and room prices etc. I made 2 video for you, you can check the usage. I used https://flatpickr.js.org/ Backend Ekran Kaydı 2021-03-27 01.52.04.mov Frontend Ekran Kaydı 2021-03-27 01.58.10.mov2 points
-
A Fieldtype for dynamic options that are generated at runtime via a hook. Configuration Inputfield type You can choose from a range of inputfield types on the Details tab of a Dynamic Options field. Your field will return a string or an array depending on if the selected input field type is for "single item selection" or "multiple item selection". Maximum number of items You can define a maximum number of items the field is allowed to contain. The core inputfields supported by this module will become disabled once the limit is reached. This option is only applicable if you have selected an inputfield type that is for multiple item selection. Format as Pagefile/Pageimage object(s) If the field will store paths/URLs to Pagefiles/Pageimages then you can enable this option to have the formatted value be a Pagefile/Pageimage object for "single" fields or an array of Pagefile/Pageimage objects for "multiple" fields. There is a related Select Images inputfield module that allows you to visually select image thumbnails. Defining selectable options Selectable options for a Dynamic Options field should be set in a FieldtypeDynamicOptions::getSelectableOptions hook in /site/ready.php. The hook should return an array of options as 'value' => 'label'. An example hook is shown on the Details tab of a Dynamic Options field: $wire->addHookAfter('FieldtypeDynamicOptions::getSelectableOptions', function(HookEvent $event) { // The page being edited $page = $event->arguments(0); // The Dynamic Options field $field = $event->arguments(1); if($field->name === 'your_field_name') { $event->return = [ 'red' => 'Red', 'green' => 'Green', 'blue' => 'Blue', ]; } }); Formatted value If a Dynamic Options field uses a "single" input type then its formatted value is a string, and if it uses a "multiple" input type then its formatted value is an array. The unformatted value of a Dynamic Options field is always an array. Also see the Configuration section above for description of an option to have the formatted value be Pagefile/Pageimage object(s). Examples of possible uses $wire->addHookAfter('FieldtypeDynamicOptions::getSelectableOptions', function(HookEvent $event) { // The page being edited $page = $event->arguments(0); // The Dynamic Options field $field = $event->arguments(1); // Select from the "files" field on the page if($field->name === 'select_files') { $options = []; foreach($page->files as $file) { // Value is basename, label is description if one exists $options[$file->basename] = $file->get('description|basename'); } $event->return = $options; } // Select from files in a folder if($field->name === 'select_folder_files') { $options = []; $path = $event->wire()->config->paths->root . 'my-folder/'; $files = $event->wire()->files->find($path); foreach($files as $file) { // Value is full path, label is basename $options[$file] = str_replace($path, '', $file); } $event->return = $options; } // Select from non-system templates if($field->name === 'select_template') { $options = []; foreach($event->wire()->templates as $template) { if($template->flags & Template::flagSystem) continue; $options[$template->id] = $template->name; } $event->return = $options; } // Select from non-system fields if($field->name === 'select_field') { $options = []; foreach($event->wire()->fields as $field) { if($field->flags & Field::flagSystem) continue; $options[$field->id] = $field->name; } $event->return = $options; } // Select from FormBuilder forms if($field->name === 'select_formbuilder_form') { $form_names = $event->wire()->forms->getFormNames(); // Use form names as both keys and values $event->return = array_combine($form_names, $form_names); } }); https://github.com/Toutouwai/FieldtypeDynamicOptions https://processwire.com/modules/fieldtype-dynamic-options/1 point
-
Announcing the current status, planned release, roadmap and preview of Padloper 2. Status Feature freeze. Full multilingual support. Only PHP 7.2+ supported. Support for ProcessWire 3.0 only. Backend support for modern browsers only (that support JavaScript ES6 modules). Current Work Finish work on admin/backend. Work on installer and uninstaller (including configurable availability of some features). Work on UI/UX improvements. Start work on documentation with special focus on technical documentation. Continue work on Padloper API and data/model component. Roadmap Please note that these ARE NOT hard and fast targets. The roadmap may have to be adjusted to accommodate technical and non-technical constraints. Q1 2021 Inbuilt support for (latest) PayPal (full rewrite, no external modules required). Additional work on Padloper API. Invite a limited number of early alpha testers (fully-priced product). Soft and closed release of Padloper 2. Q2 2021 Start work on relaunch of Padloper website. Inbuilt support for Stripe (no external modules required). Future Plans Support for more Payment Gateways. Support for order, customers, etc imports and exports. Support for AdminThemeReno and AdminThemeDefault. Separate fully-featured frontend shop module. Consider support for multiple currencies. FAQ 1. Have you abandoned this project? No. 2. When will Padloper 2 be released? First early alpha release is scheduled for Q1 2021. This target may change depending on circumstances! Access will be by invite only for this first release. 3. What is the pricing model of Padloper 2? Three licences: Single Site, Developer and Agency licences (12 months’ updates and VIP support). 4. How much will Padloper 2 Cost? No price has been set yet. It will cost more than Padloper 1. 5. Can we upgrade from Padloper 1? No. 6. Will existing users of Padloper 1 get a discount for Padloper 2? No, this will not be possible. Apologies for the earlier announcement. It was unrealistic and unworkable. 7. Can we pay for Padloper 2 in advance? No. 8. Does Padloper 2 render markup/templates in the frontend? No. Access to all data you need to build your shop’s frontend is via the Padloper API. 9. Can we keep sending you ‘Are we there yet’ messages? No, please. Preview Here is a video preview of the current state of the backend/admin of Padloper 2. Please note the following: This is early alpha. There are bugs! It even includes WIP/notes!! FOUC, misaligned things, etc. The video shows the near-raw implementation of Vuetify UI. The UI/UX improvements work is yet to start. What you see here is the development version. Some of the incomplete features may not be available in the early releases. Most of the features you see will be optional to install.1 point
-
It took me a while to find this; I thought I’d link to it in case others wanted to see it:1 point
-
Just a missing dot. $this->files->copy(__DIR__ . '/templates/', $this->config->paths->templates);1 point
-
1 point
-
I already showed an example here https://processwire.com/talk/topic/21212-rockmigrations-easy-migrations-from-devstaging-to-live-server/?do=findComment&comment=212496 and here https://processwire.com/talk/topic/25342-custom-classes-for-page-objects-the-discussion/?do=findComment&comment=212563 of course you can use $tpl = "template=yourtemplate" instead of using the class constant.1 point
-
Please see my post here That's correct behaviour. You are attaching the hook in your custom page class, but the hook you are attaching belongs to "Pages" and not to the custom page class. If you attach a Pages::saveReady hook, it will always fire on Pages::saveReady having the saved page as arguments(0) and therefore you need to check if that page is your custom pageclass or not. BTW I'd recommend doing this instead of $this != $p $page = $event->arguments(0); if(!$page instanceof self) return; I've had problems using $page != $this when some properties of my page have changed and therefore the check returned false even though it was an instance of my custom pageclass. "instanceof" should always work as expected. You could also just check for $page->template if you prefer...1 point
-
In Page.php we have the hookable loaded method: /** * For hooks to listen to, triggered when page is loaded and ready * * #pw-hooker * */ public function ___loaded() { } It is called on these spots in PW: So this means that loaded() is triggerd on a page find operation: I'm not 100% sure if that means that it is called on every page find or if PW's internal cache somehow plays a role, but as long as the page is not loaded, the loaded hook will not trigger. If you look at the docs of modules you see that init() is called immediately when the module is loaded and ready() is called when the api is ready. This can make an important difference sometimes where hooks work in init() but not in ready() and vice versa. Page objects don't have these methods though. These are all the hookable methods of the Page baseclass: Additionally you have hookable methods in PagePermissions.module: And several others ? But no init() and ready(). Because init() and ready() are a concept of PW modules: My point is that loaded() of a page might only be triggered in very special cases. Imagine a module that loads a page only on uninstall() of the module. Then the loaded() event of your pageClass would happen very late in the request. But if you use custom page classes in an object oriented way then they become much more like a PW module and then I think it makes sense to stick to the PW module naming convention and that means that init() is triggered on module/pageclass init - just like you had the code in init.php. That IMHO does also mean, that this code does get executed on EVERY request. It does NOT mean, that the code is executed only ONCE - that's a matter of the "singular" setting of a module. See examples below. Code in ready() on the other hand is just like code in ready.php - it fires once, but later in the process, when the API is ready and all other init() methods of all modules and pageclasses have been triggered. Try this /site/modules/Test.module.php <?php namespace ProcessWire; class Test extends WireData implements Module { public static function getModuleInfo() { return [ 'title' => 'Test', 'version' => '0.0.1', 'summary' => 'Your module description', 'autoload' => false, 'singular' => false, 'icon' => 'smile-o', 'requires' => [], 'installs' => [], ]; } public function init() { bd('test init'); } public function ready() { bd('test ready'); } } Install the module and then call it from the tracy console: It only fires init() but not ready() - because when loading the module PW's ready event has already been triggered. Now make that module autoload, do a modules refresh and fire the console code again: You see the difference? ? Now just for fun we make the module "singular": If I happen to need something to execute on every load of the pageClass I use the class constructor: This means that my custom pageclass always has the correct template and does always live under the correct parent in the pagetree. As you can see I define all my fields as class constants. This makes the code so much more readable and also makes typos nearly impossible. It might feel like overhead, but actually it makes me a lot more efficient as well: So I'm actually using most if not all of my page classes as something like a singular autoload module. Overhead? Maybe a little. Problem? I think/hope no ? Hope that helps. Suggestions for improving this further always welcome ?1 point
-
@tcnet However, you block him from being able to publish it there in case he changes his mind. And even if he never wants to do that, it is confusing for the PW community that there exists two modules with different code bases and authors. Which module I am referring to now when I say: I like "ProcessFileManager"! Yours or his?1 point
-
1 point
-
Module for hiding pages for non-superusers. Download HidePages Requirements ProcessWire 3.x Changelog 1.0.1 (31 March 2018) Module renamed to prevent confusion 1.0.0 (30 March 2018) Initial release1 point
-
Its a private module, not public. You can take FieldtypeEvents as reference for you.1 point
-
You can create your templates inside your modules folder, like "MyModule/templates/" on module installation you can copy these templates to "site/templates/" folder.1 point
-
Nice module, i added this feature to Mystique module next version. You can set a fallback function as a config. Here an example config. Also next version will support most of ProcessWire selectors. You can check or test it from next branch.1 point
-
No, the values are not imported. It only connects the Fields of the chosen Template to the current Template as well. A Field can be used by multiple Templates. For example you might have a website that showcases a lot of products and also has a blog. For this you could make a Template “product” with Fields for price, dimensions and so on, as well as of course a Field called “title” and a textarea Field called “body” for the product name and a description. Now in your “blog” Template you could use “title” and “body” as well. You can even change some Field settings depending on the Template.1 point
-
I'm all in on pageClasses and it has totally changed the way I'm building apps with processwire ? I'm even rewriting old projects step by step to make my code better readable and maintainable. The great thing is that this does not break any existing code - you can move hooks step by step into the new pageClasses as dedicated methods of that pagetype. I have showcased my way of doing what you are asking for in 2 posts starting here: https://processwire.com/talk/topic/21212-rockmigrations-easy-migrations-from-devstaging-to-live-server/?do=findComment&comment=212491 I'd recommend triggering a method called "ready" only on the PW "ready" event, not on "loaded" - that's something different and if you create a method called "ready" that is actually triggered on "loaded" you'll likely produce code that might at some day produce hard to find bugs... Same goes for "init". I'd be interested what Ryan says to this topic. The reason why ready() and init() of custom page classes are not triggered is obviously because custom page classes are not autoload modules. They are requested on demand and you can therefore not tell when or if they get loaded. I guess that's to minimize the footprint of every request as much as possible. In my modules I simply use RockMigrations class loader to load all my custom pageClasses: https://github.com/BernhardBaumrock/RockMigrations/blob/2d85e460ce5aa394480906ad5b41cd1a0e86d0fe/RockMigrations.module.php#L1991-L2003 That might produce a little overhead, but I don't think that this get's noticable any time soon so the benefits outweigh by far.1 point
-
Thanks to you both. I am flat out with work at the moment so will reply as soon as I can. I am not ignoring you! ?1 point
-
Hi folks, Just stumbled upon this gem and completed the first two levels ? Looks entertaining indeed (at least for coders, of course...) https://www.i-programmer.info/news/90-tools/14431-oh-my-git-the-game.html Quote: "All in all, Oh My Git! is an intuitive game that really teaches you Git. ...[for those] who has ever struggled with Git." https://blinry.itch.io/oh-my-git Happy gitting ?1 point
-
Great work @kongondo. This looks fantastically feature-filled. You've obviously made a massive investment in this module, especially from a behind the scenes technical point of view. It is a shame in one sense it isn't built out if processwire pages, but it's obviously more powerful or efficient to have escaped the limitations of that setup. My only concern personally is the UI. I do prefer it over the standard UIkit setup of Processwire but I think myself and my clients would prefer they were closer visually to make it more of a seamless experience. I like the siderbar though, I can't think of a PW paradigm you could have used for that. Could you explain the difference between order notes and order comments though? Great works, thumbs up. Tell me where to send the money.1 point