Jump to content


Popular Content

Showing content with the highest reputation since 07/31/2020 in all areas

  1. 30 points
    In preparation for the next master version, this week no new features were added, but just like last week, more than a dozen issue reports were resolved. Having focused largely on fixing various issues over the last month, I feel pretty confident that the current dev branch is significantly more solid than the 3.0.148 master version. It adds and improves a whole lot, and also fixes a lot. And to the best of my knowledge, there aren’t any new issues between 3.0.146 and 3.0.164 that haven’t already been fixed. Basically, I don’t think it makes any sense to keep all these updates exclusive to the dev branch any longer, so have merged it to master, today. Consider it a soft launch, as I haven’t made it an official tagged version yet. Maybe I’m shy, but wanted to wait till Monday before Git tagging it and making it official. The master branch has a different audience than the dev branch, and so there’s always that possibility that some new issue will appear that hasn’t on the dev branch, and wouldn’t have. So we’ll let it marinate on the master branch for the weekend before broadcasting it very far. By this time next week, I should have a blog post ready that covers all that’s new in this version, which is 226 commits ahead of the previous master (3.0.148), so there’s a lot to cover. I want to thank you all that have been helping to identify and report issues on GitHub as they come up. Having covered a lot of issue reports over the last month, I can see a lot of effort goes into preparing many of the reports. Your work is appreciated. This month I focused primarily on the reports that I thought were likely to make the most difference to the most people. I also focused on issues that I thought could be accommodated without introducing potentially new issues or new code to test. Of course, not every report could be covered, and there’s always more to do, so I’ll be getting back to it on the dev branch here soon. In addition, I’ve held off on some new things I’ve wanted to add for awhile (a feature freeze of sorts) in preparation for an end-of-month master version. I’m looking forward to outlining all that’s new in next week’s blog post. Until then, thanks for reading and if you get a chance to test out the new 3.0.164 version, please do and let me know how it goes (both master and dev branches are identical right now). I hope you have a great weekend!
  2. 11 points
    There's now a free and open source version similar to sizzy available: https://responsively.app/
  3. 9 points
    @fruid I don't really understand your use-case. You say your client is going to use SQL to update the database, does that mean they are going to write raw SQL queries in front of a terminal? That seems like a really inefficient way to go about content creation, especially since you have to make sure your data fits within the constraints defined in the template and field settings. Despite that, you can still do that, you just have to add a couple of JOINs and be careful with your WHERE clauses. Each field table comes with a foreign key corresponding to the page ID. If your client is really some kind of SQL wizard who prefers the power of raw SQL for data migration over the limited interfaces puny mortals have to use, what's stopping them? Or do you mean "the client is going to log into phpMyAdmin / Adminer / MySQL Workbench / ... and insert data through that interface"? In that case, you're not really using SQL anyway, you're just using an interface that's closer to the database, that *may* be slightly more efficient to use for batch creation / updates if you really know what you're doing. If that's what your client wants – well, that's an interface you can build for them! Something like a batch update module that lists pages and allows you to edit them inline. In fact, such a module exists already: Lister Pro comes with inline editing for multiple fields at once. This gives you a convenient interface to update many pages at once and still stay within one backend and have all the input / constraint validation apply to your edits. Best of both worlds 🙂 By the way, if you've ever tried to manually find something in a Drupal 8 database, you will like ProcessWire's database structure MUCH more ...
  4. 9 points
    Thanks, @ryan! Sometimes I think that ProcessWire is so mature and feature rich that only fixing the issues at hand can make it stand out even more than adding the new stuff (until the the stuff is added and I start thinking that I could not live without the features just added))) Thank you so much for keeping the right balance.
  5. 9 points
    Where exactly are you stuck? Differentiating between normal and AJAX requests, rendering content (are you doing that server- or client-side?), encoding the content for the AJAX response? An example of your current code and what's not working about it would be helpful. A couple of observations, in no particular order: The first thing I notice is that the infinite scroll library you linked seems to employ a non-standard way of doing "load more" buttons. Instead of requesting only the new items, it works with an existing classic pagination and just loads the entire next page, throws away everything but the new items and adds them to the existing container. While this does work, it's incredibly wasteful, loading entire pages just to discard most of them immediately. So don't let that library trip you up if you want to build "real" AJAX-powered pagination. What endpoint are you calling in your AJAX request? I remember some tutorials around here recommending to hit the same URL as a regular page view, and differentiating between normal page views and AJAX calls by checking the X-Requested-With header – in my opinion, that's not a good approach. It doesn't even work properly if you use the Fetch API (the modern alternative to XMLHttpRequest). Depending on how much side-loaded content you need on your site, I would either use a URL parameter (?ajax=1) or build an entirely separate endpoint (/api/events/...). The latter approach scales much better. Are you returning HTML or structured data from your endpoint? Depending on that: Returning structured data, i.e. a JSON-encoded object with information about the events is the cleaner way to go about this. But since the first five elements are already rendered server-side, that means you have to replicate your template-logic in JavaScript to create the same HTML structure that the server-rendered events have. Not ideal. In general, I only use this approach if the entire app is client-side rendered (like the Architekturführer Köln). Returning server-rendered HTML is not great, because it makes your API non-reusable (for example, if you want to display side-loaded events in different places with slightly different layouts, you'll need separate endpoints or parameters). It's also just not very clean to insert raw HTML into your page. Though it is a bit easier for simple use cases. I need to mention this: Do you really need to side-load your events? It's one of those features that clients go crazy about because it's "cool and modern", but why not use a regular pagination, which works out of the box and is also better for SEO? If the reason is that your visitors need to load too many pages this way, is there any reason why you can't just show 25 events per page instead of 5?
  6. 7 points
    The hosting company 20i here in the UK have added ProcessWire as a 1-click install. This is a really good company, they recently advertised on FileZilla installs (may still do). Here is the announcement: https://mailchi.mp/20i/august-news-for-20i-resellers
  7. 7 points
    Each field may belong to more than one template, and each template has a different set of fields. Current structure works well with that concept, makes it possible to connect (or disconnect) fields with/from templates with ease, makes it unlikely for a single table to grow to giant proportions (thus making all queries against it slower), and also allows fetching/searching/saving the exact data that ProcessWire needs to fulfil a specific request. So yes — there are advantages to current structure. It's also a very fundamental part of ProcessWire, so changing it is not possible without major changes to the core 🙂 It has been. If you'd like to read a bit more on it, I'd suggest doing a google search for something like "processwire database structure". You'll find a lot of existing content on this topic 🙂 Your point of view is not unheard of for newcomers but trust me, there are valid reasons why the database architecture is what it is. Much of it is due to the fact that ProcessWire — unlike some competing platforms, I might add — was designed with custom data structures (custom fields) in mind from the ground-up. Some other systems (WordPress, for one) have a much simpler database structure, but that's because they weren't originally intended for the same kind of use as ProcessWire. In the context of ProcessWire this would be a bad idea: First of all the Admin is a ready-to-use tool for managing content, and I highly doubt that anyone will really have easier time managing the content with raw SQL. It can be fun and/or if you've had to do that a lot in the past you may be used to it, but still: ask them to give the Admin a try and I bet that this idea will go away in no time. If you manually update the rows in the database, most of what ProcessWire's fields do will be completely skipped. This includes validation, filtering, and sanitization; things that are there to help you build sites with valid and well formed data. Without these features you will run into trouble eventually, it's just a matter of time. ProcessWire does internal cleanups and such using hooks, and those will not get triggered if you update the data manually in the database. This means that you'll likely be left with broken data, missing pieces here and there, and so on. Some fields (take Repeaters for an example) will also be very difficult to update manually via database. Finally, while we're on the topic of hooks: they are a major feature in ProcessWire, used by both core and third party (module) code — and, once you get used to it, probably your own code as well — and again if you don't go through the "official channels" (API or Admin) you'll loose this benefit altogether.
  8. 6 points
    Not quite sure what's causing the recursion error, but your method is marked private, which means it can't be called from outsite. Because your page class extends Page which extends Wire which comes with a magic __call method that will be invoked in this case. That method tries to figure out what you're trying to do, since it's supposed to provide easy access to properties and methods of all Wire extending objects. The error call stack indicates there's something going wrong there. Making your getSummary method public should fix the issue!
  9. 6 points
    No, that's a common misconception. There's no security benefit at all (it can be bypassed super easily), but comes with multiple downsides (worse UX, higher chance of typos). It may even decrease security because it discourages the usage of password managers. See security.SE, NCSE and web.dev for reference. By the way that's only slightly related to this issue. The profile page does allow passwords to be pasted; but the inputs for the new password are only activated after the old password field has been typed into, and that event handler only listens for input events, not paste events.
  10. 6 points
    Probably worth mentioning that since this setting prevents ProcessWire from using unfamiliar hosts in output, it's actually pretty important: Let's say that your server was configured to serve your site with any host that a visitor happens to provide. (I've seen this happen, but admittedly it's a major configuration fumble.) Someone points some-weird-and-perhaps-malicious-domain.tld to your site, and then visits the site using said domain. This could be intentional, or even an accident (again this is something I've seen happen, as weird as it may sound.) Finally some code — your own, or perhaps code from a third party module, or even some core feature — asks ProcessWire for the full hostname, and makes use of it in output. Now, if the $config->httpHosts setting didn't exist, ProcessWire would have no way to know which domains are valid, and it would just have to trust that the domain specified by the user is indeed a valid one. Any output using this potentially malicious domain could then get cached, leading to various cache poisoning related issues: redirecting other visitors to this domain, or perhaps making the visitor or ProcessWire itself unknowingly send private data there, thus granting a third party access to it.
  11. 5 points
    Render oEmbed data from YouTube/Vimeo URLs... or TextformatterVideoEmbed for power users. https://github.com/nbcommunication/TextformatterVideoMarkup The use case... On an upcoming project, we want to be able to render YouTube/Vimeo URLs as thumbnail images, that when clicked open up in a (UIkit) lightbox. Additionally, we want to be able to specify the thumbnail image - as part of a RepeaterMatrix block which contains a URL field (video) and an Image field (thumb). The result is this module, which allows you to specify the markup used to render the oEmbed data: The formatter can be used on any Text field e.g. Text, Textarea (CKEditor or not), URL etc. Global configuration options are available (e.g. rel=0), based on TextformatterVideoEmbedOptions. An 'empty value' can be specified for URLs that do not return data from the oEmbed endpoint The render method is hookable, allowing you to customise rendering on a per page, per field basis Plenty more information here 🙂 https://github.com/nbcommunication/TextformatterVideoMarkup/blob/master/README.md Back to the use case... How do we render the thumbnail and then use the image from our Image field? In the module config Markup field: <figure data-uk-lightbox> <a href="{url}" data-poster="{thumbnail_url}" data-attrs="width: {width}; height: {height}"> <img src="{thumbnail_url}" alt="{title}"> </a> </figure> Then in site/ready.php <?php $wire->addHookBefore('TextformatterVideoMarkup::render', function(HookEvent $event) { // Arguments (for info) $tpl = $event->arguments(0); // string: The markup template $data = $event->arguments(1); // array: The oEmbed data $url = $event->arguments(2); // string: The requested URL $emptyValue = $event->arguments(3); // string: The empty value used if no data is returned // Object properties (for info) $page = $event->object->page; // Page: The page $field = $event->object->field; // Field: The field $html = $event->object->html; // bool: Is it HTML being parsed, or plain text? // Replace the thumbnail image if($field->name == 'video' && $page->hasField('thumb') && $page->thumb) { $data['thumbnail_url'] = $page->thumb->url; $event->arguments(1, $data); } }); The module requires PW >= 3.0.148 and PHP >= 7. It probably doesn't need to, but the expectation is that power users will be able to meet these requirements! The module is also Beta - please don't use in production yet. I suspect there will be edge cases related to the changes I made to the URL regexes from TextformatterVideoEmbed - so far though they are working for me. If you come across any issues please let me know! Cheers, Chris
  12. 4 points
    Hi @fruid, I understand your concerns. The db structure can look quite complex, especially if you are used to working with db tables and SQL select ... from ... etc; Teppo explained the reason for this structure. The great thing about this structure is that you get an abstraction layer that makes all the PW awesomeness possible. It transforms all the custom fields and data in the database into PHP page objects that can be used for easy and effortless markup generation. I'm talking about the great pw api 🙂 echo $page->title; echo $page->headline; echo $page->image->size(200,200)->url; Display all that in multiple languages? Same code 😎 I think that's really genius! Are there downsides of this approach? Yes, as always. For example it is not easy for PW to do a "SELECT * FROM table_xy" to get a list of thousands of rows of data. That's because the magic of transforming the complex db structure into an easy to understand and use API has some costs. It needs to load all rows of data into memory and therefore this get's slow when working with lots of data. PW handles this by applying pagination wherever possible, so that it only loads chunks of data and stays fast. But still there might be situations where you simply need a good old "SELECT * FROM ..." and "foreach($pages as $page) $rows[] = [$page->title, $page->headline, ...]" is no option. That was quite a long introduction and explanation why I built RockFinder3 😄 So at least the PULL part of your request is already doable 🙂 What about the PUSH part (meaning updating data in the DB, doing "UPDATE ... , INSERT INTO ...")? First, you can still use native SQL commands on PW, it's quite easy: $result = $this->database->query("SELECT * FROM pages LIMIT 5"); var_dump($result->fetchAll(\PDO::FETCH_OBJ)); The problem is, that updating data can get quite complex because you need to update several tables, several fields, several languages... That's why such operations should really be done via API. That's of course a totally different approach if you are used to working with SQL commands, but it is the best option in 99,5% of the cases. There's a topic about that where I showed my findings: For the remaining 0,5%: You see, it can be quite easy. Is it a good idea? 99,5% no, because you don't get all the security features of PW that ensure that data is sanitized before storage etc. And you don't get the power of hooks. Updating pages via API will still trigger saveReady() and saved() hooks while direct SQL updates will not. Hope that helps 🙂
  13. 4 points
    Release 0.7.0 adds a few features and fixes an issue reported by @MoritzLost. Collection panel: Field names as column headers The collections panel now uses the field label as column header. No need to pass them in explicitly anymore. See the docs on column headers for details. Shortcuts panel: Add option to hide shortcut summaries Disable the summaries altogether by setting the summaries option to false. Shortcuts panel: Fix undefined-index error when destructuring shortcuts
  14. 3 points
    That was the way they did it in other CMSs I used in former times - before I luckily found ProcessWire! It was like a breeze of fresh air after a long stuffy time... The dilemma you are in is to incline to habits you are familiar with. Try to understand the way PW works, and you will soon be convinced. (And as a next step: Try to convince the client...) All the best!
  15. 3 points
    This is not the whole picture. Simple fields might only have a single `data` column, but complex ones might have many more. Also multi-language support does work by adding `data_{lang}` columns to those field tables. Though I can see the argument for having template (or more correctly fieldgroup) based tables, where columns of fields would be merged into an single table.
  16. 3 points
    It happens to all of us 😄 This is actually why I dislike the use of the magic methods like __call, because they make tiny mistakes like this harder to spot ... without the magic, this would just result in a clear, easy to fix error message, but with it it's way harder to figure out what's going on.
  17. 3 points
    @cb2004 - if that works, great - I didn't think it would work to set something in ready.php and use it in config.php PS - you can simplify the $subMembers bit to: $subMembers = wire('pages')->get(1302)->children->each('id'); or even better because it won't load the pages, just their IDs: $subMembers = wire('pages')->findIDs('parent=1302');
  18. 3 points
    The ecumenical city pilgrim trail in Villingen, Germany is a small trail through the city where you can visit churches and and other places of interest. This Progressive Web App is a small website to guide visitors through these places and give additional informations. You can install it on your smartphone or tablet and walk the trail with it. app.stadtpilgerweg-villingen.de Features: Interactive Map Progressive Web App Interactive Map Before entering the map you get a little tutorial where you can choose between two routes, the standard trail or a more accessible trail. You can track your position on the map and click on the markers. Each marker is a view with additional information to the place. The views can contain texts, quotes, images or a chat element. The map was realized with Leaflet and styled with Mapbox. Progressive Web App The website can be installed as Progressive Web App on your smartphone or tablet for a better experience. The PWA remembers the last visited view and has no unnecessary browser navigation. It can also partly work offline and caches almost everything. The PWA was realized with the help of Workbox. Modules used: Repeater Matrix ProCache Map Marker (Google Maps) Sitemap ProcessWire Upgrade TOTP two-factor authentification Tracy Debugger Regards, Andreas
  19. 3 points
    Are you using PHP 7 or above? '??' is a null coalescing operator added in PHP 7.
  20. 3 points
    You'll need to do it with raw SQL. Something like this: $pdo = new \PDO("mysql:host=$config->dbHost;dbname=$config->dbName", $config->dbUser, $config->dbPass); $stmt = $pdo->query('SELECT `id` FROM pages WHERE templates_id = "29"'); $rows = $stmt->fetchAll(\PDO::FETCH_NUM);
  21. 3 points
    @ryan In the spirit of closing up Github issues, could you take a look at issue #1133? Changing passwords on the profile page does not work if the old password is pasted instead of typed in manually. Edge-case, admittedly, but when a client stumbles upon this it's pretty disruptive. As far as I can tell it's just a jQuery event that needs to listen to paste events as well as input events, so it should be a one-line fix. Though of course I don't know the code base so well, so I might be mistaken 🙂 Same for issue #1111 about titles getting cut off in the page tree. Thanks!
  22. 3 points
    The idea from @Ivan Gretsky of using template tags (which are on the Advanced tab of Edit Template) seems like a really good one. An approach to searching for tags on templates is here: Another possibility would be to prefix each relevant template name (e.g. "prefix-templatename") and then find using the "starts with" operator: $foundPages = $pages->find("template^=prefix"); But I think the tags approach would probably be better – more flexible, and organises things nicely on the Templates page in the admin.
  23. 3 points
    There is no easy way I know of to do exactly what you're asking for. But as far as I understand the actual need is to find pages with selected templates. If you do not need to select the templates to be used in selector in admin, you should be able to hard-code the selector like this (see here for explanation): <?php $childChildren = $pages->find("template=template-a|template-b|template-c, sort=sort"); If you need to be able to select the templates in admin, you could add this module to some page, and then use it's value in a selector. Hope the module still works in current version of PW. There is an option to tag fields in admin and then use the tag instead of a list of fields in selectors. If the same thing worked for templates, that could be a good way to solve this task. But I did not find any docs on that, so you just might want give it a try first, and then fallback to the module if it's not possible.
  24. 3 points
    With your code you’re only getting the children of /shop/products/’s FIRST child. Is that what you expect? If you want all grandchildren of /shop/products/, you could do something like $products = $pages->find('parent.parent.path=/shop/products/'); (Sorry if that’s not 100%, I just got up lol)
  25. 3 points
    And from the RFC: While I'd love to give this a try, this limitation is a dealbreaker for me. All the environments I work with host multiple versions of ProcessWire. Might be another reason to move to fully containerized environment... 😄
  26. 3 points
    Well this was a great one to do. The Beyond Banglatown site is the public facing site for a report conducted by researchers at the London School of Economics and the University of Manchester, and published by the Runnymede Trust. The aim is to present the findingsof the report in a publically accessible way that can be used by teachers and students and well as the general public. It covers the changing face of the neighbourhood around Brick Lane in East London. https://beyondbanglatown.org.uk/ Technically this was the first project we used ProcessWire on - although what with one thing and another it's taken 18 months to get the site launched, so we've managed to get a few others out before this one. It was certainly jumping in at the deep end though and we learned a lot. The site involves a fair amount of ajax driven content and we had to get to grips with importing the data used for the maps and graphs as well as sorting out how best to manage templates and assets. As far as modules that we used there's nothing too exciting, but certainly we made good use of TracyDebugger as we fumbled about. A special mention also needs to go to the PW documentation, the API references and of course this forum which provided a great deal of help. Anyway - we're really pleased with the site and it's already been getting very good coverage. Hopefully the first of many PW sites. s.
  27. 2 points
    [SOLVED] found a fix myself I followed: https://medium.com/@ajtech.mubasheer/setup-https-in-xampp-for-localhost-bc3d01393f31 to allow https as localhost for my xampp setup and I can now do api calls to https:// 😄
  28. 2 points
    What do you guys think of changing that to Vertikal spiegeln Horizontal spiegeln Beides spiegeln 90° drehen (rechts) 90° drehen (links) 180° drehen S&W Sepia Actually I don't understand why we have the options for 270° rotation at all? -270 = +90, so why does it show up??
  29. 2 points
    One more addition to this: The API is, in fact, one of the biggest advantages of ProcessWire. While the preferred term is "content management framework", one may as well think of it as an ORM of sorts. ProcessWire was never designed for direct database access, and that's the whole point: it's meant to (mostly) abstract the database layer away so that both developers and content editors can (as much as possible) avoid the complexities and inherent risks of dealing with SQL queries. I must say that I don't agree at all with your point about ProcessWire's advantages taking a backseat once the website is finished. I get where you're coming with this, but I'd assume that we can both still agree that it's extremely rare for a client to actually prefer SQL over a GUI — let alone them being competent and meticulous enough to produce data that fulfils all expectations we as developers might have. Obviously we come from different backgrounds and thus have different expectations. If I would've suggested to any of the clients I've ever worked with a platform that requires them to use SQL, that would've been a disaster 🙂
  30. 2 points
    @MoritzLost "Don't Panic Ipsum" is pretty cool. Nice work!
  31. 2 points
    Changing the method visibility fixed the issue. I don't know how I overlooked it. This is officially the most embarrassing thing I've posted on any support board... ever. Ha! That was totally an accident as I've written other page classes and minded the private/public declaration. Hope this ends up helping others! Thanks!
  32. 2 points
    Thanks @Ivan Gretsky and @BillH! I'm gonna use the first method with the templates. I see the interest about tags, but for my project, I have to use the templates
  33. 2 points
    And also for a11y 😉
  34. 2 points
    I haven’t read to deeply on this thread but just wanted to point out quickly that infinite scroll libraries lean towards leaving HTML page markup in place for seo reasons in that you most likely want those pages indexed like any other paginated content.
  35. 2 points
    If you need redirecting to the final domain name, you may have a look to this snippet. But you have to add it manually somewhere in the top of your root .htaccess file. ################################################################################ # Domain-Namen erzwingen # <IfModule mod_rewrite.c> RewriteEngine On AddDefaultCharset UTF-8 RewriteCond %{HTTP_HOST} ^example\.com [OR] RewriteCond %{HTTP_HOST} ^example-variation\.com [OR] RewriteCond %{HTTP_HOST} ^www\.example-variation\.com RewriteRule ^(.*)$ https://www.example.com/$1 [L,R=301] RewriteCond %{HTTPS} !=on RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] </IfModule> # ################################################################################
  36. 2 points
    @fruid never touch the core (wire folder). If you need another Uikit version for the frontend. Install in your site/template folder.
  37. 2 points
    Has anybody tried PHP Preloading in PHP 7.4 with Processwire yet? https://stitcher.io/blog/preloading-in-php-74 Sounds interessting... I would Preload all files in /vendor/ and /wire/. What do you think?
  38. 2 points
    Absolutely you can! You just need to get the page the repeater items are on, then you can access the repeater items on it. Based on your code above it should be simple: $id = 1234; // replace with desired page ID $alertspage = $pages->get(id); // replace "alerts" with your repeater field name foreach ($alertspage->alerts as $alert) { // do something with the repeater items ... }
  39. 2 points
    Small remarks. You should break the loop when work is done: foreach ($page->fields as $field) { if ( $field->type instanceof FieldtypePageTableExtendedGrid ) { // ... break; } } Another approach without loop. Fields is an instance of WireSaveableItems providing a find($selector) function: $selector = implode('|',$fields->find('type=FieldtypePageTableExtendedGrid')->each('name')); if ($page->hasField($selector)) { // ... do something }
  40. 2 points
    I played around with multi-instances and found out that we currently (PW 3.0.163) are not able to use multiple instances when more then one site has set $config->useFunctionsAPI (in site/config.php) to true! Then I saw that, (when $config->useFunctionsAPI was set to false) in all instances $config->version returned the same version, that from the master instance. So, first I was a bit confused, but then I thought that this may have to do with the early step when PW processes/build the $config. And indeed, if I set in all site/config.php files the $config->useFunctionsAPI to false, and then in all site/init.php files to true, everything is working fine. Now we can use our sites with the functions API, and we can load as many multiple instances in parallel we want. 🙂 TL;DR site/init.php /** * FOR BETTER SUPPORT OF MULTIINSTANCES, WE ENABLE $config->useFunctionsAPI HERE, * INSTEAD OF THE site/config.php FILE: */ $wire->config->useFunctionsAPI = true; Bootstrapping three different instances, in first step each of them in a single environment: <?php namespace ProcessWire; if(!defined('PW_MASTER_PATH')) define('PW_MASTER_PATH', 'E:/laragon/www/hwm/'); if(!defined('PW_MASTER_HTTPURL')) define('PW_MASTER_HTTPURL', 'https://hwm.local/'); // bootstrap ProcessWire instance site1 (3.0.163) require_once(PW_MASTER_PATH . 'index.php'); mvd([ 'httpurl' => $wire->wire('pages')->get(1)->httpURL, 'instanceNum' => $wire->getInstanceNum(), 'config->version' => $wire->wire('config')->version, 'useFunctionsAPI' => $wire->wire('config')->useFunctionsAPI ]); When running all three in a multi instance environment, they load fine, (no compile error), all with the use for the functions API enabled: <?php namespace ProcessWire; if(!defined('PW_MASTER_PATH')) define('PW_MASTER_PATH', 'E:/laragon/www/hwm/'); if(!defined('PW_MASTER_HTTPURL')) define('PW_MASTER_HTTPURL', 'https://hwm.local/'); if(!defined('PW_SITE2_PATH')) define('PW_SITE2_PATH', 'E:/laragon/www/hwm2/'); if(!defined('PW_SITE2_HTTPURL')) define('PW_SITE2_HTTPURL', 'https://hwm2.local/'); if(!defined('PW_SITE3_PATH')) define('PW_SITE3_PATH', 'E:/laragon/www/hwm3/'); if(!defined('PW_SITE3_HTTPURL')) define('PW_SITE3_HTTPURL', 'https://hwm3.local/'); // bootstrap ProcessWire master instance (3.0.163) require_once(PW_MASTER_PATH . 'index.php'); mvd([ 'httpurl' => $wire->wire('pages')->get(1)->httpURL, 'instanceNum' => $wire->getInstanceNum(), 'config->version' => $wire->wire('config')->version, 'useFunctionsAPI' => $wire->wire('config')->useFunctionsAPI ]); // create a secondary instance from master (3.0.163) $wire = new \ProcessWire\ProcessWire(PW_MASTER_PATH); mvd([ 'httpurl' => $wire->wire('pages')->get(1)->httpURL, 'instanceNum' => $wire->getInstanceNum(), 'config->version' => $wire->wire('config')->version, 'useFunctionsAPI' => $wire->wire('config')->useFunctionsAPI ]); // create instance of a second site (3.0.162) $site2 = new ProcessWire(PW_SITE2_PATH, PW_SITE2_HTTPURL); mvd([ 'httpurl' => $site2->wire('pages')->get(1)->httpURL, 'instanceNum' => $site2->getInstanceNum(), 'config->version' => $site2->wire('config')->version, 'useFunctionsAPI' => $site2->wire('config')->useFunctionsAPI ]); // create instance of a third site (3.0.152) $site3 = new ProcessWire(PW_SITE3_PATH, PW_SITE3_HTTPURL); mvd([ 'httpurl' => $site3->wire('pages')->get(1)->httpURL, 'instanceNum' => $site3->getInstanceNum(), 'config->version' => $site3->wire('config')->version, 'useFunctionsAPI' => $site3->wire('config')->useFunctionsAPI ]);
  41. 2 points
    Is it possible to control Processwire hook priorities, other than what the module devs agree on? For example, I have installed Redirects 404Logger 404Search The behaviour I want is: Redirect if possible, else Log page not found, and Do 404 search The behaviour I have is Log page not found, and Redirect if possible, else Do 404 search If I could lower the priority of 404Logger, then I guess this would work as I need it to. I imagine I can modify the module, but I'd want this to be update survivable. Cheers, Paul
  42. 1 point
    It would be fantastic if we could set different configurations for CKEditor fields based on template or user roles. Like described on https://weekly.pw/issue/14/ under "More CKEditor upgrades", we can use config files in /site/modules/InputfieldCKEditor/ to store settings per field. E.g. for the body field this would be /site/modules/InputfieldCKEditor/config-body.js. Maybe this logic could be extended to something like /site/modules/InputfieldCKEditor/config--field-body--template-home--role-mycustomrole.js. I was coming over from Joomla to PW couple of years ago and there we had an excellent CKEditor integration called JCE where you could define settings per user role etc. Maybe I am wrong but up to now we need to create additional fields if we need editor config settings per template. If there already is a way to do that I'd be happy to know.
  43. 1 point
    This should be possible to do with a hook. Look here for inspiration. Or just search for something like "hook admin inputfield show" (preferably, in Google)
  44. 1 point
    Am I right in thinking that multiple hooks that are added for the same event can be prioritised by doing something like this... $session->addHookAfter( 'login', $this, 'myLoginHook', array('priority'=>xyz) ); Where xyz is the relative priority for the hook and the lower the value, the earlier it will be called as the hooks are executed?
  45. 1 point
  46. 1 point
    Hi @Outward. Thanks for the answer. I use 5.6 version. But now i have changed to 7, than it works.
  47. 1 point
    Wow @MoritzLost, that's quite a response. Thanks so much! I will post a few examples here of my code but reading all your point made me realise a few things. Let's start from back: We don't need to load the events, but eventually there is going to be many of them in the archive. My idea was to display the most recent ones and if you want you can pull the next most recent, etc. With pagination maybe it will work the best as I can render everything on the server and just display what I need. My idea was to render everything at the server side as it is easier for me. But I completely get your point why this is not scalable. The Infinite scroll was also too complicated for the same reason, I didn't know what's going on in the back scenes. Right now: let postData = { "ajax:": true, "itemOffset": itemOffset, }; $.ajax({ type: "POST", url: url, data: postData, beforeSend: function (xhr) { xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded") }, success: function (data, status) { pageData = data; itemOffset += itemsToLoad; } }).done(function () { // when finished and successful container.insertAdjacentHTML("afterbegin", 'loaded: ' + pageData + ' (by jquery ajax)'); }); and then I wanted to execute that with my load_events.php template: $num_new_events = $_POST['itemOffset']; $events = $pages->find('template=nk-event, limit=$num_new_events'); // Render something about these events title, images, etc... foreach ($events as $event) { $event_title = $event->title; //etc... $events_output+= '<div class='event'>'. $event_title .'</div>'; //etc... } return $events_output; and then my JS will take it again from there. Of course, this didn't work last week, now it works but only from the home page, because it cannot find my load_events.php file or CORS policy issues. So at the end, I thought it's a bit more straight-forward but it seems like I need to rethink my approach. I have spent a lot of time on this project, so maybe I will try to make what I have until now work or switch to pagination. Thanks for the feedback!
  48. 1 point
    Of course, you are right. I should have read the requirements more carefully :-).
  49. 1 point
    Maybe useful for you @teppo. In one of my last projects I integrated a lightbox gallery that outputs both videos and pictures. The data source for the videos and images was a PageFile field. Here is an excerpt from the template in which the gallery was integrated via Javascript. Resizing works similarly as suggested by @Robin S // galleries $page->_galleriesJS = ''; $galleriePages = $pages->find('template=gallery'); // 16:9 inline video $markup = '<div class="mfp-video-wrapper"><div class="mfp-video-inner"><video width="854" height="480" controls autoplay preload> <source src="{src}" type="video/mp4"> Leider wird dieses Video von ihrem Browser nicht unterstützt. </video></div></div>'; if ($galleriePages->count) { $galleries = ''; foreach ($galleriePages as $gp) { if ($gp->files->count == 0) continue; $items = []; $filesDirPath = $gp->files->path; foreach ($gp->files as $gi) { if (!fileExists($gi->url)) continue; // inline video if (in_array($gi->ext, array('mp4','m4v','ogg','ogv','mpg'))) { $src = str_replace('{src}', $gi->url, $markup); $items[] = ['type' => 'inline', 'src' => $src]; } // wrong file type else if (!in_array($gi->ext, array('png','jpg','jpeg'))) throw new WireException("Unallowed Fileformat $gi->ext for magnificPopup Gallery"); // any image with youtube video source in description else if (strpos($gi->description, 'youtube')) { $oembed = getVideo($gi->description); if ($oembed) { // nocookie source used $items[] = ['type' => 'iframe', 'src' => $oembed->frameUrl]; } } // image else { $src = $gi->url; $copyFileName = strstr($gi->filename, $gi->ext, true) . '1200x0.' . $gi->ext; list($width, $height) = getimagesize($gi->filename); if ($width > 1200) { if (!file_exists($copyFileName)) { $files->copy($gi->filename, $copyFileName, ['limitPath' => true]); $imageSizer = new ImageSizer($copyFileName); $imageSizer->resize(1200, 0); } $src = str_replace($config->paths->root, '', $copyFileName); } $items[] = ['title' => $gi->description, 'src' => $src]; } } $gallery = [ 'gallery' => ['enabled' => true], 'type' => 'image', 'midClick' => true, 'mainClass' => 'mfp-lightbox-wrapper', 'items' => $items, 'tClose' => 'Schließen (esc)' ]; $gallery = json_encode($gallery); $galleries .= "$('.mfp-open-$gp->id').magnificPopup({$gallery})\n"; } $page->_galleriesJS = "<script> $galleries</script> "; }
  50. 1 point
    For simple json outputs, you can use WireArray::explode and json_encode() or wireEncodeJSON() methods https://processwire.com/api/ref/wire-array/explode/ $myPages = $pages->find('template=basic-page'); // extract required fields into plain array $data = $myPages->explode(['title', 'created']); echo wireEncodeJSON($data);
  • Create New...