Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation since 09/20/2021 in all areas

  1. This week I've been focusing on the dev branch and some low level code optimization, especially as it relates to the PW boot process, translating URLs to pages and identifying the page, language, URL segments, page numbers, etc. from the request URL. I'm breaking down much of the logic (currently in the ProcessPageView module) into more focused parts that can become part of PW's $pages API, increasing reusability of related code. (Don't worry, this won't affect any existing hooks). At the same time, I'm looking for opportunities for optimization and performance improvement, and have already found a few. For instance, the LanguageSupportPageNames module introduces overhead into some page finding operations and there's good improvement potential there, among others. I'm pretty much still in the middle of it all though, so am going to hold off on committing any of this to the dev branch until it's further along. But since we've got a quiet commit log this week, I just wanted to keep you up-to-date. Hopefully some of these fairly significant updates will be stable enough to commit to the dev branch next week. By the way, these updates will also enable the SessionAllow module (from last week) to be configurable by page, as PW will now identify the requested page before starting the session. More soon. Have a great weekend!
    30 points
  2. All the updates I mentioned last week are committed on the dev branch today, and it's quite a lot of new code and revised code. There's enough here to justify a couple of version bumps, but I'm leaving it at 3.0.185 temporarily because the ProcessWireUpgrade module will see the version change and some people might upgrade automatically. Because there's so much that's been rewritten, refactored, added and changed here, I'd like it to marinate for a week on the dev branch before it triggers any upgrade notifications. Our dev branch tends to be very stable, and this is one week where there's enough new code that I don't want to call it as-stable-as-usual just yet (though it might very well be). In addition, it's also not totally finished as there's still some redundant code to be removed and stuff that needs to be moved around a bit, though everything should be fully functional as-is. I am running it here on the processwire.com site without any issues, so chances are that all is good, but I always like to be cautious. Below is a summary of what's new and changed. It's a bit technical, and there's nothing here that's all that important to know about, but whether you read on or not, just know that the core is getting even better and faster with updates like these. The core PagePaths module has been refactored and has multi-language support. Previously it only worked on single-language sites. Now multi-language sites can take advantage of potentially significant performance improvements offered by this module. This is one module that is not installed by default, but it's definitely worth installing: Modules > Core > PagePaths. The core LanguageSupportPageNames module has been refactored. Assuming I did it well, you shouldn't notice any difference other than that it's faster. For instance, one of the changes is that it drops its old indexes on the pages table and re-creates them in a different way. I discovered some situations where finding pages by multi-language path was resulting in full pages table scans. Using MySQL “explain” statements I found I could prevent that by reversing the order of the columns in the language-specific indexes, preventing the full table scan and making it many times faster. This could make a big difference on large multi-language sites, but is less likely to be noticed on smaller sites. The LanguageSupportPageNames module also gained a new configuration setting that lets you specify what should happen when a page is accessed at a language it's not available in: throw a 404 or redirect to the default language. The core PagePathHistory module has been refactored. It has a powerful new getPathInfo() method, though it's primarily of interest for internal core use. A new PagesRequest class has been added to the core and it can be accessed from $pages->request(). It primarily focuses on one hookable method: $pages->request()->getPage(). The method accepts no arguments but it analyzes the current request, identifies the page to render, and returns it. Previously this logic was in the ProcessPageView module. The benefit of this method is that you can now determine the page to render much earlier, like during the boot process. Previously the current page wasn't identified until after PW booted and the ProcessPageView module loaded. This will enable [for example] a module such as SessionAllow to decide whether or not to allow sessions based on what page was requested. In addition, this method is hookable, so you could have a module that adds its own logic to identify or change the page that should be rendered. A new PagesPathFinder class has been added to the core and can be accessed from $pages->pathFinder(). Like the PagesRequest class, this new class primarily focuses on one method: $pages->pathFinder()->get($path). The given $path can contain any page path, optionally containing language prefix, URL segments, pagination numbers, or even a previously named version of the path. It will find and validate that path and return an array of information about it. PagesPathFinder does its job very quickly. In fact, it's about 10 times faster (in testing/timing locally) than PW could previously identify this information using existing methods. PagesPathFinder will also take advantage of the PagePaths and/or PagePathHistory modules when appropriate, if they are installed. Below is an example of what the return value would be for path /es/hello/bar/baz/page3 where /es/ is the language prefix, /hello/ is the actual page, /bar/baz/ are the URL segments and /page3 is the pagination number segment. It analyzes everything out and returns a 200 "ok" response if the path is good, or in this case, it's returning a redirect because it detected a Spanish URL with English page name and pagination prefix, and it's suggesting a redirect: $info = $pages->pathFinder()->get('/es/hello/bar/baz/page3'); [ 'request' => '/es/hello/bar/baz/page3', // path that was requested 'response' => 301, // one of 200 (ok), 301 (permRedirect), 302 (tempRedirect), 404 (pageNotFound), 414 (pathTooLong) 'type' => 'permRedirect', // ok, permRedirect, tempRedirect, pagePathError, pageNotFound or pathTooLong 'errors' => [], // array of error messages indexed by error name 'redirect' => '/es/hola/bar/baz/pagina3', // suggested path to redirect to, blank otherwise 'page' => [ // info about page that was matched 'id' => 1237, 'parent_id' => 1232, 'templates_id' => 12, 'status' => 1, 'name' => 'hello' ], 'language' => [ 'name' => 'spanish', // name of language detected 'segment' => 'es', // segment prefix in path (if any) 'status' => 1 // language status where 1 is on, 0 is off ], 'parts' => [ // all the parts of the path identified [ 'type' => 'language', 'value' => 'es', 'language' => 'spanish' ], [ 'type' => 'pageName', 'value' => 'hello', 'language' => 'default' ], [ 'type' => 'urlSegment', 'value' => 'bar', 'language' => '' ], [ 'type' => 'urlSegment', 'value' => 'baz', 'language' => '' ], [ 'type' => 'pageNum', 'value' => 'page3', 'language' => 'default' ] ], 'urlSegments' => [ // URL segments identified in order 'bar', 'baz' ], 'urlSegmentStr' => 'bar/baz', // URL segment string 'pageNum' => 3, // requested pagination number 'pageNumPrefix' => 'page', // prefix used in pagination number 'scheme' => 'https', // blank if no scheme required, https or http if one of those is required 'method' => 'pagesRow', // method(s) that were used to find the page ] While you might never need to use this method yourself, ProcessWire now uses it on every request. And now that this logic is isolated from ProcessPageView and has a dedicated $pages API, it's much more open and we can, for example, more easily apply tests to this logic. I've covered a few updates here but there's more if you feel like digging in the commit log https://github.com/processwire/processwire/commits/dev. Thanks for reading and have a great weekend!
    26 points
  3. It took a little more time this week to wrap up what I was finishing last week (and the week[s] before). But I think it's now at a good spot to move on to something else, and so I started with some Repeater and RepeaterMatrix updates. In Repeater, a new feature was added that's been requested for awhile: the ability to add items anywhere you choose. Previously you could do it only by adding items to the bottom, and then drag them in place. Now you can click insert before/after [icons] in each repeater item header and it will add the new item in place. It is also depth-aware. This is something that I think will also be useful especially for people using repeaters for page builder type contexts. (Note: the feature does not [yet] work if you have all Ajax features turned OFF in your repeater settings). There's a GIF screencast below that shows you how it works. You can click the "insert before" or "insert after" actions and it inserts a new item in place. Alternatively, if you hover either action for a second, it'll show you where it's going to insert an item and you can click either the the item, or the action, to complete the insertion. There's still likely some optimizations and improvements to make in the JS here but so far it seems to be working well. (I made this as a GIF but for some reason IP.Board won't accept it, so here's a YouTube embed instead): Everything in Repeater also gets inherited by RepeaterMatrix, so you'll find this feature there too. But it's not fully functional there just yet. That's because RepeaterMatrix items also have a "type", so I'm working on a new version of RepeaterMatrix that lets you select a type once you've chosen where to insert the item. Another related feature in progress in RepeaterMatrix at the same time is a dropdown/select option for choosing what matrix type you want to add for items. This is an alternative to the current list of links that appears at the bottom. The dropdown also gives you the option of having groups of related types. More on that soon, potentially next week. Thanks for reading and have a great weekend.
    21 points
  4. This week I kept working on what's been in progress the last couple of weeks. That wasn't really the plan, as I was hoping to move on to other parts of the core. But I found it a took a lot of time to adjust everything to the new code and classes, and to refactor and remove other chunks of code that could either be simplified or removed. So these last few weeks of updates took a lot more time than I expected, and it's one of those things where once I got into it I felt I had to keep working until it was done as well as it could be. That meant getting pretty deep into some core logic. So in hindsight I'm slightly regretting refactoring so much code without major short-term benefits that can make more interesting reading here. And there are perhaps some short-term drawbacks in potentially introducing new bugs, as goes with any new code. But that's how it is sometimes. The good news is that it's a definite improvement in quality and I have no doubt there will be long term benefits especially in terms of improved performance and maintainability. But in any case, I'm glad to be wrapping up these particular updates so that I can move on to other parts of the core and Pro modules, and hopefully I'll have more interesting stuff to write about next time. One small addition you might find useful in these updates is that you can now identify the closest matching page when a 404 occurs. Maybe you want to provide a hint to users that land on a 404 as to what page they might have been looking for. Now you can do this in your 404 page template file: $p = $pages->request()->getClosestPage(); if($p->id > 1) { echo "<p>Were you looking for <a href='$p->url'>$p->title</a>?</p>"; } Like last week I'm not bumping the dev branch core version just yet because I don't want to trigger any upgrade alerts that might prompt people to upgrade immediately. I'd rather focus more on testing and leave these updates to those that are interested in that testing, helping to track down any issues. Thanks in advance for your help with testing these updates. Likewise, thanks for reading, I hope you have a great weekend!
    20 points
  5. @AndZyk Here's a new fieldtype I have been working on for the past weeks. These draggable blocks are defined by developer using custom templates, and they are fully stylable. The module is quite far from being production ready, but I wanted to share this, since I think this might be something you're looking for 😉 Proper teaser video will come after I reach the first milestone in development process.
    18 points
  6. Repeater Easy Sort Adds a compact "easy-sort" mode to Repeater and Repeater Matrix, making those fields easier to sort when there are a large number of items. The module also enhances Repeater Matrix by allowing a colour to be set for each matrix type. This colour is used in the item headers and in the "add new" links, to help visually distinguish different matrix types in the inputfield. Screencasts A Repeater field A Repeater Matrix field with custom header colours Easy-sort mode Each Repeater/Matrix item gets an double-arrow icon in the item header. Click this icon to enter easy-sort mode. While in easy-sort mode: The items will reduce in width so that more items can be shown on the screen at once. The minimum width is configurable in the field settings. Any items that were in an open state are collapsed, but when you exit easy-sort mode the previously open items will be reopened. You can drag an item left/right/up/down to sort it within the items. The item that you clicked the icon for is shown with a black background. This makes it easier to find the item you want to move in easy-sort mode. You can click an item header to open the item. An "Exit easy-sort mode" button appears at the bottom of the inputfield. Configuration In the field settings for Repeater and Repeater Matrix fields you can define a minimum width in pixels for items in easy-sort mode. While in easy-sort mode the items will be sized to neatly fill the available width on any screen size but will never be narrower than the width you set here. In the field settings for Repeater Matrix you can define a custom header colour for each matrix type using an HTML "color" type input. The default colour for this type of input is black, so when black is selected in the input it means that no custom colour will be applied to the header. Exclusions The easy-sort mode is only possible on Repeater/Matrix fields that do not use the "item depth" option. https://github.com/Toutouwai/RepeaterEasySort https://processwire.com/modules/repeater-easy-sort/
    16 points
  7. There's a couple things that made me think this part of the core could be better (and nothing related to middleware). First is that PW didn't originally support multi-language URLs, and so the LanguageSupportPageNames module was built to hook in and add support for that. There are benefits (performance, simplicity, etc.) to having that logic lower-level in the core and part of the same logic that identifies non-multi-language URLs. So that's something I've been interested in for a long time, but it was always more than I wanted to get into. The other thing is that I was working on that SessionAllow module and found it was a real drawback not to be able to know what Page was requested before deciding on things like whether to allow a session or not. Granted, we can still know the request URL before we know the Page, but it just seemed a lot more flexible for the core to know the requested Page much earlier in the boot process. That way, we can do things like configure whether sessions are allowed on a per-template basis, where such an option seems to make the most sense. Another example is 404 pages—maybe we don't need a session on a 404 page. But without knowing whether the URL will resolve to a Page or not, we didn't have that choice. Following these updates, we will. Lastly, I just like to revisit the core logic for things and improve it when/where possible, which helps to keep it fresh on the mind. But I don't like to get into replacing this kind of major core code when it'll soon be merged to the master, as this is the kind of stuff that needs more testing over a longer period of time. So with a comfortably stable master version available right now, it seemed like a good time to work on this.
    13 points
  8. Field that stores one or more references to ProcessWire pages with additional data in field context. Values are editable via page edit modal of the referenced page provided from the field if module AdminPageFieldEditLinks is installed and "Enable link to create new pages?" is checked in field settings. Requirements: AdminPageFieldEditLinks >= 3.1.4 https://github.com/kixe/FieldtypePageContextData https://processwire.com/modules/fieldtype-page-context-data/ Use case example: The planning of the Tonmeistertagung in the CCD (Congress Center Düsseldorf) from November 3rd, 2021 to November 6th, 2021 is in the finalization phase. The conference consists of a conference part and an exhibition. The planning is done via a separate frontendless PW instance. There, all companies (pages) that are active at various events are kept in a pool. Changes (address, logo) can always be done there. For the exhibition of the current conference in November, the exhibitor-companies (pages) are selected via a page reference field. A stand number must now be assigned to each selected company (page). We had originally solved this using the Profield FieldtypeTable. However, this had the disadvantage that each entry again made all companies available for selection and did not recognize which were already selected in a previous table row. The new field type now allows the value (company's stand number) to be assigned to a Company (page) in context to a specific Pagefield living in a specific page. https://tonmeistertagung.com/en/exhibitors/exhibition/
    12 points
  9. Right - as part of my efforts to show off more of the work we've done recently, here's a site we launched earlier this year. On The Record are a not-for-profit that specialise in oral histories and creative media. We've done a few nice projects with them ( A Hackney Autobiography was a lovely project we did with them in our pre PW days). A creative design was very important to them as well as being accessible and usable. There's not too much bespoke backend coding going on. We needed to provide them with a way of easily adding audio and video files but that was mostly done using normal fields and a modified version of Ryan's TextformatterVideoEmbed module adapted for use on plain text fields. Apart from that, it's just the usual supects for extra modules: ProCache LoginPersist and Macrura's ProcessDocumention module which we normally use for provide help pages in the admin area. The front end is pretty much bespoke but with a few components lifted from various places; looks like we used Bootstrap grid for one. It's another site where we used CSS filter properties to apply a consistent look and feel to images the client uploads. I think it looks nice anyway and the client is very happy with it and took to using the PW admin with no problems.
    9 points
  10. @AndZyk, I don't think this is entirely accurate. Maybe things have changed since I last read the thread but below is the quote from @ryan with respect to his thoughts on a layout / page builder: https://processwire.com/talk/topic/25129-weekly-update-–-12-february-2021/ So, it is not a matter of lack of interest but more about 'lack of expertise', albeit with willingness to support it on the PHP (ProcessWire) side 😄. By the way, I could have offered to take lead on this but until a certain module is released (getting very close now! 😉), I don't have much time for anything else 🙂.
    8 points
  11. I have slowly but surely been working on an IndieAuth module for ProcessWire. IndieAuth lets you sign in to applications using your domain name and grant access to read/write to your site. I initially set up a version of this in 2016. My understanding of IndieAuth was limited at the time and it really only let you use IndieAuth to sign into your own site. There are some interesting possibilities there, but it was premature. (I'm making this separate thread to clearly separate them.) So what does this module actually do? 1. Authentication: When you visit a site like indielogin.com and enter your domain name, you will be taken to your ProcessWire admin area to approve the request. If you approve the request, you will be returned to the site and logged in as your domain name. 2. Authorization: When you visit an application like Quill, it needs to also get your permission to post to your site. You will be taken to your ProcessWire admin area to approve the request and the scopes that the app is requesting (create, update, delete, etc.). If you approve the request, you will be returned to the app, logged in as your domain name, and the app will have an access token for your site. Features Browse the applications you have granted access tokens to. See when each one was granted, last used, and will expire. Revoke any application’s access tokens Set the default expiration period for new access tokens. The initial default is 14 days. During authorization, confirm and change the scopes granted to the application. For example, an app may request “create” and “delete” scopes, but you can grant only “create.” During authorization, you can also choose to grant an access token with no expiration Try it out! I have been testing the new module and think it is almost ready to release in the ProcessWire modules directory. I would like to have a few more people beta test it and provide feedback first, though. If you’re interested, follow these steps: Download ProcessWire IndieAuth from Github and follow the instructions there to install it Test Authentication: visit indielogin.com and enter your domain name. Follow the prompts to authenticate and you should end up back on indielogin.com with a success message. Test Authorization: visit Quill and enter your domain name. Follow the prompts, noting the additional fields for scopes and expiration. After successfully authorizing, you should end up back on Quill with a success message. Go back to the ProcessWire admin area of your site. Visit Access > IndieAuth and you should see an entry for the access you just granted to Quill. Optionally test access tokens To test access tokens, you will need a module that accepts them. I have set up a minimal Micropub module for that purpose. All it does currently is verify the access token and shows a debugging message indicating the request was received. Follow the instructions to install the Micropub module. Go back to Quill and try to post a short note to your site. Quill is expected to respond with “Something went wrong,” but scroll down and the section labelled Micropub response should show “Debugging: Micropub request received.” If you see that, it means the Micropub module successfully received and verified the access token! The Micropub module will eventually be fully functional so you can publish to your site using a variety of Micropub clients, but that is a separate project that is going to take me some more time. I wanted to get the IndieAuth module out there instead of waiting to release both at the same time. More information If you’re interested in more details on IndieAuth, I recommend “OAuth for the Open Web” by Aaron Parecki. If you are interested in implementing IndieAuth in your project, see the IndieAuth specification. Originally published: https://gregorlove.com/2021/10/indieauth-for-processwire-development/
    7 points
  12. @Ivan Gretsky Hooks have already been added for this, and I think they were present in the dev version I posted in the ProFields board a few months back? I don't remember for sure, but I'm trying to make everything hookable so that people can modify the output as needed, and will keep looking for additional opportunities for that as I build in more related features. @teppo Yes there's a renderAddMatrixItemLink() hookable method for this, and it renders a link for one matrix item type, and gets called for each of them. So you could change the output to be anything you want. This is already present, but with the changes being made, chances are another hookable method will be added related to this. @Pete If I understand correctly, this is already there. See the "Matrix types to allow for adding new items" on the "Input" tab when editing your matrix field. This can be configured in template context which enables you to specify some types for one template and other types for another, etc. @mlfct Thanks, I was able to reproduce that here too and have pushed a fix on the dev branch.
    6 points
  13. This fieldtype and inputfield bundle was built for storing measurement values within a field, rendering them in a variety of formats and converting them to other units or otherwise modifying them via the API. The API consists of a number of predefined functions, some of which include... render() for rendering the measurement object, valueAs() for converting the value to another unit value, convertTo() for converting the whole measurement object to different units, and add() and subtract() for for modifying the stored value by the value (converted as required) in another measurement. In the admin the inputfield includes a checkbox (which can be optionally disabled) for converting values on page save. For an example if a value was typed in as centimeters, the unit was changed to metres, and the page saved with this checkbox selected, said value would be automatically converted so that e.g. 170 cm becomes 1.7 m. A simple length field using Fieldtype Measurement and Inputfield Measurement. Combination units (e.g. feet and inches) are also supported. Please note that this module is 'proof of concept' at the moment - there are limited units available and quite a lot of code tidying to do. More units will be added shortly. See the GitHub at https://github.com/MetaTunes/FieldtypeMeasurement for full details and updates.
    6 points
  14. Hello, I am in need of a ProcessWire Developer to update my existing website by adding an additional landing page for a new product. The content and layout will be provided for you and we would need it implemented into the website. Please message me if you have experience developing websites in ProcessWire and are interested in this project. This project will be less than one month approximatley. Best, Roisin
    6 points
  15. See the attachment for the job posting. Contact information is in the posting. 2021-10 Lead Web Programmer.pdf
    6 points
  16. Great to see those core things evolving. Someone has to look after them. And we all know who that is))
    5 points
  17. ProcessWire definitely shines in the security department and the login page does have throttling. I don't know what your threat model is but usually sites have to deal more with bots than individual bad actors, but that depends on the purpose/use for your site. I've built many PW sites over the years and not one has ever been compromised. In my opinion, your biggest threat as far as hackers go would be a person that came into possession of one of the users' login credentials or much more common automated attack scripts with other vectors like requests containing data that the code isn't prepared to handle, or MySQL injections in your forms. Here are some additional thoughts on your login URL. If you don't want bad actors to know the login URL then it should be changed it to one that is practically unguessable like /clientname-admin-login or something easy to remember but hard to guess. Consider that your /processwire login URL is not unknowable because it's the default. Someone intent on getting to the login page or knowing what CMS you are using could analyze the markup and see that your images are being served from /site/assets/files/{page id} and any assets like JS may be served from the templates directory like /site/assets/templates/scripts- the file structure consistent across ProcessWire sites. When you load a page on a ProcessWire site, the server returns the request with the header "x-powered-by: ProcessWire CMS" unless you've disabled it and that will let someone look up what the default URL would be. Using /processwire in JS isn't really the issue. All that aside, it's not automatically a disadvantage to have your login URL known. Most of the PW sites that are built probably keep /processwire. My take is that if you have the opportunity to change it and reduce the chance non-authorized people would see the login page to begin with, why not? If this were my project I would change the login URL and create a dedicated /api page in the admin then use a hook to hide it in the page tree on render for non-superusers. It would keep the main site tree tidy as desired, allow for a clean semantic URL to work from, and not hard code in references to a part of the website that isn't content-related. If you want to take security against bots into consideration I would look into adding some bot blocking rules to your .htaccess file, I use 7G Firewall. Bot blocking prevents bot HTTP requests from requiring ProcessWire to boot up, analyze the URL, determine that it doesn't exist, and then serve the 404 page- this improves performance by reducing server load. Blocking bots also takes care of many other automated malicious requests as described above. I kinda blew this open a bit, but I think your question about security being limited to hackers and the login page could benefit from a wider scope.
    5 points
  18. Session Viewer is a module for ProcessWire to list session files and display session data. This module is helpful to display the session data of a specific session or to kick out a logged in user by simply delete his session file. After installation the module is available in the Setup menu. The following conditions must be met for the module to work properly: Session files Session data must be stored in session files, which is the default way in ProcessWire. Sessions stored in the database are not supported by this module. The path to the directory where the session files are stored must be declared in the ProcessWire configuration which is by default: site/assets/sessions. Serialize handler In order to transform session data easier back to a PHP array, the session data is stored serialized. PHP offers a way to declare a custom serialize handler. This module supports only the default serialize handlers: php, php_binary and php_serialize. WDDX was dropped in PHP 7.4.0 and is therefore not supported by this module as well as any other custom serialize handler. Which serialize handler is actually used you can find out in the module configuration which is available under Modules=>Configure=>SessionViewer. Session data The session data can be displayed in two different ways. PHP's default output for arrays print_r() or by default for this module nice_r() offered on github: https://github.com/uuf6429/nice_r. There is a setting in the module configuration if someone prefers print_r(). Apart from the better handling and overview of the folded session data the output of nice_r() looks indeed nicer. Links ProcessWire module directory github.com
    4 points
  19. ProcessWire is an excellent framework for building just about anything, with great tools for permissions, input fields, and creating data structures. With the Combo and Table profields, it's possible to handle just about any data. These fieldtypes show the potential of ProcessWire to handle SQL tables in a more 'traditional' SQL table format, which leads to one area I wonder might have potential for a new feature. In addition to ProcessWire, I also do some work with ASP.Net Core, and one of the nice features it has is the ability to work with existing SQL databases, so that you can either build your models in the framework, or use existing SQL Tables. While working with any SQL data is possible in ProcessWire, it's a lot more hands on, with less built-in support. InputFields and FieldTypes are separate, and there's no reason why an inputField can't be used for data input for any kind of data, and indeed there are some modules that use inputFields to edit custom table data. What would be an amazingly useful addition to ProcessWire would be a module that allows mapping of inputFields to fields in an arbitrary SQL table without modifying the structure of the table itself. This is something the open source Directus project does by using metadata tables to store data about to display input for existing SQL tables, without touching their structure, but documentation isn't great for that project. I think ProcessWire has all the plumbing in place to enable this kind of functionality, and the Combo fieldtype gets pretty close, but still requires the combo table records to be associated with a ProcessWire page. Obviously, existing SQL tables won't automatically map to pages, which means directly accessing them on the front-end via URL automatically isn't possible, but often this isn't required as they may be for backend use only, or for consumption within a ProcessWire page. The recent support for URL/Path hooks though, means that if there is a need to directly access existing SQL on the front end via URL, it should be possible to create a hook to do so. I think adding the ability to create backend data entry for existing SQL tables would fully complete the ProcessWire philosophy of getting out of your way and not making assumptions about your content. It's currently already best of class in terms of doing this regard to front end presentation, but it's still a bit opinionated about data structures at the back end. This is absolutely fine if you're building a web app from scratch, and works really well in most cases, but there are times where being able to quickly incorporate existing data structures would be useful. To be clear, this isn't a replacement for the existing pages model, as that would be a huge and unecessary task to completely re-engineer ProcessWire, but rather an enhancement that can sit alongside all the good stuff that's already in ProcessWire so that it's possible to get ProcessWire to handle existing SQL data tables on the backend as neatly as it already does with its own data.
    4 points
  20. This is a bit vague, but Tracy can sometimes help identify slow requests. You could also look into browser dev tools (just in case it's some specific resource that's slowing queries down), slow database queries (MySQL slow query log if it's available, though PW debug mode tools can also provide plenty of insight into these if you happen to run into a slow query while browsing the site), and perhaps even Apache logs to identify which specific requests are taking a long time. If you have access to ProDevTools package, I can highly recommend Profiler Pro. We recently used this to debug a module that was causing issues due to hooks, and for that purpose it was brilliant. On the other hand: if said slowdown is indeed quite random, one potential culprit would be LazyCron. I would likely start by checking if any local code snippet or module is triggering a slow task via Lazy Cron. I've ran into that many, many times.
    4 points
  21. I'm with you in that I like the look of Tailwind but I've never quite found the right project to justify using it. These days I rarely use a framework at all. Support for flexbox and grid has meant that a lot of the advantages of using a framework don't apply any more. Browsers are a lot more consistent these days as well, so there's not as much need for polyfills and resets and vendor specific tweaks that might have been baked in to a framework. My starting point for a project is a single CSS file that has some minimal styles and utilities in that I'm pretty sure I'll always need. Originally that was based on Wing css but I've tweaked and added to it over the years. I then have other css files for components that I've used over the years - so if I need an off screen menu for example I have one that I can reuse and adapt. The same applies to javascript; In the old days (a couple of years ago anyway) I would have just included jQuery by default in a project but now I just have a few native javascript functions I can include when I need to. Most of the work we do is pretty bespoke stuff so this works better for us. I imagine that if you were doing lots of sites that were fairly similar then a framework might be useful. One situation we would use a framework for is when we need to do an admin interface (we a did a great project that had a SMS bot the client could manage for example). For that we've used ModularAdmin which is based on Bootstrap 4 (and which hasn't been updated for a few years so probably not that useful a link). Now I'm essentially a solo dev, so bespoke code is easy to manage. If you're part of a larger team (or looking for a job) then I bet having decent documentation and consistency is much more important so learning a framework is probably a smart move.
    4 points
  22. OK. STEP #1 Create a file, e.g admin.js and save it to your preferred location. In this example, we have saved it at site/templates/scripts/admin/admin.js STEP #2 Add either of the below JS code in admin.js (you don't need both; choose one or the other). jQuery version: $(document).ready(function () { // #wrap_Inputfield_list_price is the ID ProcessWire will assign to your list_price field's wrapper (an li element). // you can confirm this by examining the markup around your 'list_price' input in dev tools. // Inputfields is a utility files that ships with ProcessWire. // more details: inputfields.js - JS specific to behavior of ProcessWire Inputfield forms. Inputfields.focus("#wrap_Inputfield_list_price") }) Plain JavaScript version: const InputfieldAdminScripts = { focusAnInputfield: function (inputfield_id) { const inputfieldToFocus = document.getElementById(inputfield_id) // if we found the element,focus it if (inputfieldToFocus) { inputfieldToFocus.focus() } }, } // DOM ready document.addEventListener("DOMContentLoaded", function () { InputfieldAdminScripts.focusAnInputfield("Inputfield_list_price") // this will also work here. you can use it instead of the above // Inputfields.focus("#wrap_Inputfield_list_price") }) STEP #3 Inside ready.php, add this code to load admin.js. You can modify this to only load under certain conditions if you wish. <?php namespace ProcessWire; $this->addHookBefore('AdminTheme::getExtraMarkup', function (HookEvent $event) { $config = $this->wire->config; $url = $config->urls->templates; $config->scripts->add($url . "scripts/admin/admin.js"); }); Please note that in Chrome (and maybe FF as well), if you have your dev tools opened and the cursor currently focused on it, the inputfield might not seem to be focused, but it actually is. 😀
    4 points
  23. Hi @ryan, does this have an impact on init.php and ready.php? For instance, will init.php still not be aware of the current page? Can $pages->request()->getPage() inside a template file be a replacement for ready.php? Thanks for the awesome updates!
    4 points
  24. Adapting a post Ryan made in the Repeater Matrix support forum: In /site/templates/admin.php, before the line... require($config->paths->core . "admin.php"); ...add the following... if($page->process == 'ProcessPageEditImageSelect') { // The page ID that is open in Page Edit $edited_page_id = (int) $input->get->edit_page_id; // The page ID that contains the CKEditor field // This is where PW will look for images by default $cke_page_id = (int) $input->get->id; // If the edited page is not the same as the CKEditor page if($edited_page_id && $cke_page_id && $edited_page_id != $cke_page_id) { // Get the CKEditor page $cke_page = $pages->get($cke_page_id); // If the CKEditor page is a particular Repeater field page // Substitute the name of your Repeater template if($cke_page->template == 'repeater_your_repeater_template') { // Set the page ID where you want PW to look for images $input->get->id = $edited_page_id; } } }
    4 points
  25. v0.0.3 saves database value in terms of base units. Selector fieldname.magnitude then operates consistently regardless of what units are chosen - selecting values in terms of base units. Thanks for the tip @kongondo
    3 points
  26. OK - I did this and it seems to work OK. @teppowas rather quick off the mark with the PW weekly report - I still have to add a lot of units and do some tidying (and remove debugging lines in case people don't have Tracy!). I will also add some notes about what I learnt doing this as the existing tutorials (such as @bernhard's) don't seem to cover fieldtypes which use the database. Support thread started at
    3 points
  27. Hey @Pete! You can limit types by template out of the box - look at the template overrides. There is a nice module by @Robin S that can do more than that. Is you need to restrict in part of the page tree, you will need to reach for hooks. You can look at the ones Robin uses in his module.
    3 points
  28. @bernhard It might be something to do with your server's root certificate. Have a look at https://letsencrypt.org/docs/dst-root-ca-x3-expiration-september-2021/ You can check if your root cert has expired or not by checking it here https://www.ssllabs.com/ssltest/ Update: I just ran your domain name and it looks like your DST root cert expired (per Let's Encrypt article above)
    3 points
  29. IMPORTANT ALERT!!! Hi everyone, I had a site today that was loading really slowly for the first view for guest users. Turns out the https://restcountries.eu API that this module uses to determine if the user is in Europe is down at the moment, so loading of the site was waiting on a timeout from the failed call to the API. Now obviously the correct thing to do is for this part of the module (if enabled) to make this call asynchronously via AJAX so that it doesn't impact the loading of the site. The logic also needs to be updated so that the banner is also displayed if it can't find the visitor's region. At the moment it only works as a fallback if it can't get their IP address, which is obviously not very useful if the APIs are down.
    3 points
  30. @PascalKonings, the suggestion from @Zeka is probably the way to go, but in case you do want to stick with image tags you can set them dynamically in a hook in /site/ready.php: // Dynamically set the selectable tags for an images field $wire->addHookAfter('InputfieldImage::renderReadyHook', function(HookEvent $event) { /** @var InputfieldImage $inputfield */ $inputfield = $event->object; // The images field $field = $inputfield->hasField; // The page that the field is on $page = $inputfield->hasPage; // Only for a specific images field if(!$field || $field->name !== 'your_image_field') return; $config = $event->wire()->config; $js_name = "InputfieldFileTags_$field->name"; $data = $config->js($js_name); // Set the tags however you like, using $page if needed $data['tags'] = [ 'carrot', 'pumpkin', 'cauliflower', ]; $config->js($js_name, $data); });
    3 points
  31. A good feeling to have! Thank you for your tireless improvements to PW!
    3 points
  32. Basically <?php namespace ProcessWire; // create field $field = new Field(); $field->name = 'my_field'; $field->label = 'My Field'; $field->type = 'FieldtypeText'; // save field wire('fields')->save($field); // get field $field = wire('fields')->get('my_field'); // Create fieldgroup $fieldgroup = new Fieldgroup(); // if you want to edit fields in this field group via admin panel, name need to be same with template name $fieldgroup->name = 'my_template'; $fieldgroup->add('title'); $fieldgroup->add('body'); $fieldgroup->add($field); // save fieldgroup wire('fieldgroups')->save($fieldgroup); // get fieldgroup $fieldgroup = wire('fieldgroups')->get('my_template'); // Create template $template = new Template(); $template->name = 'my_template'; $template->label = 'My Template'; $template->fieldgroup = $fieldgroup; // save template wire('templates')->save($template); // get template $template = wire('templates')->get('my_template');
    3 points
  33. Another approach I use on my local dev environment, for completely unrelated projects on different hosts, is to simply symlink the 'wire' folder. My Setup/Structure: /www <-- my localhost root (I'm using Laragon). /processwire <-- folder dedicated to ProcessWire projects. /wire <-- the ACTUAL location of the wire folder that the symlinks point to. /project_a <-- each separate project (treat this folder as the web root: http://project_a.localhost/ ) /site <-- the project's ProcessWire /site folder /wire <--- this is a SYMLINK to the /www/processwire/wire folder /.htaccess <-- the ProcessWire .htaccess file. /index.php <-- the ProcessWire index.php file. /...etc <-- any other files that you'd put in the web root of a project (robots.txt etc). /project_b <-- same folder/file structure as above When I want to update the ProcessWire version, I just download it and copy the 'wire' folder over into /www/processwire (I actually rename the old folder, copy over the new and check everything works before deleting the old folder). Adding a New Project My process for adding a new project, we'll call it 'project_c', is then: Create the project in the ProcessWire projects folder: /www/processwire/project_c Create a local url for the project (http://project_c.localhost/) and point it to the newly created folder above. In the 'project_c' folder, unpack a copy of ProcessWire (the same version as the current shared wire folder for simplicity). In the browser visit http://project_c.localhost/ and run the installer as usual (& create the DB). Once installed successfully, delete the /www/processwire/project_c/wire folder (or rename it and delete later if it all works ok) and create a symlink to the shared 'wire' folder. The advantage of this for me, is that it does away with the need for naming the site folders 'site-project_a', 'site-project_b' etc.
    3 points
  34. Thanks for the suggestion. I'll keep it in mind but for now will leave the interface as it is for a couple of reasons: The intention with this module is just to create a temporary mode to activate when doing a drag sort, and leaving the repeater interface as per the core default at other times. At this point I don't want to get into making broader changes to the repeater interface: hacking controls into the inputfield header (the core doesn't make this easy to do), setting a default view mode, storing the view mode in a cookie, etc, like what is done with image fields. I'm predicting that users will first identify the item they want to drag with the repeater field in its normal mode. When easy-sort mode is activated the repeater items move quite a bit from their original position, and it's a feature of this module that the item you want to drag gets identified with a black background so it's easier to locate. This requires a button per repeater item rather than a single button per repeater field. Fixed in v0.1.1. Although personally speaking I gotta say... I wish @ryan would drop those ancient legacy themes from the core because it's a real hassle for module developers to support multiple themes. The Uikit theme has been the default standard for several years at this point and it's the only theme that's likely to get attention and further development going forward, so PW users should get on board with it. I only test my modules in AdminThemeUikit but will consider compatibility fixes for legacy themes on a case-by-case basis.
    3 points
  35. Nice! I'm not an UI expert but personally I'd find it more intuitive to have a grid/list switch in the inputfield header similar to the image field: Not sure, just wanted to share that idea 🙂
    3 points
  36. Guys, I found the method that I meant. It is not the field=fieldname URL that Bernhard mentioned. A long time ago I also tried to tackle a similar task, where I wanted to remember and focus the last edited field after you saved a page. I opened a github issue for this and later Ryan added some methods that he mentioned in a reply, that achieve the behaviour I and @Peter Falkenberg Brown want. Just add a #focus-field_name to the URL when the page is saved and the redirect is executed and the field gets focused. An example URL looks like https://domain.com/processwire/page/edit/?id=1056#focus-subheadline and would focus the field named "subheadline". I am a fan of using native methods that ProcessWire offers, over custom ones. But what the others wrote is also viable. I will provide a hook, just have to test it out, but it goes somewhat like this: <?php namespace ProcessWire; $this->addHookBefore('ProcessPageEdit::processSaveRedirect', function (HookEvent $event) { $url = $event->arguments(0); $page = $event->object->getPage(); if ($page->template == "book_sales" && !$page->isTrash()) { if ($url !== "../") { $goto =$page->url . '#focus-list_price"; $event->arguments = array($goto); } }
    3 points
  37. ProcessPageAdd.module has this (that is the process module that is executed when adding a page): $form->addClass('InputfieldFormFocusFirst'); And inputfields.js has this note: * - InputfieldFormFocusFirst: Class assigned to form that should focus the first field. ProcessPageEdit does not add this class, so there is no field focus on edit screens. What I'd do is probably this: // in site/ready.php $wire->addHookAfter("Inputfield(name=title)::render", function(HookEvent $event) { // we focus the field only if it is empty if($event->object->value) return; // show a hint and focus the field $event->return .= "<div>Please enter something here</div>" ."<script>$(function() { Inputfields.focus('#Inputfield_title') })</script>"; });
    3 points
  38. Yes, I think this is exactly what I will do. Like you say, it's easy to do so might as well. As a simple addition to @FireWires great answer: Don't forget about the relatively new url hooks! https://processwire.com/blog/posts/pw-3.0.173/ You don't need a dedicated page then (which means that you also do not need to hide that page from the tree via hooks)
    3 points
  39. @Siddhi Jagtap u.file perms is no write. /site/assets/* need tobe readerable/writedable to.apache sound like apache .run as account that.not you - mabe find new web host that less truble or u.can find out.user what apache run as - "apache", "nobody", "buldnog", etc. if user "apache": https://processwire.com/docs/security/file-permissions/#determining-what-user-apache-runs-as chgrp -R apache /site/assets find /site/assets -type d -exec chmod 775 {} \; find /site/assets -type f -exec chmod 664 {} \; https://processwire.com/docs/security/file-permissions/#how-to-change-permissions-of-existing-files but also visitarlos cont'la lachpud may helper - https://processwire.com/docs/security/file-permissions/
    3 points
  40. @kongondo It shouldn't have any impact on those files and the same rules apply for when the $page API variable is available. The difference now is that you could potentially call $pages->request()->getPage(); on your own to find out what page it's going to be before the rest of PW knows. I think this probably isn't a common need, but the best example I've been able to think of is that SessionAllow module, which would like to know what the current $page is going to be before it decides whether or not to start a user session. That getPage() method is also hookable, so you could also dictate what the $page API var is going to be if you wanted to. Or you could call $pages->request->setPage($page); before PW calls getPage(). @Ivan Gretsky We couldn't make the getDefault() hookable because usually when code calls that, it's because it literally needs the default language and not one that's been substituted for it. So I think we'd have to focus further in on what you are wanting to do, or what front-end logic you are wanting to change, to see if that could be made hookable. That pageNotAvailableInLanguage() method was added to enable hooking into the logic of what the method describes, but perhaps other types of logic can be made hookable too.
    3 points
  41. Hi @Clarity - sorry, I am a bit lost as to what you are asking. Are you referring to a particular action? Is there a place where you are being asked to enter things like 'select', 'text, 'AsmSelect', etc? Maybe post a screenshot of the interface you are finding confusing, or if you are writing a new action, then the list of available field types is only limited to the fields in ProcessWire so that is where you should go for a complete list. Is that what you're looking for?
    3 points
  42. I've pushed a fix. The separator must be translated into a real line break (expected by the Inputfield). I changed the translation to "\r\n" instead of "\n" only, which should work cross platform. Continue to use the string '\n' in the field settings. Please update to version 1.0.1. Could you please give feedback if it works? The pipe '|' you mentioned is already reserved to separate an option 'value' from the option 'title' (@see SelectableOptionManager). I prefer to handle the setup according (very close) to the expectations of the inputfield. ProcessUser and possibly some other processes for editing system pages are not supported. In the special case of ProcessUser, the GET-Parameters forfield and forpage are removed from the url of the modal window for whatever reason. Any idea? The module is still in an alpha stadium. Thanks for testing and feedback.
    3 points
  43. This is amazing! I have missed this functionality in ProcessWire for a while already. Installation Install AdminPageFieldEditLinks: https://processwire.com/modules/admin-page-field-edit-links/ Install FieldtypePageContextData (this module) Create a new field of type "Page Reference Context Data" When setting up the field: in tab "Details" enter configuration in "Additional page fields in Pagefield context". You can see many examples here https://github.com/kixe/FieldtypePageContextData in tab "Input" select "Enable view/edit linnks on selected pages?". If you don't see this field the module AdminPageFieldEditLinks is not activated in tab "Input" when changing the label field: you can also use the additional context fields as label in the page reference. Symply change your label to a custom label and define it like so: {title}, {_customfield1}, {_customfield2} assign the field to your template Screenshots When installed and configured correctly you see the page reference like normal. But now you can click it and edit the page in a modal. This modal also contains a new tab "Pagefield Context Data" (the name of the tab can be changed in field settings). Bugs found so far On Windows: separating option values for select by \n is not working correctly. Maybe use | instead? (as that's how ProcessWire separates fields) for the user template the tab "Pagefield Context Data" is not being displayed Very well done. This is SO useful! ♥
    3 points
  44. I think this relates to a problem at the video/Vimeo end rather than a problem with the textformatter module. The post below suggests that the stripes thumbnail is what appears when Vimeo fails to successfully generate a thumbnail for a video: http://support.syngency.com/en/articles/3048197-set-a-new-thumbnail-for-your-video
    3 points
  45. ProcessWire 3.0.185 is the latest version on the dev branch this week. Relative to the current master (3.0.184) this is 9 commits ahead and contains various minor fixes, improvements and additions. Since our current master version is quite stable and no significant issues have surfaced since release, we'll likely be focusing on the dev branch for several versions before merging back to the master/main branch. For details on what's new in 3.0.185 dev see the commit log. ProcessWire Weekly #383 also includes some details on a few new selector features added last week that you'll find in this version, read about it here. Today I've posted a new module in the directory called Session Allow. This module enables you to configure whether to allow sessions for each request based on simple configured rules. Currently it requires ProcessWire 3.0.184 or newer. The reason I built this module is that I find the current $config->sessionAllow setting (where you define a custom function) can be a little complicated to work with, especially since it gets called before most of ProcessWire’s API can even be used. This module aims to make control of sessions a lot simpler than that. The benefit of being able to control when a session is allowed is that it lets you better focus your resources for sessions to just the requests where they will be needed, helping to reduce server overhead and improve performance. Currently it supports allowing (or disallowing) sessions based on page path matching rules and hostname matching rules. I also plan to add support for sessions allowed/disallowed per page template, which I think would be really useful. But it'll take some changes to the PW core to support that, as ProcessWire starts the session before determining what page has been requested (and thus what template will be used). So I'm going to make the necessary core updates and then save that feature for version 2 of this module. I'm releasing the module as "alpha" right now because I rushed a bit to get it out for today and feel it needs more testing before I can call it stable. So if you are interested in using it, make sure to test everything out in a development environment first. And if you do get a chance to test it, please let me know how it works for you. Thanks for reading and have a great weekend!
    3 points
  46. I’m not quite sure if this is of interest for anyone and if this is the right forum for my post, but I got the client request to build a module extension for Fluency which translates all the text fields in a page with only one click. The module is not really ready for public (or the modules section), as it has no config page yet and was only tested in one ProcessWire installation, but maybe it is useful as a starting point for anyone who is in the same situation as me: https://github.com/robertweiss/ProcessTranslatePage The module checks for fluency-translate permissions and adds a ›Translate and save‹-button to the edit-page. It supports all core language fields, Repeater, FieldsetPage the pro modules Repeater Matrix, Combo and Functional Fields. Caution: for now, the (language-)settings have to be manually edited in the hookPageSave-Method (Lines 64–69).
    3 points
  47. I was curious and tested out the new Blocks + Layout feature of Kirby 3.5 and here is my brief experience: The interface of the Layout feature is really nice and its fun to add or drag & drop blocks. If the Repeater Matrix would have such an interface, it could be a nice layout builder in ProcessWire. Also it is possible to add custom settings for each row, which makes it possible to customize your layout more. But currently it is not possible to switch the layout (f. e. from 3 columns to 4 columns). If you want to do this, you have to add a new row and drag & drop the blocks there. Also you cannot add custom settings to each column. This feature is currently in development. As for the blocks: You have a default set of blocks (Text, Image, Video etc.) which is nice and covers most of the content needs. Each block has its own snippet, similar to field templates. So you are free to customize the default blocks. Or you can create custom blocks with own fields. But you cannot see all fields of the custom blocks in the layout interface. To edit custom blocks you have to click on the block, which I think is ok in my opinion. In my opinion the Blocks + Layout feature is cool, but has its limitations at the moment. It is a nice mix of layout builder and customization. I wish the Repeater Matrix could be enhanced in this way. But I know that layout builder are no easy task. 😀
    3 points
  48. What's the value of upload_max_filesize in php.ini, and is your web server Apache or nginx? Asking because... upload_max_filesize limits the maximum size of any single file (post_max_size is the maximum size of entire request), and if you're running on nginx then there may be other directives (such as client_max_body_size) that also affect this. Depending on server config this may not work at all. If you have access to php.ini, that's definitely more likely to work.
    3 points
  49. By default, the ProcessWire object is only output in the backend or if you have frontend editing active. Otherwise, you need to add it to the html head in your your php template like this: <script> var ProcessWire = {config: <?= wireEncodeJSON($config->js(), true, $config->debug) ?>}; </script>
    3 points
  50. Hi. You can try to use $page->if() https://processwire.com/api/ref/page/if/ if($page->if('image')) { // ... } $page->if('image', function($image) { // ... })
    3 points
×
×
  • Create New...