Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by Inxentas

  1. @OllieM Not long at all. Following the steps above (which is basically just doing the smart thing and backup up old files) it took me a couple of minutes at most.
  2. Ah, got the bugger! I was setting the Page template using a string rather then grabbing a full instance of the template. I think this used to work in a previous version or something, but this is way cleaner anyway: $new->template = $this->templates->get('page-address');
  3. $_POST is an associative array of variables passed to the current script via the HTTP POST method when using application/x-www-form-urlencoded or multipart/form-data as the HTTP Content-Type in the request. Not when using application/json. For json, you'd typically do something like this: $data = json_decode(file_get_contents('php://input'), true); AJAX is Javascript, and Javascript libraries often use the JSON method. I'm not sure if jQuery does, but I had the same issue when working with AngularJS in the past.
  4. I'm writing a class file for an Account page that parses a form whenever a certain 'action' is set in $input->post. The template contains forms to save an existing address, and one to add a new address. Saving the address works great, but my code bugs out the moment I attempt to create a new one. Here is the code I am using in the class file: <?php namespace ProcessWire; /** * This is the class tied to the page_account template. */ class PageAccountPage extends WebshopPage { public $addresses; public function __construct($page) { if($page->input->post->action) { $id = (int)$page->input->post->id; $title = (string)$page->input->post->title; $street = (string)$page->input->post->street; $zipcode = (string)$page->input->post->zipcode; $city = (string)$page->input->post->city; $phone = (string)$page->input->post->phone; $email = (string)$page->input->post->email; switch($page->input->post->action) { case 'save': // find page $a = $this->pages->get($id); $a->of(false); $a->title = $title; // populate fields $a->webshop_address_street = $street; $a->webshop_address_zipcode = $zipcode; $a->webshop_address_city = $city; $a->webshop_address_phone = $phone; $a->webshop_address_email = $email; // save page $a->save(); break; case 'add': // create page $new = new Page(); $new->name = $title; $new->parent = $this->user; $new->template = 'page-address'; $new->save(); // populate fields $new->title = $title; $new->webshop_address_street = $street; $new->webshop_address_zipcode = $zipcode; $new->webshop_address_city = $city; $new->webshop_address_phone = $phone; $new->webshop_address_email = $email; // save page $new->save(); break; } } $this->addresses = $this->user->children("template=page-address"); parent::__construct($page); } } The problem sits in the add case of the switch. I get the following error: Trying to get property 'fieldgroup' of non-object in C:\wamp\www\fransvanberendonk.com\vendor\processwire\processwire\wire\core\PagesEditor.php on line 370 To be clear, the template 'page-address' is one that gets created on module install through code. That code also modifies the User template to allow children in the form of 'page-address' pages. 'page-address' can have a 'user' as a parent. I'm not sure if it's relevant (since it all seems fine from the backend), but here is the code that does that: // set relationships for page_address $page_address->parentTemplates([$page_order, $user]); $page_address->noChildren = 1; $page_address->save(); // set relationships for user $user->noChildren = 0; $children = $user->childTemplates; $children[] = $page_address; $user->childTemplates($children); $user->save(); I also get a message in the CMS after the page bugs out: PagesLoader: You must assign a template to the page before setting field values (title__data) [pageClass=ProcessWire\Page, template=] Which a weird message because the pageClass of the page I'm trying to save is PageAccountPage, which inherits from WebshopPage, which interits from Page. I tried not setting the title before the first save() and filling the name value instead, but to no avail. I'm not sure what goes wrong here. DISCLAIMER: I am aware I should sanitize data first. I wanted to get the thing working first, this code is WIP off course.
  5. Thank you Ryan! I have been dilligently but blindly turning Output Formatting on and off in my code for years now, it's nice to know how it all works below the hood. ๐Ÿ˜…
  6. Yeah I'm still debating where it belongs, I just thought it nice to encapsulate them into the page classes. Why did I not think of using it as a static property? That seems a good idea. That way I can still have the constructors be responsible for it's auto-instantiation on every page that extends WebshopPage ๐Ÿ™‚ but be sure there is only one instance.
  7. I have a weird issue regarding page classes. For my module, I'm using a couple of those. For clarity, class names are in bold while template names are in italic. The WebshopPage class extends the Page class and is the class from which the others extend. PageCheckOutPage is the class for the CheckoutPage template and extends WebShopPage. Now I've added the following constructor to WebshopPage, in order to make sure every page that extends it has scope on an instance of the (custom) Cart class: public function __construct($page) { $this->cart = new Cart($this->session); parent::__construct($page); var_dump( get_class($this) ); } Now what happens is that the constructor of the Cart class is called twice when I view a page with the CheckoutPage template. Yet the PageCheckoutPage class doesn't have a constructor of it's own, so I would have expected it to fire it's base class constructor once. Yet with the var_dump above, I get the following result: C:\wamp\www\webshop.com\public_html\site\classes\Cart.php:14:string 'Cart constructor' (length=16) C:\wamp\www\webshop.com\public_html\site\classes\WebshopPage.php:16:string 'ProcessWire\PageCheckoutPage' (length=28) C:\wamp\www\webshop.com\public_html\site\classes\Cart.php:14:string 'Cart constructor' (length=16) C:\wamp\www\webshop.com\public_html\site\classes\WebshopPage.php:16:string 'ProcessWire\PageWebshopPage' (length=27) Instead of the extended class simply using the base class constructor as I would have expected, both the base class as the extended class fire a constructor seperately. Now I have a hunch that this happens because each page's parent is also instantiated, and thus it's constructor is ran. I can tell from nesting pages and then using var_dump($page->name) instead. Is this assumption correct? Perhaps there is a better way to ensure that all pages that extend WebshopPage have scope on an instance of the Cart class? I'd rather not have this constructor run as many times as a given page has parents.
  8. Ah, my bad. But that does mean this solution should work. The second-last post in that topic tells you exactly what to do. As other people pointed out, it's probably a good idea to make a backup of the files and the database before you do. I do agree though, PW is a fantastic piece of software that rarely runs into these kind of issues, especially if you keep upgrading your website like... once a year. This is also a reason why I vastly prefer it over Wordpress, which is likely to whine about one of it's many plugins needing an upgrade every few weeks. PW has most of that "plugin" stuff in the core already. I can serve most of my clients without using any custom modules: I only install the ProcessUpgrade module for my own convenience. The AdminThemeUikit issue on some old sites is the only instance of PW ever making me manually update anything on the backend. I regularly say no thanks to well-paying development jobs on LinkedIn because I want to keep using ProcessWire. That says something.
  9. Heyyyy https://www.orchardheightsdental.com/ is back up! I dunno what you did, but it worked! Nice! ๐Ÿ˜
  10. Thanks for your replies, dear people! I am going to take a look at the suggested JS libraries / frameworks and see what's most suitable for the application. Your descriptions of Alpine and htmx's features were very helpful. It sounds like Alpine would be something I could learn quite easily, but htmx's SEO advantage might be something I end up liking very much. One last question though: do module developers usually supply the JS code with the module, or do module devs tend to lean on a CDN? Performance and footprint is less important to me, but I like the idea of having the module work "out of the box" without requiring code from a CDN, and offering alternate solutions for client who want custom designs for everything.
  11. I get this error all the time on my development server. 9 out of 10 times I had simply forgotten to change config.php, and my site would try to access the database using my local config! Could it be that you've accidentally overwritten that file with your local version? I ended up implementing a switch in config.php that checks what domain we're on, and sets the config variables according to the current domain. Should it be an upgrade issue, you can get into some trouble when upgrading through the ProcessUpdate module because the JS files for AdminThemeUikit are missing! I had this issue a while back with a bunch of sites that were suddenly running on PHP8 due to a decision of the hosting provider, and some friendly people on this forum helped me update ProcessWire manually to get around this issue. You can find the topic here.
  12. I have a pretty broad question about module development. At the moment I have a module (a webshop) which contains some template and class files, which the module will move into the relevant folders (site/templates and site/classes) on install. It will also create a few pages to create the initial page structure, as well as a Process that I place beneath the Admin page. Now imagine that a page with the "product" template contains a form that posts the product ID and a quantity to itself, or another page which then redirects the request. So far so good, that would work. I would like to make it so the module works "out of the box" with some bare-bones templates the developer can modify / style after install. What I am not so sure about is how I'd typically create inline interaction that works "out of the box". On most webshops, a user might click the "add to cart" button and then some Javascript fires, adding the product to the cart through an AJAX call. Now, I could make it so some file (let's call it _webshop.php) is prefixed to a template instead of _main.php, that ensures any Javascript I supply gets loaded on pages that have such interactions. But I am unsure what kind of Javascript to use for AJAX related stuff in the frontend. I would have no issues having the module copy a .JS file into the /template/scripts folder, but I'm unsure on how to structure the JS itself. I've developed apps with Vue3 and (in the olden days) AngularJS or jQuery, but I also see some AJAX interaction in ProcessWire's page tree. Whenever you click on a page that has children, I can see an URL gets called in the Network tab of Chrome's inspector. That means there must already be a methodology the backend uses. Looking at the <head> section of a backend page, I suspect this was done using JQuery. Here is an example url I plucked from the inspector. It's clearly a GET, whereas I would be using POST, but that's just a detail. /page/list/?id=1110&render=JSON&start=0&lang=0&open=undefined&mode=actions Now I am hesitant to use JQuery (as anyone used to Vue would, I reckon). I was wondering if anyone else has ideas on how to best implement frontend AJAX interactions for inline actions, when working in the context of a module? I've considered to write a Vue3 app and simpy have _webshop.php load Vue3 from a CDN, but this feels "messy" to me and not very self-contained. I would also want to prevent introducing a whole Javascript framework, especially when the existing codebase already includes a methodology for AJAX calls. I know this "question" is pretty vague, but I had hoped the community could push me in the right direction. Thank you for reading my post.
  13. Yes! Well, not immediately. When I do this to the Process it still gave me an error, but when I used the argument in the lines that delete pages by their template (orders and order pages are deleted first) then it works. I still explicitly delete the individual orders by template before I delete their parent, but I'll experiment a bit with this technique. Again PW surprises me with it's simplicity. One last question: notifications are going to ask me to mark your post as the best solution. But I don't see any options for that. How can I do this?
  14. I've tried adding the hooks to the init method. I also used my own module name. This works. public function init() { $this->addHookBefore('Webshop::uninstall', function($event){ $this->deleteProcessChildren(); }); $this->addHookAfter('Webshop::uninstall', function($event){ $this->deleteProcesses(); }); } But alas, even when I explicitly set a BEFORE hook to delete all children... and an AFTER hook to delete the process itself... I still get the same message. Because I get that error, the module isn't truly uninstalled, but it DOES delete the children of the Process page. If I then attempt to uninstall it again, it suddenly works because the previous attempt deleted all children already. But whenever I try to do this in the same request, I get the message that the Process Page still has children, so somehow it's being called too early or something. I've added a $message to the loop that runs through the Process Pages children. As you can see it deletes the "orders" page (second line) before it tries to delete the Process page (last line). Webshop: deleteProcessChildren Webshop: process child deleted: orders Webshop: Deleted 0 Pages. Webshop: Deleted 3 Templates. Webshop: Deleted 5 Fields. Webshop: Permission 'shop-owner' deleted. Webshop: deleteProcesses
  15. I've tried this, and put a $this->message() call in the hooked methods for now. They are not called at all. The pages are also not "installed" but created in the API like this: $admin = $this->wire()->pages->get("title=Admin"); $webshop = new ProcessWire\Page(); $webshop->template = "admin"; $webshop->title = "Webshop"; $webshop->icon = "cogs"; $webshop->parent = $admin; $webshop->process = $this; $webshop->save(); $orders = new ProcessWire\Page(); $orders->template = "page-orders"; $orders->name = "orders"; $orders->title = "Orders"; $orders->parent = $webshop; $orders->save();
  16. I'm developing a module that installs a couple of nested pages beneat the Admin page (and assigns the module as a Process to them). In the install method, I create these pages from top to bottom. In the uninstall method, I do the reverse and delete all children before deleting their parent page. However, I get the following error message: ProcessWire: ProcessModule: Can't delete Page 1563 because it has one or more children. This is strange as the script makes sure that isn't the case, as these are all deleted. Afterwards, their children are indeed nicely deleted. I've done a couple of checks. When I first delete all children, and use $message to print out $p->children()->count that returns zero, as expected. Yet $p cannot be deleted after confirming it's zero, because "it has children". Does anyone have any idea why? Extra information: Beneath the Admin page I create a new page called "Webshop" and assign my module as a Process to this page. This creates a button in the menu that leads to the primary admin interface of the webshop, for which I use a view. This all works nicely. The module installs a template named "orders" beneath this page, as I was planning to collect webshop orders beneath that one. In the uninstall method, I make sure to first delete all pages of the template "order" and "orders" before I attempt to delete the Webshop Process page. On an unintall attempt, I get above error message, but when I check whether the page it references (1563) indeed has children, these are indeed deleted in accordance with my code. Only the Webshop page remains, and it's Process is (logically) empty.
  17. Thank you, that worked flawlessly! I was a bit scared of manually updating 4 production sites this way, but I managed to complete the task without any real issues.
  18. Hi guys, I have a few really old sites that never received their updates. ProcessWire version 3.0.62. Now I can install the ProcessWireUpgrade module and run it, but I get some errors: Method AdminThemeDefault::getClass does not exist or is not callable in this context And that's logical considering how old these sites are. At the time we created them, Reno was the default Admin Theme. I have tried installing AdminUIKit by coping a (recent) module into /wire, which gave me another error. I've tried putting the module in /sites, same error. Error installing module - AdminThemeUikit Failed to construct module: ProcessWire\AdminThemeUikit - Method AdminThemeUikit::setClasses does not exist or is not callable in this context --- I have a feeling PW is trying to run a method on the current admin theme, which doesn't exist because it's only in the new admin theme. Can I somehow fix this and update the websites?
  19. For me the SMTP thing is not really negotiable, sometimes companies use some mail setup that requires it. I've used both PHPMailer and the module, and sometimes the module even wins out. Thanks for the "post-install-cmd" tip, that might work well for my situation... being that moving the vendor folder outside of the webroot isn't mission critical. I'm in that situation where I can do whatever I want, but I do have to work with 101 different mail clients and shared hosts so I prefer to add my most used packages to a new project by default. Thanks everyone!
  20. I took a look at the WireMail class and what I miss is SMTP support (although I might be wrong here, I simply didn't see anything in the docs that implies SMTP is supported out of the box). I could also use the module named WireMailSMTP for example, but no matter how you cut it that would involve installing the module manually for each website. It's preferable to me to manage dependencies with Composer and reuse our existing mail scripts, then installing PW modules manually for each project.
  21. Thank you, I found that article already though, and I found it to be a little messy of a process as well. On top of that I would like to use autoloaded stuff in my modules so that approach isn't super suitable for me. I have decided that for now, I'll just modify the existing index.php as that file won't change too often.
  22. Hello guys, I've started to implement Composer in my workflow more seriously and I'm looking for the best way to include more then just ProcessWire. We often use a few extra bits and bobs (such as PHPMailer) and I'm not sure how to best treat PW as a Composer package and how to get the vendor folder outside of the public folder. Now whether I do composer require or composer create project, I get PW as a full project including it's own composer.json and .lock files with it's vendor folder sitting next to the wire and site folders. Now I've done some experiments, such as moving the folder manually and changing the require statement in index.php, but that feels messy to me. I've also created a new empty project with my own folder structure, and then copied vendor/processwire/processwire into the public folder for installation, but I still need to faff around with PW's actual code. Is there a neat way to create a Composer project (or inherit the existing one) and use Composer commands to somehow get the vendor folder to sit once directory up from it's default directory?
  23. Yes, and that worked perfectly! Thank you @BitPoet. I was hesitant to change the .htaccess file but truth be told, this is kind of a legacy project, so in the end I did not do much research on what that would affect. Are there any PW related issues I should take into account? PS. I received a mail asking me to click a "mark as solution" button. I wanted to mark your reply as the solution but I'm not seeing that button. I fear I'm going blind.
  24. Hello there. I have an issue with a PW installation on some crappy shared host. A few days ago the site stopped working. So I checked the error logs, which said: Option FollowSymlinks not allowed here And logically, PW's .htaccess file says: Options +FollowSymLinks So it appears that FollowSymlinks is suddenly no longer allowed on this server. I rarely have to deal with server settings, but is the impression that PW simply needs FollowSymlinks to be allowed. Is this the case? Would it be valid to state that this server isn't suitable for a PW installation anymore, because the host no longer allows SymLinks? Would that statement be correct? I've never had the pleasure of a shared host suddenly no longer allowing SymLinks out of the blue, to be fair I am not entirely sure how those work. I can run the site on my local and test servers just fine: it's just this shared host that's been giving me grief for the last few days. The homepage could be reached but every child page just gave me a serverside 404 (not the 404 you'd expect from PW itself).
  25. I have a strange occurence which I have a hard time explaining/debugging. I have a module that contains a .JS file. I load this JS file using a hook, that is called when the template != admin... meaning it will only be called on the frontend. This works on my LIVE environment, but my DEV environment seems to decide to load the file somewhere. Since it contains a script that prevents scrolling, I cannot scroll in the admin. Is there a circumstance in which modules load JS files placed in their folder? Perhaps when it has the same name of the module under certain PHP versions?
  • Create New...