Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by ESRCH

  1. I made a quick attempt at replicating the issue, but it worked for me. I unfortunately don't have the time to work on this further today, so if someone else has an idea how to solve this...
  2. I'll try to replicate this problem on my side , to see whether I can understand it . However, I have a few questions: - Which version of Processwire are you using ? - What are the fields types of the fields on the product template - When you create an order on the English backend, and then view the order in the back-end in English (by setting your profile language to English), do the order items appear? – Do you have the same problem if you create the order in the chs front-end ? Do the order items then not appear in Chinese simplified, but appear in English and default languages ?
  3. It is a core module, but you have to install it. It's in Modules > Core > FieldType > Profields: Page Table, and you click on Install.
  4. Hmmm, I don't have much time to test myself for the moment, but in your initial code to create the order, try saving the order before adding the order items: Add $p->save(); before foreach($session->get("cart_item") as $cart_item) { Also, I don't see you add a parent to the page during the creation. It might not be necessary, but you can try to see whether this changes anything.
  5. To track how many times a file has been downloaded, the basic process is the following: Have a field to store this information. Increment this counter each time someone downloads a file. Sorry for being so generic, but to be more specific, it would be helpful to have more information: Do you need to track the number of downloads separately for each file? Do you need to track the number of downloads separately for each user? How are files downloaded? It would also help to be more concrete about your use case (what type of site you are building, what type of files your users are downloading on which type of page), so that we can make a concrete example to help you
  6. Since the order items are displayed in two languages, the order items must be created. Can you show the code where you retrieve and then display the order items on the front-end (after clicking on the order in the dashboard)? Since the order item is completely skipped in English (not just displayed without text), it seems like you are using a filter in the loop (something like "if (!$product) continue;"), and there is a problem with this filter in English. If you echo $order->order_items->count(), does it show 0 (nothing) or 1? Also, is there a reason why you use a text field rather than a page field for the product_id on the order_items repeater? Finally, in the code that you pasted above, you wrote $p->save() within the foreach loop. I think you should be able to do that only once under the loop.
  7. It's a very nice website indeed. I just had an issue while viewing the site from my mobile phone (Chrome on Android): there appears to be no background on the navigation, so it is very hard to read depending on the scroll position. I would suggest to add some kind of background color to make the navigation links more visible.
  8. In this case, I would actually suggest to create a new field for the order number, since it complicates things to have a multilanguage field for this value. And as a multilanguage title doesn't make much sense for an order, you could make the title not required and hidden (under the visibility setting) for this specific template.
  9. Indeed, no hook, I hadn't read it through thoroughly enough and had assumed module = hook. And your solution is indeed less complicated, I think I'll replace mine by yours, it makes the code much easier to read
  10. I had the same problem,, and there is actually a way to access the profile language without using a hook by calliing loadPageField function of a Fieldtype, which fetches the data directly in the database: $languageField = $fields->get("language"); $profileLanguageId = $languageField->type->loadPageField($user, $languageField)[0]; $profileLanguage = $pages->get("id=$profileLanguageId");
  11. That's weird indeed. Is there no other message above the notice that you mention? Did you install a module that hooks into ProcessPageEdit or maybe ProcessUser?
  12. You should normally not do this, but I'm assuming that you set System on a page that you created, and that you want to remove this setting. The way to do this with the API is to do as follows: // Assuming that $page refers to the page for which you want to remove the status // Enable overriding the system status flags $page->status = $page->status | Page::statusSystemOverride; $page->save(); // Change the system status flags $page->status = $page->status & ~Page::statusSystemID; // If you want to uncheck the first system checkbox $page->status = $page->statux & ~Page::statusSystem; // If you want to uncheck the second system checkbox $page->save(); // Disable overriding the system status flags $page->status = $page->status & ~Page::statusSystemOverride; $page->save(); If it's just to correct a mistake, the more straightforward way to do the change is by modifying the database directly: In the database, find the right page in the pages table (you can find it easily by name or by id, which is indicated in the url when you edit the page). If you want to remove the first system flag, subtract 8 from the value in the status column (so if it's 9, it should become 1). If you want to remove the second system flag, subtract 16 from the value in the status column (so if it's 17, it should become 1). If you want to remove both, simply combine the operations by subracting 24. I hope this helps!
  13. Glad it solved your problem. Indeed, it's a pretty Swiss thread Though Swiss German would be a little difficult, I'm from Geneva... German would be fine
  14. The problem with the CustomLogout module was that we were using an anonymous function in the hook (the function($event) {...} is an anonymous function), and according to the PHP manual (here, under Changelog), PHP version 5.3 didn't allow using $this within such anonymous functions. So we had to use the "traditional" syntax for hooks, which uses a method of the module. The reason why the SiteHider module is called without needing to install it is probably because it wasn't uninstalled correctly the previously, so it is still in the database (if you look in the modules table in your database, you can probably find the SiteHider module). Before deleting a module from the /site/modules folder, you should always uninstall it first by clicking on its name in the modules list, selecting Uninstall and clicking Save. This will remove the module from the database. I see that I did a typo in my code, there is a > missing: it should be $this->config->styles->add(...); Also, the line above should be if ($this->user->name !== 'selina') because the ! operator has a higher precedence as the === operator. I hope that this solves the problem
  15. Indeed, though after some research, they added support for $this in PHP 5.4, which is why it works on my local server (I have PHP 5.4.7).
  16. Hmmm... I wonder if it's the inline function. Try this code instead for each module: <?php class CustomLogout extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'Custom Logout', 'summary' => 'Redirects to a custom login page after logout', 'singular' => true, 'autoload' => true ); } public function init() { $this->addHookAfter('Session::logout', $this, 'hookAfterLogout'); } public function hookAfterLogout($event) { $this->session->redirect($this->pages->get('/login/')->url); } } <?php class SiteHider extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'SiteHider', 'summary' => 'Hide Sites in CSS per User Roles', 'singular' => true, 'autoload' => true ); } public function init() { $this->addHookBefore("ProcessPageList::execute", $this, 'hookBeforePageListExecute'); } public function hookBeforePageListExecute($event) { if (!$this->user->name === 'selina') $this->config-styles->add($this->config->urls->templates . "css/sitehide.css"); } } Also, be careful with where you put the semi-colons (. In SiteHider, you had put it just after the if, which is a problem.
  17. For ProcessLogin: Did you put your custom login page under the Admin page? You should avoid doing that if you want people who have not logged in to access it so that they are able to login. I am a bit stumped with your errors. Could you please paste the exact code from the SiteHider.module and the CustomLogout.module files? Also, which version of PHP are you using?
  18. You can add anything you want in /site/templates/admin.php, which is the file that is first called when accessing the admin. Incidentally, this is actually also a place where you can add hooks that pertain only to the admin (though it is generally cleaner to do so in a module).
  19. I didn't realize that your post had two parts with two different questions, sorry For the logout problem, I would need to know more about the error. There normally isn't a /login page in ProcessWire from the start, so I'm surprised that this would be an issue. At the end of th error message, you can see the message that the "Error has been logged". This means that you can find this error in /site/assets/logs/errors.txt. So try doing it again, and look at the last error in the file, it should give you some indication on how to solve the issue. If not, just post the error here, as well as the exact code from the module if you adapted it.
  20. The problem is most probably the $this->user->isSelena() function. I understand the confusion, since $this->user->isSuperuser() gives the impression that you can use any user name, but it's not the case. isSuperuser() is a built-in method of the User class (you can find it on the cheatsheet under $user / User methods). If you want to allow only a specific user with the username "selina", you would do if (!$this->user->name === 'selina') This should hopefully do the trick. You should also add a semi-colon after the }) on the third line from the bottom, or you'll get another error
  21. The code from my previous post generates a simple array of editor names, over which you can loop, for example like this: // $editorials is the array from the code above foreach ($editorials as $editorial) { echo $editorial; } The $lastEditorial variable is simply used to avoid duplicates: In the code of the previous post, each iteration first compares the editor ($item->editorial) with the value it had for the previous iteration ($lastEditorial), and if it is not the same, it include it in the new array ($editorials[] = $item->editorial). Then at the end of the loop, the $lastEditorial is updated to have the new value. So using the data that you gave, the iterations go like this: "Abada" !== "", so add "Abada" to the $editorials array. Set $lastEditorial to "Abada" "Abada" === "Abada", so don't add the new "Abada" to the loop. Set $lastEditorial to "Abada" "Abada" === "Abada", so don't add the new "Abada" to the loop. Set $lastEditorial to "Abada" "Academy of Mathematics" !== "Abada", so add "Academy of Mathematics to the $editorials array. Set $lastEditorial to "Academy of Mathematics" "Chinese Academy" !== "Academy of Mathematics", so add "Chinese Academy..." to the $editorials array. Set $lastEditorial to "Chinese Academy..." etc. The result of this all is to have an array of unique editors. But if you really just want to echo the editors in place, you can shorten your code to one loop (I also reduced the number of variable assignments): $editorials = array(); $lastEditorial = ""; foreach($pages->find("template=item, editorial!='', sort=editorial" as $item) { if ($item->editorial !== $lastEditorial) { echo $item->editorial; $lastEditorial = $item->editorial; } }
  22. Wow, brilliant idea, that definitely makes the templates cleaner!
  23. As Macrura pointed out, seems to indicate that you have not linked the widget template with the banner.php file. When using $widget->render(), Processwire will check the template of the $widget Page object (I assume it's the widget template), and use its template file to render. If it doesn't have any (i.e. if you didn't set a template file), it will simply return an empty string. What you would need to do is manually set the template file to use for rendering like this: // Assumes that "banner.php" is in the /site/templates folder $widget->render($config->paths->templates . "banner.php"); But I think that the better way to do this is as follows: Create a widgets-catalog template with no template file, but with access restrictions to prevent anyone from viewing directly this page and its children. Then create a "Widgets catalog" page. This will be the parent page for all your different widgets, whatever their type. Create different templates for different widget types (e.g., text-banner, image-banner, etc.) which each have the relevant fields (file + link fields for the image-banner, text + link fields for the text-banner, etc.). Each of these templates has a corresponding template file in the /site/templates folder. Create a widgets page field, with selectable pages set to having "Widgets catalog" as the parent page. Add the widgets field to the home page and any other pages that you want. Now you can select any widget type with the widgets field, and use $widget->render(), which will use the correct template to render.
  24. As I understand it, you have different items the same editorial (as a text field), and you want to get an array with unique editorils, right? If so, here is the code to get this: $editorials = array(); $lastEditorial = null; foreach ($pages->find("template=item, editorial!='', sort=editorial") as $item) { if ($item->editorial !== $lastEditorial) $editorials[] = $item->editorial; $lastEditorial = $item->editorial; } $a->unique() filters elements using the PHP array_unique function, which compares elements according to their string representation. Since the result of $pages->find() returns a PageArray containing Page objects, and since the string representation of a Page object is its id, $pages->find(...)->unique will return unique pages, without considering the editorial field (two different pages with the same editorial will be different, since they will have different ids). That's why $a->unique isn't usable in your case.
  25. While you can put hooks anywhere, the cleanest approach is usually to create a separate module for it. In this case, the code I gave you is the code for a complete module, so here's what you should do: Create a CustomLogout.module file in the /site/modules directory (you can rename the file if you want, but it must have the same name as the class that it defines). Paste the code from my previous post. Go to Modules > Refresh. The new module should appear, and you can click on install, to install it just like any Core module. After doing this, the redirection should work. To hide the login page, I would suggest using CSS to hide a specific item in the PageList. You will notice when examining the HTML generated by the PageList that each page is actually a div with (among other things) a class of "PageListID1234", where 1234 is the id of the page. So if your login page's id is 1025 for example, you could create a custom.css file (in /site/templates/styles) with the rule .PageListID1025 { display: none !important; } You now have to include this CSS file when showing the PageList page, but only when the user is not the superuser (or any another rule based on permissions or roles). You can try using the Admin Custom Files module and checking the different options there. I must admit that I have never used it, so I can't help you much. Otherwise, you can make a module (or include it in the above module in the init function) with this hook: $this->addHookBefore("ProcessPageList::execute", function($event) { if (!$this->user->isSuperUser()) // You can change the rule here $this->config-styles->add($this->config->urls->templates . "styles/custom.css"); // Adapt the link to the file }) As a final note, you can indeed add hooks (the $this->addHookAfter(...) call) more or less anywhere, but the syntax will change: Within a class (such as a module as defined in the code in my previous post), the hook is called on $this, e.g., $this->addHookBefore("Page::render") Outside of a class (such as in a template, or the admin.php file), the hook is called on wire(), so wire()->addHookBefore("Page::render"). You can also call addHook on an instance of a class, like $page->addHookBefore("render"). What you tried to do by including my entire module code in the default.php file wouldn't have worked, because the autoload looks for classes in files that have the same name as the class (so the CustomLogout class must be in the CustomLogout.module or CustomLogout.php file). Learning about hooks requires a little effort, but once you get it, it is very logical and it really opens the door to doing whatever you want with Processwire. The hook system is really well built, and most aspects of the application can be hooked into. I would suggest the following to learn about hooks (that's what I did): Read https://processwire.com/api/hooks/ Read http://wiki.processwire.com/index.php/Module_Creation Read through the HelloWorld.module file in your /site/modules directory. It's a sample module that shows very simply how to create a basic module.
  • Create New...