Leaderboard
Popular Content
Showing content with the highest reputation on 04/17/2020 in all areas
-
Here’s a brief update on what’s new in the core since last week. Next week I’m going to compile a more complete overview of everything that’s in 3.0.154 (and more) and put it in a blog post. I wanted to do that today, but my kids have needed a lot of help with various things today (and this whole week actually) with all of this online school stuff and I’ve run out of time. We're a few weeks in and school is cancelled for the rest of the year due to the coronavirus (likely the same around the world). I'm still learning how to adapt to kids around all day and needing attention, but overall it's nice to have the family around more even if it is sometimes hard to get work done. So I’ll keep this sort of brief, and get into more details next week. Several updates were made to the core/LanguageFunctions.php (language functions) file, with biggest being the option to programmatically replace translation text (whether multi-language support is installed or not), useful for very easily updating core/module output to say exactly what you want, and without needing to install multi-language modules. No longer do you need to use various hooks to change text in one module or another. Also moved the __('text') configuration options to dedicated functions which makes it more clear to use, as well as much better for documentation purposes: wireLangEntityEncode(), wireLangTranslations(), wireLangReplacements(). You'll see these new functions in our docs by next week. More details and examples of these in action in next week’s blog post. The CKEditor version has been upgraded from 4.12.1 to 4.14.0. To see what’s changed, see the release notes for CKEditor 4.13.0, 4.13.1 and 4.14.0 here. There’s actually quite a lot here in terms of additions and fixes. Note especially the two security related fixes in 4.14.0 (though I think only the first may be applicable to us). While it looks like a rather unlikely combination of factors needs to come together, and with just the right person, it’s good to be aware of nevertheless. Of note is that these particular cases are entirely client side, before PW ever gets to see or filter the content, so this is something that only a CKEditor upgrade can fix. Updated the core Debug class to use PHP 7.3’s recommended hrtime (high resolution time) for debug timers, rather than microtome. This is only available in PHP 7.3 and newer. As far as I can tell it produces identical results to microtome (as far is our timers go) but the PHP documentation page indicates hrtime is what we should now be using, so that’s what we’re going with. I also did a little refactoring and minor improvements in the Debug class as well. Updated ProcessWire’s Inputfield rendering system so that you can customize markup by matching a field by name, and without hooks. This essentially takes part the Inputfield customization system developed for LoginRegisterPro and brings it into the core. This opens up a lot more customizability for those that want it. Various resolutions of GitHub issue reports, with more on the way. The above are just updates from the last week, but there’s plenty more in 3.0.154 as well. See ProcessWire Weekly #309 for details on Image and file field updates, new $database->columnExists() method and new Selectors::getOperators() method, and more. There are also the new expanded file and image properties, as discussed in #308 and the last blog post. Thanks for reading and I hope you all have a great weekend!12 points
-
Indeed, that’s because the the message is set before the admin controller actually runs and saves the the change. Basically, every page in the admin backend executes a specific “Process”. You can hook into the base Process class to add your message only after a process has been executed: $this->addHookAfter('Process::execute', function($event) { if ($this->wire('user')->isLoggedin() && $this->wire('config')->myCrazySetting) $this->message("Hope you know what you’re doing with that setting!"); }); This can be put in the same file, above the controller line.4 points
-
Edit the page 'admin' and give it a new 'name' (in the page's Settings tab). Note that immediately you save you will get a 404 since the URL will still point to /processwire/. Just change that to the new name you gave admin and you are good to go.3 points
-
Works a treat. Thanks for explaining, that was very helpful! Here's the finished hook for future reference. In templates/admin.php // user template switch warning in backend $this->addHookAfter('Process::execute', function($event) { // only works for logged in users that have a custom frontend template enabled if ($this->wire('user')->isLoggedin() && $this->wire('user')->template_switch->value != 'default') { $u = $this->wire('user')->name; $t = $this->wire('user')->template_switch->title; $p = $this->wire('config')->urls->admin . "profile"; $this->wire->warning("Frontend der Seite wird für User $u aktuell mit dem Template \"$t\" ausgegeben. <small>Einstellung \"Frontend Template\"im <a href='$p'>Benutzer-Profil</a></small>", Notice::allowMarkup); } });3 points
-
In a template $page is the current page that your visitor has requested and is being output for them. $pages gives you access to all pages in the system by calling methods like $pages->find() or $pages->get(). “Child” is only one child. When you call $page->child() it will give you the first child. If your page has multiple children, you may want all of them. That’s when you call $page->children(). If you want only some children, you can pass a selector to the method. See the docs herehttps://processwire.com/api/ref/page/child/ and here https://processwire.com/api/ref/page/children/. “Render” usually implies that the method generates markup aka HTML code for you. When you use get() you simply get the thing you asked for. It may be a Page object or the contents of some field or something else, depending on the context. ProcessWire has the concept of “Output Formatting”, which means that field values can sometimes also generate/contain markup themselves, without the word “render” showing up anywhere. So it’s not all that clear cut, but that’s the basic idea. ”Rendering“ means taking something that can’t be output to the browser directly and formatting it, usually as HTML. Sometimes ProcessWire makes its features available to you as properties AND as methods. This can be convenient but also confusing. You’ll have to consult the docs for each individual case, or just test out what works. If you want to pass arguments/options, you must use the function way. If you’re not familiar with the concepts of properties and methods/functions, perhaps familiarize yourself with PHP basics before reading the ProcessWire docs, or just read the PHP docs as you go along. Or ask in the forums here, PW has an exceptionally friendly community. Welcome to ProcessWire ? Edit: To answer your actual question, you cannot do $page->children->image->url, because children is a PageArray. It's a way to collect multiple pages, in this case all the child pages of $page. So when you call children->image, it doesn't know which child page to take the image from. You could do $page->child->image->url. That would give you the image from the first child page. Be aware that there may be no children, or the first child may not have an image. These cases may need to be considered as your website grows.2 points
-
As it seems you are quite new to PW and motivated I suggest to avoid if(this AND that AND that): // user template switch warning in backend $this->addHookAfter('Process::execute', function($event) { $user = $this->wire('user'); // early exit if user is not logged in if(!$user->isLoggedin()) return; // early exit if template is default if($user->template_switch->value == 'default') return; // show message to change template $u = $user->name; $t = $user->template_switch->title; $p = $this->wire('config')->urls->admin . "profile"; $this->wire->warning("...", Notice::allowMarkup); }); Of course this is totally up to you or anybody but IMHO this improves readability a lot. ?2 points
-
Call me crazy but i kinda like it so far. And we solved it together @adrian ? thats what problems are for, to be solved. Again thank you for all the help.2 points
-
They have disabled it, just not via disable_functions line. I don't know how they have done it, but if you google: php "due to system policy" you'll see lots of results, so it must be a fairly common thing on budget hosting.2 points
-
2 points
-
You could just put it into templates/admin.php. The file should already be there. Here is the entire default file plus a line for the notice: <?php namespace ProcessWire; /** * Admin template just loads the admin application controller, * and admin is just an application built on top of ProcessWire. * * This demonstrates how you can use ProcessWire as a front-end * to another application. * * Feel free to hook admin-specific functionality from this file, * but remember to leave the require() statement below at the end. * */ if ($user->isLoggedin() && $myCrazySetting) $this->message("This is the notice text"); require($config->paths->adminTemplates . 'controller.php');2 points
-
2 points
-
I ended up just ripping out what I needed from this (didnt think it required a whole library really), so I also included google and outlook as options.2 points
-
No reason to apologise. Ideas are always welcome here, no matter how rough they might be ? If I got this right, you could sort of achieve the Admin view part of this with Listers and some custom code, or perhaps ListerPro out of the box, though that would mean that such content is no longer managed in any sort of tree structure (yet, at the same time, it would still actually exist in the tree). The latter part could then be half resolved by hiding the page from the tree with a hook that hides such pages from the tree, but it still wouldn't change the fact that in ProcessWire pages always exist in a singular tree. This "one tree" approach is actually pretty fundamental to ProcessWire, and — as Ryan explains in this very old thread — there's a good reason for this: I think someone was developing a module (?) a while ago that sort of created separate trees, though again it was basically a "virtual" approach where you get multiple page lists in admin, yet behind the scenes things are still in one big list. On a loosely related note: a while ago I came across a site that used an approach of URL segments + separate PHP router library. Not necessarily an approach I would've preferred — in most cases that's just some added complexity you don't really need — but that's always an option. Anyway, I think you may be onto something here, but I'm just not sure I'm seeing the entire picture yet ?2 points
-
This is interesting! Full disclosure: on a few occasions I've considered adding a separate model layer to Wireframe, but I've never found a proper reason, i.e. I couldn't think of anything I can't do without it — or even anything it would make notably easier or more effective or more organised — and I'm trying not to add features just because they'd be fun to implement. That being said, I'm always on the lookout for interesting new stuff to add, as long as it adds real value to the framework ? I think when you say "model" you probably mean something a little different than what it means to me personally. In my mind models are tied to data structure, have very little to do with routing, and so on. In fact from what I could gather from your examples it looks like such models would indeed be a lot like custom post types in WordPress in that they'd be located in a single "bucket" and define a per-model route that's separate from the regular page tree structure. If that's the case, wouldn't one variation of that just require creating a parent page on the root level and then subpages below that? Or, for more complex routes, you could make the parent page render its subpages based on URL segments. All the building blocks are already there, though obviously this one needs quite a bit more work — you have to define the routes programmatically, for one. Any chance you could flesh your idea out a little more: What would you use this sort of thing for? How would you envision defining the routes? How would this be different from existing options, such as placing a parent page under root and then subpages using specific template under that, or using URL segments — i.e. would the biggest benefit be some abstract method of defining routes? WordPress templates are a bit different in that they're about representing data, while ProcessWire templates are obviously all about structuring data. Wireframe, for an example, has concepts called "layout" and "view", which are largely in line with WordPress' templates: each template can have multiple views, and each of those views can then be used to render pages in different ways, and/or for different purposes (JSON, RSS, HTML, etc.) Long story short: I'm intrigued, but not entirely sure of all aspects that this concept would bring to the table. Definitely interested in hearing more though!2 points
-
We recently rebuilt the Architekturführer Köln (architectural guide Cologne) as a mobile-first JavaScript web app, powered by VueJS in the frontend and ProcessWire in the backend. Concept, design and implementation by schwarzdesign! The Architekturführer Köln is a guidebook and now a web application about architectural highlights in Cologne, Germany. It contains detailled information about around 100 objects (architectural landmarks) in Cologne. The web app offers multiple ways to search through all available objects, including: An interactive live map A list of object near the user's location Filtering based on architect, district and category Favourites saved by the user The frontend is written entirely in JavaScript, with the data coming from a ProcessWire-powered API-first backend. Frontend The app is built with the Vue framework and compiled with Webpack 4. As a learning exercise and for greater customizability we opted to not use Vue CLI, and instead wrote our own Webpack config with individually defined dependencies. The site is a SPA (Single Page Application), which means all internal links are intercepted by the Vue app and the corresponding routes (pages) are generated by the framework directly in the browser, using data retrieved from the API. It's also a PWA (Progressive Web App), the main feature of which is that you can install it to your home screen on your phone and launch it from there like a regular app. It also includes a service worker which catches requests to the API and returns cached responses when the network is not available. The Architekturführer is supposed to be taken with you on a walk through the city, and will keep working even if you are completely offline. Notable mentions from the tech stack: Vue Vue Router for the SPA functionality VueX for state management and storage / caching of the data returned through the API Leaflet (with Mapbox tiles) for the interactive maps Webpack 4 for compilation of the app into a single distributable Babel for transpilation of ES6+ SASS & PostCSS with Autoprefixer as a convenience for SASS in SFCs Google Workbox to generate the service worker instead of writing lots of boilerplate code Bootstrap 4 is barely used here, but we still included it's reboot and grid system Backend The ProcessWire backend is API-only, there are no server-side rendered templates, which means the only PHP template is the one used for the API. For this API, we used a single content type (template) with a couple of pre-defined endpoints (url segments); most importantly we built entdpoints to get a list of all objects (either including the full data, or only the data necessary to show teaser tiles), as well as individual objects and taxonomies. The API template which acts as a controller contains all the necessary switches and selectors to serve the correct response in <100 lines of code. Since we wanted some flexibility regarding the format in which different fields were transmitted over the api, we wrote a function to extract arbitrary page fields from ProcessWire pages and return them as serializable standard objects. There's also a function that takes a Pageimage object, creates multiple variants in different sizes and returns an object containing their base path and an array of variants (identified by their basename and width). We use that one to generate responsive images in the frontend. Check out the code for both functions in this gist. We used native ProcessWire data wherever possible, so as to not duplicate that work in the frontend app. For example: Page names from the backend translate to URLs in the frontend in the form of route parameters for the Vue Router Page IDs from ProcessWire are included in the API responses, we use those to identify objects across the app, for example to store the user's favourites, and as render keys for object lists Taxonomies have their own API endpoints, and objects contain their taxonomies only as IDs (in the same way ProcessWire uses Page References) Finally, the raw JSON data is cached using the cache API and this handy trick by @LostKobrakai to store raw JSON strings over the cache API. Screenshots1 point
-
1 point
-
You need the include=all in the children selector. $media_tags = $pages->get("template=fundus-index")->children("include=all, sort=title"); You could also find the children directly by specifying the parent in the selector, eg: $media_tags = $pages->find("parent=fundus_id, include=all, sort=title")); replacing fundus_id with the ID of that parent page.1 point
-
For the storage of data that does not change anymore after saving it, (I mean it's not necessary to edit and save constantly) I use the module Fieldtype YAML. It's very easy to read the data and to save it too. You can save simple objects or an entire structure in the field, however you want to do, only using an associated array. For saving part check this post:1 point
-
1 point
-
Well... I'm also not convinced 100% myself to ban frontend editing completely ? The interface is great and it's so much more user friendly to get exactly the same visual representation as you type. And it sounds reasonable to only load/save parts of a page and not everything. It always depends on the usecase, just wanted to note that one has to be careful with those fancy tools and also think of the drawbacks ?1 point
-
I don't know if that is the case and I don't have time to investigate. You did lots of things right (like placing the most basic hook you can think of, then check if it works and only then doing the next step). If you encounter any problems on that road you either have to look for a different solution (like changing from frontend to backend editing) or you have to investigate and find the reason why things don't work as expected. In the current case it could either be a bug or that saving of the field just works a little differently when fired from the frontend. That's by the way one of the reasons why I'm not using frontend editing any more. It bring's too much troubles for too little benefits imho. Doing those investigations can be frustrating sometimes, but you'll learn a lot about ProcessWire which will help you on all following challenges ?1 point
-
If I got this right, you could sort of achieve the Admin view part of this with Listers and some custom code, or perhaps ListerPro out of the box, though that would mean that such content is no longer managed in any sort of tree structure (yet, at the same time, it would still actually exist in the tree). The latter part could then be half resolved by hiding the page from the tree with a hook that hides such pages from the tree, but it still wouldn't change the fact that in ProcessWire pages always exist in a singular tree. If I understand you both correctly this is what I'm doing with RockFinder2 + RockGrid / RockTabulator. It's far from perfect yet, but it's built for managing content in a non-hierarchical way which is a very common need IMHO. I don't like listers for that purpose at all. They are limited, they are ugly (*personal opinion!* taking too much space etc), they are hard to customize (like colorizations etc), they are not reacting fast to user input. Of course, there are good reasons why they work as they work: Scalability, access control, multilanguage. These are all points that are challenges for my modules. But in all my projects the benefits of having structured grids of data that are nicely designed, compact and "reactive" (like when filtering columns etc.) outweigh the cons. Not saying my modules are the way to go or better than what you describe. Just wanted to share what is already there and how I'm using it.1 point
-
Hi Marco, SnipWire supports multi currency. The taxes handling is very flexible: you could either use Snipcart's own taxes handling, an external taxes provider (like TaxJar) or the custom taxes provider of SnipWire (which has the most flexible taxes handling when it comes to shipping taxes calculation). Starting with 2021 there will be new tax rules in Europe! In simplified terms, the VAT from the customers country must be charged (this is already the case when you sell digital products!). This means that a shop system must reliably determine the country of the customer. This is currently not supported by SnipWire but will be in a future version! Nevertheless, some of the external taxes providers implemented by Snipcart already supports this kind of taxes handling. Hopefully this clears things up a bit! -- Martin1 point
-
Thank you so much! Sorry for posting in the wrong thread, i couldn't find the other one (myfault).1 point
-
Unchecking Versions List will only fix the error in the PW Info panel. The error for the Console Panel is not coming from the Console panel - it doesn't use set_time_limit() - the call to set_time_limit() is in the File Compiler module which shouldn't be updating its cache unless the Console Panel file code is changed, which it shouldn't be. Maybe you could try commenting out this line (https://github.com/processwire/processwire/blob/f9337d77a5fc9ae0cdd9486261768b102347bfd0/wire/core/FileCompiler.php#L384) and see if that fixes things without breaking the compilation process.1 point
-
1 point
-
Yes, you enter database information when you restore the backup (try it).1 point
-
1 point
-
Hey! No I think we're thinking of models the same; I didn't mean to imply that they would be tied to their routes, as the templates (basically) are in PW. I do mean models entirely separate from routing, thereby allowing for routes to be specified as needed and totally custom. The ways you mention with parent pages and URL segments I've tried, but still don't prefer totally overall, all the time... Yes, define routes abstracted. For example for a car sales website... which could totally be done in PW as-is, but for one thing I would not really want the listings to even be in the tree view in the admin... Maybe it could just be a module that would allow for creating templates and admin views of pages (?) outside of the page tree that then can be controlled and moved around (?) more easily (?) in views for those within the tree. That's probably just fine. Sorry this is a really rough idea. I don't believe I'm making it any clearer. Apologies.1 point
-
If it only was Tracy then I'd be keener to work on a fix, but in reality there is only one piece of code from Tracy that is causing the problems and you can disable that by unchecking the "Versions List" option here: The errors in the other two panels are due to PW's file compiler which I can't fix but they should go away after reloading the page because the file compiler shouldn't have to run again if the code for those panels is already cached. Note that the filecompiler will also throw these errors on other modules that don't define the PW namespace, but again they should only show the first time the files are accessed, or if they are updated in the future. Do you see that, or does the filecompiler error keep occurring on subsequent page loads?1 point
-
1 point
-
If you, for what ever reason, need to present a link to a static *.ics file for download, you can add this line to the servers .htaccess file instead have to send http headers: AddType text/calendar .ics1 point
-
Thanks for the info and the welcomes ? So far I really dig how this is setup, but definitely still learning the ropes, so that helps give me the confidence that I shouldn't worry too much. I've got a bit of an ambitious project so I'm sure you'll see me around, and hopefully I can eventually contribute something!1 point
-
1 point
-
@eydun - please try the dev branch - https://github.com/flydev-fr/Duplicator/tree/dev - it uses native backups and solved the timeout issues I was having.1 point
-
Hi, I noticed that started to get some spam comments on my site from IPv6 adresses, but unfortunately I cannot easily see from which addresses since IPv6 addresses get logged as 0.0.0.0. I found there is an (rather old) issue regarding this on Github: https://github.com/ryancramerdesign/ProcessWire/issues/1596 Is a fix regarding this on the roadmap? I would prefer not to use $_SERVER['REMOTE_ADDR'] or something similar. Thanks in advance! //Jasper1 point
-
PHP probably runs under the user configured in your anonymous authentication settings. In IIS manager, click on your website, then on "Authentication". Select "Anonymous Authentication" and click "Edit" in actions bar at the right. There you will see the user (default: IUSR). Grant this user modify permissions on the assets folder.1 point
-
1 point
-
1 point
-
@SamC it's really as simple as that: https://processwire.com/blog/posts/new-ajax-driven-inputs-conditional-hooks-template-family-settings-and-more/#new-conditional-hooks Update 2022: $wire->addHookAfter('Pages::saved', function(HookEvent $event) { $page = $event->arguments('page'); bd('page saved'); bd($event, 'event'); bd($event->object, 'event->object'); bd($event->arguments(), 'event->arguments'); }); in the beginning it can be a little confusing when to use event->object, event->arguments and event->return but with the help of tracy you can quickly bring light into the dark: add the code above to the tracy console, set the radio on the right to load it on "ready" (same as placing the code in the site/ready.php file) and save any page: $event->arguments('page') is the same as using $event->arguments(0) that you will see very often and in the tracy dump you see that 0 is simply the key for the first argument in that hookevent. you can also collapse the "data" property of the hookevent and you would see the same: You can also use your IDE to quickly find what the HookEvent is returning/containing in which hook. Let's take the common saveReady hook as an example: We know that the hook is attached as Pages::saveReady (eg because we have read that somewhere) That means that the hook is part of the "Pages" class, which is located at "/wire/core/Pages.php" - that's easy to find out using CTRL+P in VSCode: Searching for "___saveReady" lets us find the corresponding method: Now we see, that we have ONE "arguments", being Page $page - this means $event->arguments(0) would return the page being ready for saving $event->object would be the class, here "Pages" $event->return is the return value of that method, here $data (line 1739) Edit: There's some additional explanations in this post: https://processwire.com/talk/topic/27248-pagestrashtemplatefoo-vs-pagestemplatefootrash/?do=findComment&comment=224659 #search afraid of hooks1 point