Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 08/28/2020 in all areas

  1. This week I’ve been working on a combination of the core, and a PW audio-streaming project for a friend, working as a volunteer. There’s some overlap in these two things, as a lot of the core updates this week are somewhat related. It provided the needed motivation to finish a new feature I started working on in 3.0.149, which will be finally finished in 3.0.166. Actually, it’s finished now, but I haven’t bumped the version number on the dev branch yet—I’ll do that next week. The feature finished this week adds support for a new secure files option similar to the $config->pagefileSecure option (you may or may not have heard of), except that it allows you to configure secure files at the template level, rather than just site-wide level. In ProcessWire, when you unpublish or trash a page, or when you access control a page so that it’s not visible to guest users, the page’s files in /site/assets/files/page-ID/ can still be accessed directly by URL (like if someone bookmarked a PDF or something). So we have the $config->pagefileSecure option that lets you specify that the files should also be access controlled. This ensures (for example) that if a page is unpublished, its files can’t be loaded by anyone except a user that can view unpublished pages. But I rarely use this option because it is site-wide, and access controlled files take some overhead (being delivered by ProcessWire rather than Apache) and thus are something I’ve always wanted finer control over. That’s because most of the time, I don’t care too much about direct access to files because they are mostly images and endless variations of them. But there are also those specific cases where I really do need it. So being able to make it part of the template-level access control really makes it a lot more flexible, and hopefully makes the option a lot more obvious: There’s also that “Yes always” option (in the screenshot above), which is something we’ve not had before. This is useful when you want to have full control over a file download (or stream). Because the files would always pass through ProcessWire, you can hook any part of the process, keep a download counter, log downloads, etc. ProcessWire supports partial file delivery and delivery of specific byte ranges and seeking, which comes in especially handy with <audio> tags. In the case of the project I was working on this week, the audio streams are available only to logged in users (via LoginRegisterPro) and we had to find a way to make the audio files protected from direct access, so that they would only work as a stream through an <audio> tag to an authenticated user, not be accessible outside of that, and not be downloadable. That was all a bit of a challenge, but a fun one. If anybody ever runs into a similar need, be sure to send me a message. I have a few more things I want to work into version 3.0.166 before bumping the version number, so that’ll likely come by this time next week. I also hope to fully wrap up the new version of either FormBuilder or ProCache next week, followed by the remaining one the following week. Thanks for reading. Have a great weekend!
    14 points
  2. I wrote this a while back for my company's internal documentation and just realized it might be a benefit to others on the forum, so here it is! Checking whether a field was changed To check whether a specific field was changed you can do $page->isChanged(‘field’). This can only be done before Pages::save, since the save clears change tracking by default. Getting the values of a page before they were changed, from within a hook before Pages::save Method 1: The hacky way $clone = clone($page); $e->wire('pages')->uncache($clone); $oldP = $e->wire('pages')->get($clone->id); $oldP then represents the page and all its values as they were before any changes were made. Again, this will only work for hooks that run prior to Pages::save. Method 2: Using change tracking to get the old values If change tracking is set to track values, then the above is not necessary. In this case, calling $page->getChanges(true) will return an associative array of fields that changed and each field's prior value. Note that the value itself is also an array, since it is designed to be able to track multiple changes over the course of a single request/response cycle. Tracking of values is turned off by default (for efficiency sake), and there is no global switch to turn it on and off. To enable tracking of values, you must call $page->setTrackChanges(Wire::trackChangesOn | Wire::trackChangesValues) before any changes are made to the page that you want to track. Here is an example of how you can enable value tracking in ProcessWire's page editor: $this->addHookBefore("ProcessPageEdit::execute", null, function($e) { $p = $e->pages->get((int)$e->input->get('id')); if($p->template == 'event-registration') { $p->setTrackChanges(Wire::trackChangesOn | Wire::trackChangesValues); } }); Running hooks on both page saves and field saves Please note that using the following hooks is preferable if you want the hook to run both when individual fields are saved as well as the whole page: Pages::savePageOrFieldReady https://processwire.com/api/ref/pages/save-page-or-field-ready/ (for before a save) Pages::savedPageOrField https://processwire.com/api/ref/pages/saved-page-or-field/ (for after a save) Getting changes in a hook after Pages::save Note the $changes parameter passed to Pages::saved and Pages::savedPageOrField allows you to check which fields were changed during the save, even though the save is already completed. Using this is sometimes preferable to using a Pages::saveReady or Pages::savePageOrFieldReady hook since you don’t have to worry about the page cache or something else in your code preventing the original save from completing. A $values array is also provided, which is populated only if change tracking is set to track values (see above) Page cache issues when hooking before Pages::save Page cache issues may occur when you try to save another page inside of a before save hook (Pages::saveReady or Pages::save). A page save normally clears the entire page cache, which means any page fields on the page you were originally trying to save will have their values reset. So if you have to save another page inside of a before save hook, just use $page->save([‘uncacheAll’ => false]) to prevent the cache from being cleared. Preventing hooks from running on a particular save To prevent any hooks from running on a particular page save, you can use $pages->save($page, [‘noHooks’ => true])
    5 points
  3. Sometime in the recent past, Chrome and Firefox decided to hide important parts of a URL, like https:// and www., which only appear if you focus the address bar field (and even then it's still finicky). I find that it's important to show the full URL, especially when doing ProcessWire development, and particularly when deploying a website and trying to get .htaccess just right on the production site. How to show full URL in Chrome: https://winaero.com/blog/always-show-full-url-address-in-google-chrome/ How to show full URL in Firefox: https://www.cnet.com/how-to/how-to-show-the-full-url-in-firefox/ How to show full URL in Safari: https://www.laptopmag.com/articles/safari-view-full-url
    3 points
  4. Has your root .htaccess file made it through the FTP program into the online host? Please double check if it is in place there. Some FTP programs have filters that hide and exclude dot files from transfers per default.
    2 points
  5. No, but have you tried to set the page status to be unpublished, save it, then delete it?
    2 points
  6. @ryan there is still one of my very first PW projects, the MP3-DB site profile, which doesn't work with any PW 3 version (or newer PHP versions ?). I've been wanting to put the essence of it into a module for quite some time, so that one can add MP3-DB support to any existing site with ease. It seems that I'm getting a bit closer to the goal thanks to your new features, because it will be much less work if partial file delivery and delivery of specific byte ranges and seeking is now natively supported by PW! ? When starting with it (maybe around christmas this year), I will contact you before.
    2 points
  7. I'm going to start from the end, because this is the easy part (maybe) ? First of all, all the main concepts found from Wireframe have been around, in one form or another, for about a decade. Wireframe (the module) was developed a couple of years ago, and components were added about six months ago. Partials have been around since the very beginning, while components are a brand new thing. As for "should there be both partials and components", this is a good question going forward: Components are more versatile, but also more complex. There's a class (for business logic) and one or more views (for markup). Partials are a lot simpler. Even though you can pass params to partials and arrange them in directories by type or whatever, they are essentially just individual include files. In my typical project there's a need for both: by default I prefer the simplicity of partials, but if I really need to do something more complex on a per-element basis (justifying the mental and technical overhead of the class based approach), I go with a component instead. Heck, in one recent project I even surprised myself by using components within components. Not what I'd call an "easy to grasp setup" (which is always something that I try to emphasize in my work), but it gets the job done and was fun to work on. Will components and partials eventually merge into one? I don't know — maybe, maybe not. For the time being I quite like having them both around. In my projects they tend to solve different problems, even though they could be used interchangeably ? Oh, I'm sure that this makes a huge difference! As I've mentioned before I haven't really used custom Page classes, because — for my use cases — controllers provide same benefits, and then some more. Nevertheless, had custom page classes existed when I started working on Wireframe, there's a good chance that I would've taken an entirely different route ? I might've already touched some of the same topics earlier — particularly the one about having more than one type of object in Wireframe — but a few additional notes on this: You don't have to use anything you don't need. Layouts, views, and controllers are all optional. In many of my projects there's one layout, a bunch of views (often much fewer than there are viewable templates, since many templates are so simple that the layout file takes care of all the markup), and a few controllers (just for those templates that require something "more complex" behind the scenes; news or event containers / lists, page search, etc. The "everything is a component" approach is quite possible with Wireframe, though that was never really something I intended (or expected, to be honest!) The roots of Wireframe are in the MVC architecture, and that's where controllers, view, and model (which in this case is actually ProcessWire) come in. Components were intended as something that you can use to "fill in the gaps"; a bit like utility classes, for that matter. When you say that "Controllers are tied to the template of the viewed page", that's actually not entirely true: by default Wireframe will indeed only know that for a Page using the "basic-page" template it should check if a controller class called BasicPageController exists... but you can also make multiple pages share a single controller, change the controller on the fly, etc. Much of this is pretty new and I'm still experimenting with it, but I have high hopes that it will become even more useful in the future. As for the "couldn't that also be handled by the component" part: controllers do certain things that components don't, there's always exactly one controller active for a specific page at any given time, and these two work in a different context. The context of a controller is a page render request, while the context of a component is much smaller — essentially the subset of the request that it has been provided with. In my opinion it's best to keep them as separate concepts — at least for the time being — though once again who knows what will happen in the future ?‍♂️ I hope I don't really need to say this, but... feedback, comments, and (constructive) criticism is always welcome. I can't promise that I'll agree with all of it, but I'm happy to hear others' experiences nevertheless ?? -- I'm pretty sure that you've seen this already, but I've got a couple of site profiles online — https://github.com/wireframe-framework/site-wireframe-docs and https://github.com/wireframe-framework/site-wireframe-boilerplate. These are a bit dated by now (neither uses components, for an example), but they may provide some insight into the way I personally use Wireframe. I've been really looking forward to revisiting the weekly.pw website and sharing that as well, hopefully something I can get done before the end of the year. This site is also really, really dated (both visually and feature wise), and I'd also like to show off some of the new stuff in Wireframe ?
    2 points
  8. As I get it, partials came first (there were no components at the time). And components were added later due to user requests. I think too that only one (the components)) should stay in the future. But I may be missing something.
    2 points
  9. Yes ? Just wanted to share my experience so far and point out that I still think it would be nice to have. No idea about the complexity behind, so of course it's better to think twice ? Also no idea about Wireframes caching yet. I'll throw everything to ProCache in the end ? --- What I wondered during the last days of working with Wireframe is if all those different concepts (controllers, views, components, partials) are really necessare or make sense? I found myself rewriting some partials to components because I added some business logic. Now I have only one partial left ? Maybe I'll have to add others, maybe not. I don't know yet. But I wonder if it wouldn't be easier to have just one concept for all blocks? So everything would be a component and work the same. I understand that Controllers are tied to the template of the viewed page, but couldn't that also be handled by the component? I'm not sure I like that all my content is split up in different "types" and it's not instantly clear where I have to look for markup portion xy... Maybe that feeling is even stronger because I'm using custom page classes a lot. So there's not really a need for controllers at all, because my pages are already some kind of controller?! But even if that was one part of the "problem", the other part still remains: Why partials + component? Wouldn't it be easier to merge them to one single concept that always works the same? I know, that would bring in lots of breaking changes, but I'd be interested why you built the module like that. Maybe there is a good reason for that I just didn't realize until now ? Please don't take this as criticism at all. Just trying to find the right way for doing the frontend part of my projects ?
    2 points
  10. This is a great idea, we don't really use the publish/unpublished thing for these pages, but maybe a solution right under me nose ? Thanks!
    1 point
  11. Hey @bernhard! I believe this is the same concept that was discussed earlier, i.e. having direct access to public component class methods from the component view? If so, I'll be sure to dedicate this some thought soon, and if it does indeed seem like a good idea, I'll try to get it implemented for the next release (after 0.13.0, which went live a few minutes ago) ? I'm leaning towards adding this feature, but the added complexity still worries me. Just providing access to public methods of the class is one thing, but if I go on and add that, I pretty much have to add at least the (runtime) caching support currently provided by the controller to make sure that devs don't accidentally step into a really nasty performance trap. And if I add this, for the sake of consistency I have to consider also adding support for persistent caching, method aliases, disabled methods, and a few other things. Anyway, this is just me thinking out loud. I'll see what I can do about this in the near future ? I've added your idea about catching errors and logging them to my todo list. Not entirely sure about this one yet, but it's definitely worth thinking through.
    1 point
  12. Some things to check which tripped me up when taking over from a previous developer: In site/config.php ensure that the template url & path are pointing to YOUR templates url & path. The default is 'template' however is customisable In Set Up ->Templates -> [your template] -> Files tab, that your template file name is not being overridden in the Alternate File Name field by something the original dev entered HTH
    1 point
  13. @Brian Peat Debugging is easier with the Tracy Debugger module installed. The Request Info panel will show you exactly which template is being rendered and which PHP file it's using. Check if it's the correct one and take it from there.
    1 point
  14. Working fine from here, germany, via hoster netcologne and also routed over different IPs via VPNs like PureVPN and CyberGhost. @clsource and btw, nice work! ?
    1 point
  15. Hey @Brian Peat, Sadly I'm not able to answer your question — hopefully someone else can! — but just a quick note: "Landing Pages" is not a native ProcessWire concept, so presumably that's something that the original developer of this site added while setting things up. You also mentioned "widget template", and that (widgets) is another thing that isn't vanilla ProcessWire stuff. All in all the thing with ProcessWire is that since there's no "one true way to build sites", it can be hard to say much about the site in question without seeing the source code ? Normally all you need for a custom template to kick in is... Create a new template in the ProcessWire Admin and assign fields etc. to it. Create a page and select your newly added template as the template. Add a template file at /site/templates/your_template_name.php. View the page on the frontend and ProcessWire will render it using the your_template_name template and your_template_name.php template file. In case this is not the normal workflow with this site, I'd start by checking which modules are installed (look for something that might affect page rendering). Then check which template files the site has, and if one/some of those are using URL segments to achieve some sort of custom templateish effect. If at doubt, you can paste some code here — just make sure that there's nothing secret in there (keys or passwords etc.) Hopefully this will lead you to the right direction. ... and by the way: if possible, I'd try to contact the original author of the site. And make sure that they didn't leave any documentation (it'd be the decent thing to do, but obviously not everyone does that...) ?
    1 point
  16. Hi @teppo Thx, it made click in my head ? I'll write about my journey and come up with suggestions at the end of the post: First try: <body> <?php if($page->is(['template' => [GemeindeGuru::tpl_teaser]])) { echo $partials->{GemeindeGuru::tpl_teaser}->body; } else { echo Wireframe::component("Header"); echo Wireframe::component("Search"); echo Wireframe::component("Slider"); } ?> </body> Nice, this already works ? 2nd try: <body> <?php switch($page->template->name) { case GemeindeGuru::tpl_teaser: echo $partials->{GemeindeGuru::tpl_teaser}->body; break; default: echo Wireframe::component("Header"); echo Wireframe::component("Search"); echo Wireframe::component("Slider"); break; } ?> </body> A lot better imho, but what if I wanted to add a custom 404 design? I'd need to duplicate the switch case: <body> <?php switch($page->template->name) { case GemeindeGuru::tpl_teaser: echo $partials->{GemeindeGuru::tpl_teaser}->body; break; case GemeindeGuru::tpl_404: echo $partials->{GemeindeGuru::tpl_404}->body; break; default: echo Wireframe::component("Header"); echo Wireframe::component("Search"); echo Wireframe::component("Slider"); break; } ?> </body> Not bad as well, but I wanted something better ? Next try: <body> <?php $body = $partials->{$page->template->name}->body; if($body) echo $body; else { echo Wireframe::component("Header"); echo Wireframe::component("Search"); echo Wireframe::component("Slider"); } ?> </body> ProcessWire\WireException Partial file not found: C:/laragon/www/kaumberg/site/templates/partials/home.php Fast-forward: I did some more testing and realized that I was actually mixing up partials and placeholders! The final (and great) version looks like this: // layouts/default.php <body> <?php if($placeholders->body) echo $placeholders->body; else { echo Wireframe::component("Header"); echo Wireframe::component("Search"); echo Wireframe::component("Slider"); } ?> </body> // views/home/body.php echo Wireframe::component("Header"); echo Wireframe::component("Search"); echo Wireframe::component("Slider"); echo Wireframe::component("News"); echo Wireframe::component("Contact"); echo Wireframe::component("Footer"); // views/teaser/body.php <div class='uk-height-viewport uk-flex uk-flex-center uk-flex-middle'> <div class='uk-text-center'> <div><img src='mylogo.svg' class='logo'></div> <div class='teaser'><?= $page->title ?></div> </div> </div> This simply means: If the view file /views/[template]/body.php exists, render it, otherwise render the default sections. That should make it really easy to create custom layouts for some templates whily still having all other assets and scripts in place (like seo, styles, analytics etc). I think I'm happy with this setup ? I realized, that I was missing the link between $placeholders->foo and /views/[template]/foo.php I read the docs again and I saw that this information IS already there ? My personal addition to this sentence: If you know where you have to look ? This illustration makes a lot of sense now. But I didn't get it quickly I have to admit. Here's my conclusion and suggestion: IMHO your docs are great explaining "how it works", but they could be improved in regards of "how I can work with it". In my experience this can make a huge difference in the experience of someone looking at it the first time. It's basically what you said earlier: Exactly that! I think if the docs where split into two sections, the first being "quickstart" and the second being what you already have, that would be brilliant. I know that what I'm asking for is a lot of work, but if we (you ?) want to build some kind of standard, it should be as easy as possible for everybody to adopt to it ? Finally I've got a question/request that you have to review from a technical point of view. As stated above, it took some time for me to grasp this easy concept: $placeholder->default loads /views/MyTemplate/default.php $placeholder->head loads /views/MyTemplate/head.php If you look at the rest of wireframe this becomes quite obvious: echo Wireframe::component("Header") --> /components/Header/default.php echo $partials->menu->top() --> /partials/menu/top.php echo $placeholders->body --> /views/[template]/body.php This really confused me when starting with wireframe! I'd expect placeholders to live in /placeholders or, the other way round, the variable to be called $views echo Wireframe::component("Header") --> /components/Header/default.php echo $partials->menu->top() --> /partials/menu/top.php echo $views->body --> /views/[template]/body.php These 3 lines would make it obvious what options you have in your layout file. But maybe that's because I've already a better understanding of what's going on, so maybe other newcomers could comment on this? What I was really missing was a guide that helps me go through a typical web project: You got a design, you got a PW installation, you installed Wireframe, what then? Now after 2 days of testing this was the way that worked great for me (so far): Set wireframe as alternate template file for all templates that should be handles via wieframe (for this walkthrough we take home.php and basic-page.php of the default site profile). Create a default layout: /layouts/default.php <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title><?= $page->title ?></title> </head> <body> <h1>I am the default layout</h1> </body> </html> Open the root page of your site and the 404 page --> both should display the default layout We want a common page header and footer that is displayed on all templates. Shared markup with little to none business logic is best placed in a partial. Create 2 files: /partials/header.php <div style='border: 1px solid blue; padding: 20px;'>I am the page header</div> /partials/footer.php <div style='border: 1px solid red; padding: 20px;'>I am the page footer</div> Now you can output these partials in your layout's body: <body> <?= $partials->header ?> <h1>I am the default layout</h1> <?= $partials->footer ?> </body> What if we wanted a slider on the frontpage? And ONLY on the frontpage? That's what view files are for and they are accessed via $placeholders. (Don't you think that this is really misleading?) /views/home/slider.php <div style='padding: 20px; border: green;'>I am a SLIDER</div> And add it to the layout: <body> <?= $partials->header ?> <?= $placeholders->slider ?> <h1>I am the default layout</h1> <?= $partials->footer ?> </body> Now open both pages on the frontend and you'll see that the slider does only show up on pages having the [home] template. That magic is simply applied via file structure /views/[template]/slider.php Ok now we want to add the current local time of the user visiting the page. That will obviously need some PHP logic and as we want to separate concerns as much as possible we do NOT want to put that code into a partial. Instead, we create a component that consists of business locig (a PHP class extending \Wireframe\Component and a view file that is responsible for the output. <?php namespace Wireframe\Component; class LocalTime extends \Wireframe\Component { public function render() { return "<div> Your timezone: <strong>XXX</strong><br> Your local time: <strong>XXX</strong> </div>"; } } And add it after the footer of our layout: <body> <?= $partials->header ?> <?= $placeholders->slider ?> <h1>I am the default layout</h1> <?= $partials->footer ?> <?= Wireframe::component('LocalTime') ?> </body> Nice! We get the output at the bottom of all of our pages! We know that doing lots of output within php classes is ugly, so we refactor our setup a little and adopt another concept of wireframe: View files for components: /components/LocalTime.php <?php namespace Wireframe\Component; class LocalTime extends \Wireframe\Component { } /components/LocalTime/default.php <div> Your timezone: <strong>XXX</strong><br> Your local time: <strong>XXX</strong> </div> Of course, this is no a lot better for now, but it is a lot more future proof! Check your frontend, it should still display the same markup for your local time. Now we can add the "business logic" to our component: <?php namespace Wireframe\Component; use ProcessWire\WireData; use ProcessWire\WireHttp; class LocalTime extends \Wireframe\Component { public function __construct() { $http = new WireHttp(); $data = new WireData(); $data->setArray($http->getJSON("http://worldtimeapi.org/api/ip")); $this->timezone = $data->timezone; $this->unix = $data->unixtime; } } And update our view to output the component properties (note how they magically become available as view variables!): <div> Your timezone: <strong><?= $timezone ?></strong><br> Your local time: <strong><?= $unix ?></strong> </div> Go to your frontend and see the magic! Your timezone: Europe/Vienna Your local time: 1598007959 What, you don't want a unix timestamp? Ok... let's provide a formatter method so that you can easily output the time in different formats: <?php namespace Wireframe\Component; use ProcessWire\WireData; use ProcessWire\WireHttp; class LocalTime extends \Wireframe\Component { public function __construct() { $http = new WireHttp(); $data = new WireData(); $data->setArray($http->getJSON("http://worldtimeapi.org/api/ip")); $this->timezone = $data->timezone; $this->unix = $data->unixtime; } public function date($format = "d.m.Y H:i:s") { return date($format, $this->unix); } } @teppo now I got stuck again ? How would I display that formatted date in my view file for this component? Or would I need to provide the date format as variable for the constructor ( echo Wireframe::component('LocalTime', ['format' => 'Y-m-d']); ) PS: Regarding the last question. Controllers do expose methods to views. Is there a similar concept for components? I did implement the local time as component because this does not belong to a single template (then it would have been a controller, right?)
    1 point
  17. No worries ? The error is pretty clear: there's no $page->view, but in the context of the wireframe bootstrap file you can access $this->view (or wire('view') / $this->wire('view'), that's the same thing). API variable $view — behind the scenes it's an instance of Wireframe\View, which in turn extends TemplateFile — is basically how you access the View layer (layouts, view files, etc.) from a) the bootstrap file, or b) controller classes. What I often do is something along these lines: if ($page->is('template=some|template|or|another')) { $this->view->setLayout('teaser'); } Although if it's just about this one template, then I typically create a controller class that sets this. This keeps things neatly in context — just like you mentioned about custom Page classes ? <?php namespaces Wireframe\Controller; class TeaserController extends \Wireframe\Controller { public function render() { $this->view->setLayout('teaser'); } } Note: personally I don't mind having a Controller that is as simple as the one above ?‍♂️ Originally Controllers were built to solve more or less the same things that can now often be dealt with custom Page classes, though personally I still prefer the Controller approach. That being said, your idea about handling init/ready hooks is interesting. In a typical project I don't have that many hooks, so I usually just stash them in init.php/ready.php, or perhaps create a module for a specific (bigger) feature (particularly if they apply to more than one template), but this might be worth exploring further in some future project. (Also a little off-topic, but we've bundled a bunch of "very often needed" hooks into a shared module that we install on all our new projects, and I personally try to keep hooks to minimum — they are powerful, but the more you have the more complex the project gets. Basically the same thing you said about it getting chaotic; I try to fend that chaos off by saying "no" to new features/hooks/etc. as often as possible ?) This does sound like a good use case for multiple layouts. Again I try to keep my layouts pretty "dumb": in my experience too many bells and whistles and flags and toggles result in unmaintainable code. Everything that is specific to a single template generally belongs to view files instead of layouts; sometimes when I have a single page with a completely custom look — say, a campaign one-pager within a bigger site — I disable layout completely for that page, and put everything in the view (as long as it doesn't get massively complex in itself... in which case components and partials can come in handy) ? I feel your pain ? This was the main motivation for creating the original pw-mvc "framework". Imagine that you've got a team of developers all working on their own projects and inventing their own ways to structure things and solve the same issues. And not just some one-off projects that get handed to a client, but ones that the team has to maintain for many, many years to come. Proper level of standardization == happiness.
    1 point
  18. Thx again @teppo ? I hope you don't mind if I throw some suggestions here while I'm exploring wireframe ? One more suggestion for the docs: I think this docs page is a little bloated. Don't get me wrong, I really appreciate the huge amount of informations, but for me it would be easier to start from the minimum working setup and then expand from that. See the docs here: https://wireframe-framework.com/docs/view/components/ It seems to be quite complicated to create components, while all you actually have to do is this: /components/Card.php <?php namespace Wireframe\Component; class Card extends \Wireframe\Component { } /components/Card/default.php I am a Card component! /layouts/default.php echo Wireframe::component("Card"); Once I got that via try&error your "advanced" example was great ? PS: Maybe add a note that /components/Card/default.php could be replaced by adding a render method in /components/Card.php ?
    1 point
  19. @rookie I wish you hadn't said that. I've been using Windows since 1987. Probably need a blood transfusion to get it out of my system.
    1 point
  20. Hi @teppo finally did some more testing, this was my experience: Installed the module, smooth Created default site structure, smooth Set alternate template file for home.php, smooth Empty frontpage --> what now? https://wireframe-framework.com/getting-started/ stops at this step! Ok, it does not stop, but it leads to https://wireframe-framework.com/docs/ -> this is all great informations, but it does not help getting a quick grasp of how to output something on the frontpage... Please don't get me wrong. Your docs are great, but for me (and maybe others) I think some small improvements can make the experience even greater. Maybe something like this (based on my efforts from today): --- Here's a rough, unpolished tutorial for getting started with wireframe and getting the concepts on the road: Follow https://wireframe-framework.com/getting-started/ until the end Set alternate template file for home.php Create /layouts/default.php and visit the homepage --> you'll see the default layout <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Default Layout</title> </head> <body> <h1>Wireframe default layout</h1> </body> </html> Congratulations, that's your first layout! Now add some php variables: <p>My name is: <?= $view->myName ?></p> Of course, why should the layout know the name? We need a controller that tells the view what value is in the myName property! Create /controllers/HomeController.php <?php namespace Wireframe\Controller; class HomeController extends \Wireframe\Controller { public function myName() { return 'Bernhard'; } } What about my favourite CMS? <p>My favourite CMS is: <?= $view->cms ?></p> <?php namespace Wireframe\Controller; class HomeController extends \Wireframe\Controller { public function myName() { return 'Bernhard'; } public function cms() { return "ProcessWire"; } } Ok, I got it - and that's great stuff! ? Now set the alternate template for "basic-page" to "wireframe". Visit a "basic-page" site (eg the 404 page) and you'll see the default layout: The variables are empty, because the HomeController is only loaded on the home template and that's for some good reasons. Read about views in the docs: https://wireframe-framework.com/docs/view/views/ Partials to the rescue ? We modify the default layout: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Default Layout</title> </head> <body> <h1>Wireframe default layout</h1> <?php include $partials->name ?> <?php include $partials->cms ?> </body> </html> And the partials: // partials/name.php <p>My name is <strong>Bernhard</strong>.</p> // partials/cms.php <p>My favourite CMS is <strong>ProcessWire</strong>.</p> Let's make that dynamic! // name.php <p>My name is <strong><?= $name ?></strong>.</p> // cms.php <p>My favourite CMS is <strong><?= $cms ?></strong>.</p> // default.php <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Default Layout</title> </head> <body> <h1>Wireframe default layout</h1> <h2>Viewing template "<?= $page->template ?>"</h2> <?= $partials->name(['name' => 'Bernhard']) ?> <?= $partials->cms(['cms' => 'ProcessWire']) ?> </body> </html> Note that the partials are now echoed instead of included and we added the line that outputs the template of the viewed page! Note though, that partials are really just for simple chunks of code. At best even static ones. As soon as things get more dynamic, start using components instead of partials: https://wireframe-framework.com/docs/view/components/ What do you think?
    1 point
  21. Hi @ryan, I just noticed that part of the documentation for $user variable refer to Page objects instead of User object. Yes, technically, these are pages as well but I think it might confuse new ProcessWire users. In addition, the $user variable docs clear refer to users as 'users' and not 'pages'. Here's an example of what I mean. $users->delete() Here is the list of docs that need amending (that I could find): https://processwire.com/api/ref/users/add/ https://processwire.com/api/ref/users/added/ https://processwire.com/api/ref/users/delete-ready/ https://processwire.com/api/ref/users/deleted/ https://processwire.com/api/ref/users/find/ https://processwire.com/api/ref/users/save/ https://processwire.com/api/ref/users/save-ready/ (some bits are OK). https://processwire.com/api/ref/users/saved/ The get* methods and setCurrentUser() are all OK, referring to User object instead of Page object. The saveReady() refers to User object in some parts but Page object in others. For instance: But further down... Could you please consider amending these? Thanks.
    1 point
  22. Temporarily comment out the following line in Page.php: throw new WireException("You may not modify '$key' on page '{$this->path}' because it is a system page"); This will allow you to clone the home page via the API: $homePage = $pages->get('/'); $pages->clone($homePage, $homePage, false);
    1 point
  23. I can't agree more. Of course there is a logical explanation behind the current situation - there mostly always is. But the open PR's could easily be interpret as a "stale" project. Of course this is not the case as ProcessWire is one of the most worked on CMS. By mostly one guy (not to undercut the other module contributors, lots of love there). Which on itself is pretty amazing. Therefore this is true too: ProcessWire finds itself positioned in a very difficult spot. To clients this isn't very much a problem, since I always find it to be reason of the professional to sell its tools to their client. But selling the CMS to other developers/companies is a lot more difficult. There are quite a few pain points such as the open PR's, the first impressions of the master branch (last commit: 21 dec 2018), the already dated design of the website, the lack of github stars. When I Google for ProcessWire the repository of Ryan is even on a higher position than the current repository (last commit: 7 Oct 2016). The notice on top isn't very clear. These are not important to me*, but first impressions do matter. [off-topic]We should really highlight these strong points: the really great custom field CMS, the speed of development (example: the .wepb support), the great (paid) modules, the great community, second-to-none multilingual support, the great documentation and the greatly written blogs too! Ryan has his way with words.[/off-topic] * I had to look twice myself ?
    1 point
  24. I get your point @horst and what you describe is perfectly fine, but IMHO it wouldn't be a sad truth if it was communicated that way... --> "not-sad-truth" ? --> invest time for PRs --> PRs are ignored --> sad truth ? There are really small PRs that could be easily implemented within no time (eg https://github.com/processwire/processwire/pull/138/commits ). I understand, that checking all PRs can cost a lot of time, but that could be done by someone else just like @netcarver does it for the issues repo. Someone could tag simple fixes and ryan could then just work through PRs having some kind of label.
    1 point
  25. After looking to it a second time, one may come to be able to see the not so sad truth, that is: With ProcessWire we have an opensource project on a very high level in regards of code base, stability & homogenity and much much more along those lines. AND all of of this is directly related to Ryan's decision to *work through all pullrequests* himself to deeply understand, modify, and adapt the code, so that he himself is ALWAYS & IMMEDIATELY able to fix bugs resulting from those code changes. (Even after years, when maybe some people who have sent PRs have left the project again and are no longer reachable.) This has a lot of advantages! And it has, (as everything has), some cons. One of them is, that he is something like a OneManCodingArmy :-), but he is only *one* man. And I don't want him to waste his time to read through every github issue, plus every github pullrequest AND ANSWER TO EVERY ONE of them, in order to explain "why he doesn't want to do it that way, or that he doesn't have time now to do it, or that it could produce a lot of side effects, or, or, or". And one of my fantasies is that he might already be unhappy about not having the times to be carefree active here in the forums, as it was possible for him until about 4-5 years ago. It might feel ungrateful for him to read such a post. This, as a result of his disciplined behaviour, to advance the project as far and effectively as possible. Every week, or almost every day. (( @ryan Did you imagine or wish this when you turned your code into an open source project in 2010? I'm just kidding! But it may sometimes be tiring to be confronted with the same thing over and over again, when the answers have already been given many times and the internet supposedly doesn't forget anything. But when people "don't have time" to do a little research first, or try to look at it from a different angle before, but (in the worst case without any impulse control) always bring up the same things again. Pffhhhh, for my well-being that would be nothing. ? I want you to have time and energy to work in your own flow & rhythm on *your* ProcessWire. Your ProcessWire, that you gifted to us. ? )) @bernhard The truth is, (not the sad truth, not the happy truth, just the truth): it's one of two possible choices that he took 10 years ago. With all the pros and cons. In my opinion, every member of the community should respect that and never forget it. Because all that we have learned to love and appreciate about ProcessWire, all that has enabled us (even in early days, when we may not have had much code experiences) to write our own modules, is the result of that decision and I wouldn't want to miss it. The alternative would be to abandon this course and (quality) control. But all the people I've spoken to in the past, all of whom have more than 15+ or 20+ years of experience in the software business and open source sector, have consistently told me: "Be glad that it is this way. There were so many projects that started that way, but opened up and broke 1 or 2 years later." And about @netcarver question: I have contributed a lot of stuff in regard of image handling in PW. But it seems that less then 5% of it is reflected in githubs contributors list. The most things, where Ryan included my PRs as is, we have had conversations and colaborations about and on it on github or private via PM or email, until the code was accepted by him (in regard to his principles, anounced above). Aaand, it could be, that it also has something to do with the fact that he not only made the experience that I am still approachable after 6 years when it comes to issues, decisions or questions, but that I also not only understood his decision, but also respect it. Even if it has a negative effect on me in some areas. (But that's also just a fantasy of mine, with no claim to truth.) ?
    1 point
×
×
  • Create New...