Jump to content

teppo

PW-Moderators
  • Posts

    3,234
  • Joined

  • Last visited

  • Days Won

    109

Everything posted by teppo

  1. teppo

    Wireframe

    Thanks, @mlfct. This seems to be related to the WireframeRendererBlade module — I've opened an issue for it here: https://github.com/mauricius/WireframeRendererBlade/issues/1. Simply put the Blade renderer appears to expect component views to be found from /site/templates/views/[component name]/[view name].blade.php, while Wireframe expects them to be at /site/templates/components/[component name]/[view name].blade.php ? I would recommend keeping tabs on that issue if you want to use Blade. Twig implementation shouldn't have the same issue, though.
  2. teppo

    Wireframe

    @mlfct, what version of the module do you use? I recently changed a few things that might've been related, so there's a chance that it's fixed already. That being said, I don't use twig/blade myself, so if the issue still exists in the latest version, I'll have to dig in to see what's going on. Also, thanks! I'm really glad to hear that uou've found Wireframe useful ?
  3. teppo

    Wireframe

    Changelog for Wireframe 0.14.0: ### Added - New ComponentView class, as well as the ability for component views to access Component class public methods as properties, in the same way view files and layouts can access Controller class public methods. ### Changed - Hook related code moved from Wireframe module to separate Hooks class. - Accessing public class methods as properties in view files were moved into new trait MethodPropsTrait. This is used internally by Controller and Component classes. - Some minor improvements related to dependency injection within Wireframe objects (and ProcessWire objects instantiated by Wireframe.) @bernhard, what you suggested here... ... is now doable. The way it works is just like with Controllers (this functionality is provided by a new shared trait behind the scenes): <?php // component class namespace Wireframe\Component; class Test extends \Wireframe\Component { public function hello() { return 'world'; } } // component view hello <?= $this->hello ?>
  4. JavaScript ? The easy way out would be to include both phrases (possibly one as a default and other as data-attributes or something similar), and then switch those as needed. You could also fetch entire blocks based on user selections, but that would result in some overhead. Alternative would be to set a variable in .htaccess based on cookie value, and then modify the ProCache rules to serve files from another directory. In this case, though, you'd likely need to use hooks in order to make ProCache store (and clear etc.) two different versions. This approach seems a bit over-complicated for my taste ?
  5. Yes, that's the intention. I actually assumed that these were field values, but if not, then yes — you'll have to define them here as well ? This is a little off-topic, but if/when you store custom non-field values within a Page object, I would recommend prefixing them with an underscore. It's not a big deal, but can make it a little more obvious that these are not actual field values. Also, ProcessWire will never save a property such as $page->_some_key to the database, so this way it's impossible to accidentally overwrite some *real* (field) value.
  6. Perhaps I'm missing something, but couldn't you do something like this in a saveReady hook? $pages->addHookAfter('saveReady', function(HookEvent $event) { $page = $event->arguments(0); if($page->template == 'book') { $page->my_sort_field = implode(' ', array_filter([ $page->subject, $page->cleanauthor, $page->cleantitle, ])); } }); ... and now that your sort field (which could be a hidden text field, or a textarea if there's a lot of data, which I assume is not the case) contains a single value, you can sort results by that. As far as I can tell the only issue here is that you'll basically have the same data stored multiple times ?‍♂️ (Unless I've misunderstood you, and you actually want to keep all books that have a subject before any of those that don't, etc. But in that case a simple sort by multiple field seems enough.)
  7. If you mean a form for public (possibly unauthenticated) users to send data with, I would strongly recommend checking out Form Builder. It's not free, but it's well worth the cost.
  8. Collecting super long referrer values seems pointless (they're likely spam anyway), so truncating seems like a good approach. And the same applies to UA string as well ? -- Edit: just checked a few log files, and I've got similar errors there... and some of these: Exception: SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'user_agent' at row 1 (in /site/modules/ProcessJumplinks/ProcessJumplinks.module.php line 534)
  9. Hey @ryan! This is very loosely related to the weekly update, but I noticed that this week (as well as in some earlier updates) you've started converting $this->wire('api_var_name') to $this->wire()->api_var_name. Just wanted to ask if there's some benefit to this, or if it's mostly just a matter of taste? ? Not a big deal by any means of course, but I've been writing stuff like wire('session') all over my modules, so wondering if there's a reason why I should rather prefer wire()->session etc.
  10. Thanks for setting this up! ? Of course this won't be a problem for everyone, but personally I avoid direct downloads. Here are a few reasons: With direct downloads I can't easily validate the package to make sure it is indeed the original one in case the server has been compromised or something along those lines — which of course is something that shouldn't happen, but in this regard I have more trust in GitHub than individual hosting providers / server maintainers. GitHub (/ Git) allows me to see and track the full change history in case something doesn't work. This way it's easier to track what change caused the problem, why it was made (commit message), and (assuming that the module author is somewhat active on GitHub) file an issue or even submit a fixed version for approval. Finally, I prefer to handle updates via either Git or Composer. It would be too much work to keep track of different blogs for individual modules, let alone download the module package every now and then to see if it has changed . GitHub makes this trivial (periodic git fetch or git pull is quite enough). No pressure, but big thumbs up from here for always uploading modules to GitHub ??
  11. teppo

    Wireframe

    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 ?
  12. teppo

    Wireframe

    Wireframe 0.13.0 went live a while ago. This version introduces only one new feature: variables sent by controller to the view — as well as $partials and $placeholders — now work as-is while rendering fields (= in field templates). In previous versions these were accessible via the $view API variable, which didn't feel quite as intuitive. This required a new hook so there's a bit of added overhead, but at the same time various optimizations were made here and there, so this is unlikely to be noticeable. One thing to note is that this version contains a few breaking changes, though I'd be a little surprised if they affected any real sites: some Wireframe methods were converted from public to protected (these were never really intended as part of the "public API"), and the first argument for Controller class constructor method is no longer an instance of ProcessWire (this wasn't actually necessary). Here's the full changelog: ### Added - New hook makes View properties directly accessible in TemplateFiles (e.g. when rendering field templates) ### Changed - Wireframe::getController() is now a public method that can return current Controller instance, the Controller instance for provided page, or a Controller instance for provided Page and template name. - Visibility of following methods was changed from public to protected: Wireframe::___checkRedirects(), Wireframe::___redirect(), Wireframe::___initView(), Wireframe::___initController(), \Wireframe\Config::getCreateDirectoriesField(). - Controller class implementation was streamlined: new objects are wired using the native wire() function, and thus Controller constructors no longer require the ProcessWire instance as an argument. - Wireframe no longer caches partials unnecessarily, plus new Partial objects are automatically wired. - Various minor optimizations, some code cleanup, and a few improvements to comments.
  13. teppo

    Wireframe

    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.
  14. 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...) ?
  15. What I meant was basically that there could be something unexpected that the proxy approach doesn't solve — i.e. what if some WP plugin depends on REST API and a method that the proxy doesn't pass along properly, or passes along but not with correct credentials, or something. You might also stumble upon various random paths that were not proxied but are expected by WP (or some plugin). Then again, I'd expect the same to apply to the case where both systems live in the same directory. Just be sure to test things (including back and front end, form submissions, and any possible plugins that might do "something" on the front end) carefully. Either way I think it'd be good idea to communicate to the client that the "truly clean and absolutely straightforward" approach would be setting up separate ProcessWire instance, move content over, and then publish that. A (temporary) mashup of WP and PW may indeed work as expected, but there may also be some quirks. As long as the client is OK with that, your neck is safe if something odd does eventually show up ?
  16. Hey @fruid, SearchEngine finds content via the API and the operator used for text searches is configurable (see module config screen), so there's that. Depending on the operator you use you'll get a different set of results (obviously). You can read more about available selectors from the docs. As for Google-style search queries, there's nothing exactly like that built-in, but if you've got a newish version of ProcessWire (3.0.160+) and a recent version of SearchEngine installed, the module supports the advanced text search operator. The downside is that it's currently a little unclear how such queries should be sanitized so this feature is not fully functional. If you don't mind writing a bit of code yourself, there's also an example in the README about how you could provide your own search query and frontend (which, in turn, would allow you to sanitize the query string and then perform a find operation using the "#=" operator). ... and, as for the last point, it's actually also possible to use markup generated by SearchEngine yet still provide a custom results object. It involves a couple of extra steps, but something like this should work (requires SearchEngine 0.26.0 and ProcessWire 3.0.160+): // load and init SearchEngine $searchEngine = $modules->get('SearchEngine'); $searchEngine->initOnce(); // (for autoloader) // construct a Query object ($q stands for the _sanitized_ query string) $query = new \SearchEngine\Query($q); $query->results = $pages->find('search_index#=' . $q . ', limit=25'); // render results echo $searchEngine->renderResults([], $query); That doesn't remove the need to sanitize the query, though. That's something you'd (currently) have to do yourself if you want to use the advanced text search operator to the full extent.
  17. teppo

    Wireframe

    Heads-up! Wireframe 0.12.0 is now the latest master version. This is a pretty big update (in both lines of code, as well as features), so I'd recommend testing carefully after updating. The biggest parts are implemented as a companion module Wireframe API, but there are quite a few changes and updates for the main module as well: ### Added - Support for named arguments when using `Wireframe::component($component_name, $args)`. - JSON API. See comments in the WireframeAPI module file for more details. - New Page methods Page::getController() and Page::setController(). - Module config screen provides support for creating directories corresponding to configured Wireframe URLs, assuming that they were provided as relative paths. ### Changed - Wireframe::setView() accepts optional view name as an argument. - View::setController() accepts Controller name (string) in addition to Controller class instance or null. - When Controller is instantiated, it no longer overrides the Controller property of the related View instance. ### Fixed - Wireframe::partial() now works as expected for partial names with file ext included (partial_name.php etc.) - Wireframe::partial() prevents 2 or more dots in partial name, just in case (directory traversal is not intended).
  18. @Roych, you should probably report the issue at the module's support board, so that the author gets notified: .
  19. While you're at this, perhaps you could take a look at this as well: https://github.com/processwire/processwire-issues/issues/988. I haven't checked recently, but at least back then the modules directory wasn't updating the module version (note that this was unlikely to be caused by normal delay, as the version number hadn't updated in months). Thanks ? Just in case I've been updating the version numbers for all my modules manually. It's not a huge deal, but would be better if the automation worked (though again, I haven't done any tests recently, so maybe this was already fixed.)
  20. teppo

    Wireframe

    Currently the component view file has no way to access the component class. Instead the component class has to pass all the required variables to the view. View can obviously perform actions that seem sensible in that context (such as formatting a date). I have considered adding access to component methods but wasn't entirely sure if it was a good idea. This is still on my todo list and I'll give it more thought in the near future, likely after 0.12.0 has been released. On one hand it might be handy (and in line with how controllers/views behave), but on the other hand every new feature introduced to the module increases complexity, so I want to make sure that it also provides substantial value. Decisions, decisions ? Your current options would be to a) pass the variable formatted from the controller class to the vie file — and if individual instances of this component could require different formats, then passing the format as a parameter is indeed a sensible approach — or b) handle formatting in the component view file (and again optionally pass the format as a parameter to the component and from there to the view file). -- I'll have to get back to some of your other points — which were really good, by the way! — later ?
  21. I can't say that I've been in the exact same situation, but back in the days I worked on a site that was comprised of two or three separate WordPress installations (with their own individual domains behind the scenes), one section that was powered by Craft (I believe), and probably a few other bits and pieces as well. The trick there was a separate proxy service. Sure, this was intended as a long-term solution so that's somewhat different than what you're trying to do, but if these two sites need to co-exist for a notable time, some sort of proxy solution is still the approach I'd recommend looking into. I don't have an out-of-the-box solution for this, but both nginx and Apache can handle proxying specific paths: https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/ https://httpd.apache.org/docs/2.4/mod/mod_proxy.html https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html It would also be pretty simple to do this in PHP, of course — just fetch the real content with WireHttp (in ProcessWire) or wp_remote_get() (in WordPress). POST requests etc. can get a little trickier, though. That's also something you'd want to test carefully in case you decide to go on with web server level proxying ? Just for fun I did a little test using Apache mod_proxy. Probably will take this off line soon, but currently https://weekly.pw/isit/ should serve the content from isit.pw to weekly.pw ? // vhost (after enabling proxy and proxy_http apache modules) SSLProxyEngine on // .htaccess RewriteRule "^isit/(.*)$" "https://isit.pw/$1" [P] Edit: just to clarify, the solution I'm proposing here is... Separate ProcessWire and WordPress installations, with their own URLs. WP in the real domain, PW in a subdomain would likely be preferable. Installing PW in a subdirectory would result in another layer of potential complexity. Don't try to mash these up in the same directory — it's not going to work. Create new content on the ProcessWire site section (= branch) by section, and once the section is ready, proxy traffic via WP site (.htaccess, vhost, and/or PHP, depending on a few factors). Test, test, and test some more. Once everything has been proxied and no (valid) requests hit the WP site (keep track of access logs), replace the WP site with the new PW site. There are some relatively complex steps involved here, so if you're at all uncomfortable with any of it (and especially if the site is critical to the client), you should be very careful when making changes. You should also make sure that the client understands that this is a rather unconventional, and potentially risky, approach ?
  22. teppo

    Wireframe

    The way I see it: if it's output-related, I prefer to put it into a Controller. This is the layer that handles everything that isn't needed in Admin or when loading the page outside Wireframe render context (hooks etc.) In my "ideal project" Controllers provide the backend implementation for the front-end; an API of sorts. I prefer to keep my view files as "low-logic" as possible, and everything that looks like code (external API calls, database queries, complex loops that iterate over content and convert it into some sort of list, etc.) go to Controllers instead. Controllers also provide out-of-the-box some caching features that I've found pretty handy: all Controller method return values go into run-time cache (non-persistent, for a single request), and they have built-in support for persistent caching. In the next release Controllers will also interact with the new companion module WireframeAPI. And yes, obviously one of the reasons I personally prefer Controllers over custom Page classes is that I can bundle in features that I find useful in multiple (most) projects ? Note that while Controllers are by default tied to a specific Template (TeaserController etc.) that's not a must — especially in the later versions of Wireframe this line gets blurrier (is that a word?) and in some situations a single Controller might be applicable to more than one Template. All that being said, it's true that the line between custom Page classes and Controllers can be a little blurry, and it's often a matter of preference ? For <title> tag and SEO tags (metadata) I use a Markup module. Sadly the module that we use in our projects is not publicly available (yet... @Fokke, what do you think, would you mind releasing it? ?) Assets often these depend on the layout, so I typically don't bother to convert them to a partial. Unless it's something like a GA or chatbot tag that also includes a snippet of code and an API key or something, those I prefer to split into partials for maintainability. Now, I'm not entirely sure if I really "got" your question, but there are multiple ways to do this, and I don't think any of them is really "wrong": If you have multiple layouts that share some parts, you could convert those shared parts to partials, components, or even markup modules, depending on the complexity of each of these parts. If it's a one-off thing, i.e. all templates have essentially the same layout except that the Teaser template needs to include JS library X in the head section, sometimes the easy way out is to include a template-specific if statement in a shared layout file. (Emphasis on "sometimes".) If it's something "repeatable", like an array of JavaScript file URLs, you could define it in wireframe.php, Controller class, etc. and then iterate those items and output something like script tags in the layout. ... or you could define a placeholder: // layouts/default.php <head> <title><?= $page->title ?></title> <?= $partials->head->seo ?> <?= $placeholders->head ?> </head> // views/Teaser/head.php <meta name="author" content="<?= $page->author ?>"> <script src="my-awesome-library.js"></script> Placeholders are just a way to "inject" a specific view of a template (or multiple templates) into a predefined location in the layout file. Placeholder slots can also be filled from Controller, though I've found little use for that; sometimes this might be handy if you, say, have a Markup module that should generate the placeholder content, and you already have a controller class. Or something along those lines ? In some relatively simple projects I've had a single layout file, and then placeholders for a) custom stuff in the head area, b) aside content, and c) main content (default view — technically this is a placeholder as well). This works nicely if the page layout is the same across all / most templates, and they just need to inject their own content elements into specific locations ?
  23. teppo

    Wireframe

    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.
  24. teppo

    Wireframe

    Keep 'em coming! ? I'm currently digging into a few Wireframe core things based on your earlier comments. It's really helpful to hear how others are using / getting started with Wireframe, and what sort of troubles they may be running into while doing it. Your comments have already been quite helpful, and I may be able to simplify / streamline some things in the next release. Docs definitely need some love. I'm still learning how to write useful documentation — one that doesn't omit anything that might prove out to be valuable later on, yet still feels "light enough" to get you up and running quickly. Every time I dive into a new library or language or something like that I seem to run into the very same "just give me the damn facts so that I can try it!" thing. I mean... yes, I get that this is all important and all, but do I really need to know all that just to give it a quick try... ?
  25. teppo

    Wireframe

    @bernhard, here's a quick test based on your hook approach: $wire->addHookBefore('Wireframe::render', function(HookEvent $event) { $event->view->setLayout('default'); }); At least from init.php this works as expected. In my own projects I would rather set this in Controller or wireframe.php, though, since this is a little unexpected (and impossible to override without modifying the custom Page class itself, though not sure if that's a problem for your use case.)
×
×
  • Create New...