Leaderboard
Popular Content
Showing content with the highest reputation on 02/02/2022 in all areas
-
I've not participated much here, since I feel there are more knowledgeable folks here already, but a few quick (?) opinions/experiences: I would love to have an easy way to migrate changes for fields and templates between environments, and version control all of that. I've had cases where I've made a change, only to realize that it wasn't such a good idea (or better yet, have a client realize that) and off we go to manually undo said change. Sometimes in quite a bit of hurry. These are among the situations in which an easy rollback feature would be highly appreciated. I do like making changes via ProcessWire's UI, but at the same time I strongly dislike having to do the exact same thing more than once. Once is fun, but having to redo things (especially from memory, and potentially multiple times) is definitely not what I'd like to spend my time doing ? I've worked on both solo projects, and projects with a relatively big team. While versioning schema and easily switching between different versions is IMHO already very useful for solo projects, it becomes — as was nicely explained by MoritzLost earlier — near must-have when you're working with a team, switching between branches, participating in code reviews, etc. I'll be the first one to admit that my memory is nowhere near impeccable. Just today I worked on a project I last worked on friday — four days ago! — and couldn't for the life of me remember exactly what I'd done to the schema and why. Now imagine having to remember why something was set in a specific way years ago, and if altering it will result in issues down the stream. Also, what if it was done by someone else, who no longer works on your team... ? Something I might add is that, at least in my case, large rewrites etc. often mean that new code is no longer compatible with old data structures. For me it's pretty rare for these things to be strictly tied to one part of the site, or perhaps new templates/fields only. Unless both you and the client are happy to maintain two sets of everything, possibly for extended periods on time, that's going to be a difficult task to handle without some type of automation, especially if/when downtime is not an option. Anyway, I guess a lions share of this discussion boils down to the type of projects we typically work on, and of course different experiences and preferences ?♂️ As for the solutions we've been presented with: I've personally been enjoying module management via Composer. Not only does this make it possible to version control things and keep environments in sync, it also makes deploying updates a breeze. As I've said before, in my opinion the biggest issue here is that not all modules are installable this way, but that's an issue that can be solved (in more than one way). While I think I understand what MoritzLost in particular has been saying about template/field definitions, personally I'm mostly happy with well defined migrations. In my opinion the work Bernhard has put in this area is superb, and definitely a promising route to explore further. One thing I'd like to hear more is that how do other systems with so-called declarative config handle actual data? Some of you have made it sound very easy, so is there an obvious solution that I'm missing, or does it just mean that data is dropped (or alternatively left somewhere, unseen and unused) when the schema updates? Full disclosure: I also work on WordPress projects where "custom fields" are managed via ACF + ACF Composer and "custom post types" via Extended CPTs + Poet. Said tools make it easy to define and deploy schema updates, but there's no out-of-the-box method for migrating data from one schema version to another (that I'm aware of). And this is one of the reasons why I think migrations sometimes make more sense; at least they can be written in a way that allows them to be reverted without data loss.4 points
-
With coded migrations you alter the structure of the application and it is great that your module provides this. But I think we should respect that not everyone wants to do this by code. Some would rather like to use the admin UI. And this is where the recorder comes in. Any changes are reflected in a declarative way. Even coded migrations would be reflected there. What I was trying to say is that the complete state of the application should be tracked in a declarative manner. How you get to that state, be it through coded migrations or through adding stuff through the UI, should be secondary and left up to the developer. ? Please don't go just yet. I'm sure we can all benefit from your input.3 points
-
Have a look at Bernhard's video in the first post of this thread which presents a proof of concept YAML recorder. This records all fields/templates to a declarative YAML file once you make changes through the admin UI to either a field or template. So you will always get the current state of all fields/templates as a version controllable file. That could be imported back once someone writes the logic for the import process. That YAML recorder really is a great first step. But fields/templates config alone do not represent the full state of a site's structure. We'd need to also record the state of permissions, roles and modules and later create/restore them on import. @bernhard's RockMigrations module already has methods createPermission and createRole, so does the PW API. Modules can be installed/removed through the PW modules API. So importing the recorded changes should be possible. The recorder and importer are the key features needed for version controlling application structure. Adding fields/templates/permissions/roles/modules through code like with RockMigrations would be an added benefit for developers who don't like using the admin UI.3 points
-
Thanks @MoritzLost for the detailed post. One thing I don't understand and am hoping you might explain is how Craft handles field renaming within the project config file. Do the config files refer to fields by ID, name, or something else? It seems like IDs couldn't be used in the config because if the IDs auto-increment as fields are added then they wouldn't be consistent between installations. But if names are used instead of IDs then how is it declared in the config that, say, existing field "date" was renamed to "post_date", versus field "date" was deleted and a new field "post_date" was created? Because there's an important difference there in terms of whether data in the database for "date" is dropped or a table is renamed.3 points
-
Just an FYI that I have fixed the CSS issue with the Console panel when it triggers the bluescreen.2 points
-
Now it does, thanks ?. Thank you very much for the very clear and detailed explanation. My confusion is over ?.2 points
-
Sure, I did it a few times but clients always have to pay the price :) Just kidding... Yes, it can sometimes be a real issue for sure. Anyway, I work solo and my projects/clients are somewhat "special" and most of the time clients just rely on all my decisions. Still, thanks for your insights! You have clearly explained your motivations which are more than reasonable, I think. I would be more than happy to join a crowd funding initiative if YOU were the one to lead it, but first someone needs to make Ryan firmly believe he also needs this... Sounds impossible, but never say never.2 points
-
I was explaining the very same needs above, I think. I think we can all agree that this would be dead useful. Ryan does the same but manually, as he enjoys redoing manual clicking work in production. While I can imagine that it can be fun for him, I always avoid this, as it is boring to do it IMHO. That is why I make changes to templates/fields in production, clone the db to local afterwards, and work in code in local staging. When all is ok, I just need to apply the code changes to production because the production db is already up-to-date in the first place. While it works for a one man show, starts to be an issue for a team. Still, even a solo developer would be better off if our feature request could become reality one day.2 points
-
@szabesz Ryan's post in the update thread is very insightful in this regard: Main takeaways from this: Ryan always works alone, never in a team. Ryan only works on projects with sporadic, large updates, never continuous/ongoing development. With these constraints, a manual workflow is really no problem. Personally, I still wouldn't want to go without version control and automatic deployments, but I can see that if you're not used to that kind of workflow you don't see the need for it in this case. Unless you run into one of the constraints to this manual workflow: Working on the same project with multiple people at the same time without version control is near-impossible and error-prone. Working on a project with constant updates where you need to deploy not once every 3 months, but 5 times a day – in the latter case, those 5 - 10 minutes for each deployment really add up and get annoying real quick. So I can understand Ryan's point of view that version control integration is kind of a 'luxus' feature, instead of an absolute necessity for many teams/projects. I don't agree with this view – but ultimately it's up to Ryan where he wants to take ProcessWire. And it's up to developers to figure out if ProcessWire's feature-set is sufficient for each individual team or project. I agree with @szabesz that you need this in the core. Full version compatibility will require some changes in mindset and feature-set for the core, and this can only come from the core itself. @Kiwi Chris The difficulty comes from trying to use migrations, so a stream of changes, instead of declarative config. You want a config that describes the entire system so it can be built from scratch if necessary, not just a set of changes to go from one build to another. See below for details. ----- In the other thread I posted some arguments why a declarative config is better than PHP migrations, just leaving this here since @dotnetic asked to have it cross-posted:2 points
-
One method would be to combining two finds, something like this: $results = $pages->find("search_index%=$query, has_parent=1234"); $moreResults = $pages->find("search_index%=$query, has_parent!=1234"); $allResults->import($moreResults); $limitedResults = $allResults->slice(0, 15); Note that setDuplicateChecking() can be useful with import() when doing this sort of thing. Perhaps someone else knows how to do this with a single selector!1 point
-
Yes, writing the config should always dump everything. Much easier than keeping track of changes. Of course, under the hood the actual implementation could optimize that further, for example by only writing files that have changed to reduce disk i/o. But conceptually, the config should always include the full config for the current system state. On import, you probably can't wipe out all fields since that would remove the database tables and wipe all content. When the config is applied, the appropriate process/class should read the config and apply any differences between the config and the database state to the database. I.e. create missing fields, remove fields that aren't in the config, apply all other settings etc. At least that's how Craft does it. Conceptually, the entire config is read in and the site is set to that state. In Craft, there's a clear separation of concerns between config and data. The config is tracked in version control, data isn't. That's not a problem if you don't do any 'real' content editing in your dev environment. For our projects, we usually set up a staging environment pretty early on and do all actual content editing there. Once the project is ready to go live, we either switch the live domain over to that staging environment (so staging is promoted to production, essentially). Or we install a new instance of the project and copy over the database and assets folder so we have separate production and staging environments. For projects that are already live, you just wouldn't do any real content in the dev or staging environments. If you really need a large content update alongside a code update, you could use an export/import module or migrations. Migrations complement the declarative config and most of the time, we don't need them at all. By the way, there's a discussion to be had about where you draw the line between config and content. For example, for a multilingual site, are the available languages configuration (only editable by the dev) or content (editors can create new languages)? There are many of those grey areas and I don't think this has a single right answer. Craft uses UUIDs in addition to the name. Each field also has an ID that's environment-specific, but that's an implementation detail you never have to interact with, since you can always refer to a field by name or UUID. So you can change a field handle while the UUID stays the same. This also prevents naming conflicts, since new UUIDs are pretty much guaranteed to be unique. ---- On a broader note regarding the difference between declarative config and migrations: It's important to distinguish between the 'conceptual' view (the config represents the entire site state) and implementation details. Take git as an example. Conceptual, each commit represents a snapshot of the entire codebase in a particular version. Of course, under the hood git doesn't just store a copy of the entire codebase for each commit, but optimizes that by having pointers to a database of blobs / objects. But that's an implementation detail, while the public API is inspired by treating each commit as a snapshot of the codebase, not a collections of diffs.1 point
-
If you want dates to output in other languages, I'd start here: And perhaps also look at this: If you want all dates from a particular field to be formatted the same on output, look at the Details tab for the data field. To format dates on a template, use PW's $datetime->date() (see https://processwire.com/api/ref/wire-date-time/date/). Or you could get the timestamp (the unformatted date) with $page->getUnformatted("date_field") and then use PHP's date functions – particularly strftime().1 point
-
If I'm understanding what you're trying to achieve correctly (which I may not be!), might something like this work? $twoDaysAgo = strtotime('-2 days'); $twoDaysAhead = strtotime('+2 days'); $pagesInDateRange = $pages->find("template=templatenameA, datefield>=$twoDaysAgo, datefield<=$twoDaysAhead, sort=datefield"); foreach($pagesInDateRange as $pageIDR) { if($pageIDR->type == 'season') { // Using just two generalised field and variable names as an example $var1 = $pageIDR->field1; $var2 = $pageIDR->field2; $relevantPages = $pagesInDateRange->find("template=templatenameB, fieldA=$var1, fieldB=var2, sort=datefield"); } elseif ($pageIDR->type == 'solemnity') { // etc etc } foreach($relevantPages as $rPage) { // Render pages } } This could all go in the template for the page.1 point
-
Some people are wanting continuous upgrades to complete sites, but the kind of scenario I'm facing for the first time, is potentially identical, simultaneous upgrades required to multiple sites with different data, but on an extensible modular level. I've been thinking along the lines of having a method to build a full state, but whenever any objects in that state change, having some way to track what's changed since the last build. Building the full state looks to be relatively easy; specify what fields, templates, and pages are required, and in what order to satisfy dependencies, and then dump JSON files with definitions of all the objects required. Handling changes since the initial build in a reversible way is more of a challenge. I think if I did want reproducible upgrades to whole sites, that would be easily achievable by simply specifying the module dependencies in a configuration file, as they would encapsulate all the fields, templates, and pages required for a given site configuration, I'm moving towards the idea that everything other than the core would basically end up being a module, which in some cases may be responsible for nothing more than maintaining a set of fields templates, and possibly pages (eg for lists) for a specific task. Existing module dependency capabilities mean I can handle if a module depends on existing fields, as I can simply make it depend on the module that installs and maintains those fields. EG, module 1 installs a base set of fields, templates and pages. Module 2 requires some of the object data installed by module 1 but extends on that with additional functionality including its own fields, templates, and possibly pages. Module 3 also requires data from module 1 and extends on it in a different way. All sites will have module 1, but will have either module 2 or 3 but not both. I don't want or need to migrate an entire site, as that would get too messy if I start deploying a number of similar sites, but each with unique user data and sub-components. I still want to be able to use the UI though for rapid prototyping, and then build a deployment configuration once I've tested things out. Obviously changing things via the UI doesn't automatically add dependencies to a module, but that's fairly insignificant to achieve. Microsoft's Entity Framework Core specifically has an issue with this. It can generate automatic migrations with schema changes, but a renamed field or class results in a drop and create, rather than a rename, and their documentation recommends manually editing auto-generated migrations to deal with this. Obviously this problem isn't unique to ProcessWire by any means. ? The way things work there, is class definitions are complete, self-contained defintions of the schema, but separate migration files handle getting to that state if the current schema doesn't match the class definitions. Although .Net is a different platform, I wonder whether the way Entity Framework handles migrations could provide some insight into how to build a workable system for ProcessWire?1 point
-
So I'm working on a new release and I just found this the other day myself. To fix this right away, change the following on line 172: <?php // From: wire('log')->save(self::ERROR_LOG, $message); // To: wire('log')->save(self::ERROR_LOG, $output['message']); This line means that there was a problem with DeepL. Either it had trouble connecting or DeepL returned an error when you tried to translate. In the ProcessWire admin take a look at the Fluency log, I think it may be named "deeplwire-api". It should contain the error to help you troubleshoot.1 point
-
@kongondo @szabesz @horst A completely automated deployment enables continuous deployment as well as a number of other workflows. Being able to rollback to a previous version is part of it, but it's only one of the benefits of version control, and probably not the most important one. It's all a question of how much your workflow scales with (a) the amount of work done on a project / number of deployments in a given timeframe and (b) number of people on your team. For me, the 'breaking points' would be more than maybe one deployment a week, and more than one person working on a project. There were many different approaches mentioned in the previous threads – migrations, cloning the production database before any changes, lots of custom scripting etc. But those all break down if you're starting to work in a team and get into workflows centered around version control. The key to those workflows is that each commit is self-contained, meaning you can rebuild the entire site state from it with a single command. For comparison, here's how I work on a Craft project with my team, following a feature-branch workflow. I may work on the blog section while my colleague works on the navigation. We both have our own local development environment so we can test even major changes without interfering with each other. Once my colleague has finished, they commit their changes to a separate branch, push it to Github and open a pull request – including any template changes, translations, config changes, etc. I get a notification to review the PR. I would like to review it now, but I'm working on a different feature right now, have a couple of commits and some half-finished work in my working directory that's not even working at the moment. No problem, I just stash my current changes so I have a clean working directory, then fetch and checkout my colleague's branch from Github. Now it only takes a couple of commands to get my environment to the exact state the PR is in: composer install (in case any dependencies / plugins have changed) php craft project-config/apply (Apply the project configuration in my current working directory) npm ci (install new npm dependencies, if any) npm run build (build frontend) Most of the time, you only need one or two of these commands, and of course you can put those in a tiny script so it's truly only one step. Now I can test the changes in my development environment and add my feedback to the PR. Keep in mind that the new 'blog article' entry type my colleague created with all it's fields and settings is now available in my installation, since they are included in the config that's commited in the branch. Now imagine doing that if you have to recreate all the fields my colleague has created for this PR manually, and remove them again when I'm done. Now image doing that 10 times a day. By the way, everything I was working on is savely stored in my branch/stash, but is not interfering with the branch I'm testing now. This is the benefit of a declarative config: Everything that's not in the config gets removed. So even if I left my own work in a broken state, it won't interfere with reviewing the PR. With migrations, you'd have to include an up and down migration for every change, and remember to execute them in the right order when switching branches. Any manual steps, no matter how easy or quick they are, prevent those workflows at scale. Automatic deployments also makes your deployments reproducible. Let's say you have an additional staging environment so the client can test any incoming changes before they hit production. If you do manual deployments, you may do everything right when deploying to staging but forget a field when deploying to production. With fully automated deployments in symmetric environments you'll catch any deployment errors in staging. That's not to say you can't introduce bugs or have something break unexpectedly, but by removing manual steps you're removing a major source of errors in your deployments. I can one-up that: zero clicks. Automatic deployments triggered through webhooks as soon as a PR is merged into the main branch on Github. Deployment notifications are sent to slack, so everyone sees what's going on. A branch protection rule on Github prevents any developers from pushing directly to the main branch, and requires at least one (or more) approvals on a PR before it can be merged ? You're clients never ask you to undo some change you did a while ago? Not because of some bug, but because of changed requirements? In any case, if your version control only includes templates, but not the state of templates/fields that those templates excect, you won't be able to reverse anything non-trivial without a lot of work. Which means you don't get a major benefit of version control. Going from commenting out chunks of code because 'you might need them later' and just deleting them, knowing you will be able to restore them at any time, is really enjoyable. Having the same security for templates, fields, etc is great. Fun story: I once implemented a change requested by a client that I knew wasn't a good idea, just because it would take less time than arguing. Once they saw it in production, they immediately asked me to revert it. One `git revert` later, this feature was back in its previous iteration.1 point
-
This is to keep track of the state of a site's structure independent from the content. To allow changes of fields and templates that have been altered on local or staging to be transferred to the production version without loosing content that was introduced in the meantime. Does this make sense?1 point
-
I can't look into that in detail but maybe RockFinder can help you: https://github.com/baumrock/rockfinder3#example-group-by-date1 point
-
make sure u have latest master version 3.0.184. sessionCookieSameSite added 3.0.178 ProcessWire Weekly #366 or add to htaccess <ifmodule mod_headers.c> Header always edit Set-Cookie ^(.*)$ $1;SameSite=None;Secure </ifmodule> u should have no issue.1 point
-
The most common way to use the "Add New" feature is by defining "Allowed template(s) for children" and "Allowed template(s) for parents" on the templates in question. See the information in the screenshot below: When you have this configured then you can quickly add new pages of the child template via the "Add New" button and menu link. The "Bookmarks" feature applies when you haven't defined allowed parent/child template settings, but you want a shortcut to add a new child page under some specific parent page. So if you had some deeply nested page that you often want to add new child pages under you could set a bookmark for that parent. Clicking the bookmark would then be the same as opening the page tree to that parent and clicking "Add", but it would perhaps save you some time. It's not a feature that I've found all that useful in practice.1 point
-
Minimal Fieldset Adds a config option to Fieldset/FieldsetGroup/FieldsetPage to render the fieldset without label or padding in Page Edit. When a neighbouring field in the same row is taller than the fieldset the extra height is distributed evenly among rows within the fieldset. Requires ProcessWire v3 and AdminThemeUikit. Why? This module allows you to create layouts in Page Edit that would not be possible without it. It's useful when you want a layout that has two or more fields as rows that are themselves within a row in Page Edit. It's also useful when you have some fields that you want to add to a template as a group (i.e. via FieldsetGroup or FieldsetPage) but having a heading and visible wrapper for the fieldset in Page Edit would be redundant. Example: Installation Install the Minimal Fieldset module. Usage In the field settings for any Fieldset/FieldsetGroup/FieldsetPage, tick the "Remove label and padding for this fieldset" checkbox. https://github.com/Toutouwai/MinimalFieldset https://modules.processwire.com/modules/minimal-fieldset/1 point