Jump to content

Jan Romero

Members
  • Posts

    695
  • Joined

  • Last visited

  • Days Won

    20

Everything posted by Jan Romero

  1. Welcome to PHP lol https://www.php.net/manual/function.preg-replace.php https://www.php.net/manual/function.str-ireplace.php https://www.php.net/manual/function.str-replace.php https://www.php.net/manual/function.mb-ereg-replace.php (just use this) https://www.php.net/manual/function.mb-eregi-replace.php (or this) https://www.php.net/manual/function.mb-ereg-replace-callback.php https://www.php.net/manual/function.substr-replace.php https://www.php.net/manual/function.preg-replace-callback.php https://www.php.net/manual/function.preg-replace-callback-array.php
  2. Only if you tell it to: https://curl.se/docs/manpage.html#-L You’ll also have to increase the maximum number: https://curl.se/docs/manpage.html#--max-redirs
  3. Hi. Sorry about the short reply, but does the Permission “profil-edit” not do what you need out of the box?
  4. Oooh, the page name settings could be a select in the installer if there are enough useful and distinct ones. That would be dope. Definitely a super common need in Germany. @ryan shameless plug, since you’re going to be working on the installer, I opened a small PR inspired by a recent thread for your consideration ?
  5. y not function get_zehner($page) { return wire('pages')->count("parent={$page}, template=mitglied, mitglied_kategorie=Zehnerkarte"); } or even function get_zehner() { return wire('pages')->count("parent=/mitglieder/, template=mitglied, mitglied_kategorie=Zehnerkarte"); } I would additionally rename the function to something like anzahlZehnerkarte, because I would probably expect "get_zehner" to return a PageArray.
  6. Please show how you call get_zehner(). It looks like you’re passing in a Page object $page, but Page has no method count() that takes a selector. You can only call it without any arguments and it will give you the number of children of that page: https://processwire.com/api/ref/page/count/. Perhaps you want to use pages()->count($selector)? Also, this line is outside of <?php ?> tags and will not be executed: $mitglied->mitglied_kategorie = $_POST['Kategorie']; Also, please indent and use the forum’s code feature.
  7. Hi! If you want to accept any numeric value, you can just use Fieldtype Integer, Float or Decimal. As long as you don’t choose the HTML5 input, it will accept spaces and strip them when saving the page. If you still need further regex validation, it may be interesting to add regex validation to the numeric field instead of using a text field and dealing with the spaces. If you want to use Fieldtype Text, your idea of hooking ProcessInput seems good. Perhaps also look into hooking Fieldtype::sanitizeValue instead. Or maybe Fieldtype::sleepValue. All of these options will remove the spaces once when saving and then never display them again. If you want to show the spaces to editors for readability, consider horst’s idea or (assuming they’re deterministic like thousands separators) put them back in somehow. Fieldtype::wakeupValue will work, I imagine. Fieldtype::formatValue wouldn’t be the right choice here, because, as you noted, it only formats for output on the page, not for input fields in the page editor.
  8. I think the easiest and arguably cleanest way to detect this would be wire('page'). In the Admin it will give you the system page with the ProcessPageEdit process, ID 10. When it’s your API it should be whatever page you set up as the endpoint. Or you could look at input()->url or something.
  9. Indeed… Like I said, the code is the best documentation. So I guess it’s $page->setAndSave( [ 'title' => "($id) $template_label | $address, $ort" , 'name' => "$id $template_label $address $ort" ] , null , [ 'noHooks' => true ]);
  10. No, because unfortunately the docs don’t show an example with multiple fields and the options array. I may be wrong and it’s a little difficult to see on mobile, but I would say it needs to be two separate arrays, like this:
  11. Come on, man, you can do this ? That’s the same error message from before. Also, like I said, I’m pretty sure you just had to move the one ] to a different place. The number of brackets was correct. I haven’t been on the computer much today. I can look at the language stuff tomorrow, if you want. Btw a good “trick” is to just skim the actual source code of PW methods. I often find the docs a little lacking, unfortunately. Ryan’s code is quite readable, and usually one is only interested in what happens to the arguments, where best to hook etc. Somewhat superficial stuff like that, if you will, so it’s not too bad. For example, it seems your code is mixing up the fielname/value array and the options array when calling setAndSave(). PW functions often takes multiple different types in multiple different places, which can be a blessing and a curse.
  12. Hi, have you achieved your desired results yet? Just a quick note: if you change multiple fields on one page it’s probably more efficient to just change them individually and then call $page->save() once, instead of using $page->setAndSave() multiple times. Read the docs for more info. Also be aware you’re changing the page’s name every time (well, kind of) Address or Ort change. That can be desirable, but if the page is accessible at its default URL, that URL won’t be stable, and as everybody knows, cool URLs don’t change. I’m not sure I completely understand your requirements, but it looks like it should kinda work? Obviously when you generate the page name in Pages:added and save it, the Pages::saved hook will be triggered and override that change, so you might want to run the first one with ['noHooks' => true] or just get rid of it.
  13. Just to add to the reports, I have coincidentally encountered this issue just minutes ago and thankfully remembered this thread. Bernhard’s/Robin S’s fix worked for my image. It was EXIF orientation 6 (confirmed this to be in line with the specs. 90° CW to make it upright), shot on some old-ish Samsung phone and uploaded without client side resizing. The original showed up fine, but the generated variations were upside-down. Thanks!
  14. Umm yeah I mean did you run that code? From the looks of it I would say it should rain errors, but if it works for you, that’s great! Allow me to step through and critique it anyway: $this->addHookAfter("ProcessPageAdd::buildForm", function(HookEvent $event) { //get the result of the hooked method, which is a form (class InputfieldForm). //it’s also the only form we care about here, so calling it $form is fine. $form = $event->return; //this gets the parent page, so we can stop doing anything unless we are //at the correct position in the page tree. good. //note the indent I added, though ;) $parentField = $form->getChildByName('parent_id'); $parent = pages()->get($parentField->value); if (!$parent->matches('template=dashboard_customer')) return; /*this is going to error, because $page does not exist here. you CAN *call the current page by writing any of this instead of $page (you *don’t WANT to do that here, though. read on before you change this): * - page() (if you have functions API enabled in config.php) * - wire('page') * - $wire->page * - $this->page * - $this->wire('page') *see https://processwire.com/docs/start/api-access/ *since this is confusing and for all other reasons stated in that link *i would recommend simply always using page() etc. */ $pageid = $page->id; /*this is just weird and unnecessary unless your template labels contain *slashes and end in .php, which in itself seems weird and unnecessary? *if you want a template’s name (usually the same as the template file *without the extension), just use $template->name. * ===> importantly, none of this makes sense because when this code runs, you <=== * ===> cannot know the page’s id nor its template!!! <=== * ===> you want to give the page ITS OWN id for a name. this is impossible to <=== * ===> know at this time, as the page has not been created yet. the template, <=== * ===> likewise, has not been chosen by the user. this code BUILDS the drop <=== * ===> down field that lets the user choose a template! <=== */ $template = basename($page->template->label,'.php'); //this was my suggestion to get the page name field from the form, however, //as we see below, you have discovered a better way, which is great! $nameField = $form->getChildByName('_pw_page_name'); //this was my suggestion to make the field invisible. as you’ve discovered, //you could also use $nameField->collapsed = Inputfield::collapsedHidden. //there is a difference, though! AFAIK, Inputfield::collapsedHidden will //completely REMOVE the field from the form output, so you can’t change it //with javascript. that was my main reason to use the class instead, //because you may actually want to do that. $nameField->wrapClass = 'InputfieldHidden'; //this shouldn’t work because of the $page business above. I guess it will //result in "() " because neither $pageid nor $template can have any //reasonable values. //moreover, you can’t use parentheses or spaces in page names, so they will //get stripped or converted to - anyway. remember this is the page name, not //the title. $nameField->value = "($pageid) $template"; //this is unnecessary because we have already put $event->return into the //variable $form. $titleField = $event->return; //this is great, but you should remove the above line and use $form instead. if(!$titleField->has('title')) return; //this is a great way to get the title field from the form! also a great way //to get rid of it. it will still allow you to put a value inside at this point. $titleField->title->collapsed = Inputfield::collapsedHidden; }); Now to do what you really want, you need to hide the fields you want to hide in this ProcessPageAdd::buildForm hook and use an additional hook to set the values. That second hook will have to run at some point when all the things you need to generate those values are known. Since you want to use the page id (there is no real reason to have the page id in the name that I can think of!), that point has to be AFTER the page has been saved. That’s fine, but if you contented yourself with just the template name + a number generated by PW, you could use the Javascript option I suggested above and obviate the second hook. It’s no biggie either way, so whatever. You could hook Pages::added, making your entire code look like this: $this->addHookAfter("ProcessPageAdd::buildForm", function(HookEvent $event) { $form = $event->return; $parentField = $form->getChildByName('parent_id'); $parent = pages()->get($parentField->value); if (!$parent->matches('template=idee')) return; //using the neater way to edit the field! $form->_pw_page_name->collapsed = Inputfield::collapsedHidden; $form->_pw_page_name->value = 'this is a temporary name nobody should ever see, just leave it'; $form->title->collapsed = Inputfield::collapsedHidden; //no default value for the title }); $this->addHookAfter('Pages::added', function(HookEvent $event) { //this time, we can get the page that has just been created! $page = $event->arguments(0); //same as above: only run under certain parents if (!$page->matches('parent.template=idee')) return; $page->setAndSave('name', "{$page->id}_{$page->template->name}"); });
  15. I agree wit wbmnfktr, however, I also tend to agree with OP that the installer could be made more fool-proof. We’ve had a lot of threads over the years with people getting 500s trying to access the Admin (or anything other than the front page) right after installing PW. OP’s case may be especially niche, but .htaccess adjustments to get PW running aren’t really. It might be a good idea for the installer to ping the chosen admin URL and display a warning with some instructions if it doesn’t get a 200. Also, from a UI perspective, looking at this screenshot I just see a bunch of tick marks. We all know users don’t read anything you put in front of them, and this only encourages us to believe no further action is needed. IMHO, the “Complete & Secure Your Installation” section shouldn’t have check marks. Maybe it should even be a different color to emphasise its to-do-list nature and differentiate it from the mere success messages. “Get Started” is mostly to-do as well, albeit more optional.
  16. Right, so… We have a couple of different problems here. The template label thing is just a simple programming mistake. I’m sure you can figure it out by looking at the last three lines again. Hints: 1. on $templates->get() 2. on API access in general (you can’t use $templates inside a function. This is an unfortunate ProcessWire quirk that makes things unnecessarily difficult for beginners. You just have to be aware of it OR simply use the functions API everywhere) Now the ProcessPageAdd::buildForm hook. Let’s look again at what we’re hooking and what we want to accomplish. Hooking after ProcessPageAdd::buildForm means that the hook code is being executed right after the Page Add Screen is generated. That is to say, the form that asks the user for the template they wish to instantiate under the given parent, if you will. This means that that code cannot know the user’s template selection. It can however know the parent page, i.e. the page of which the new page is going to be a child. So anything you do in the hook either happens in EVERY Page Add Screen, or you can make it depend on that parent page (which I called $parent in my example). It looks to me like you’re trying to skip the hook depending on the child template – this isn’t possible because that template has not been determined yet. If I understand the requirements right, you may want to do this: $this->addHookAfter("ProcessPageAdd::buildForm", function(HookEvent $event) { $form = $event->return; $parentField = $form->getChildByName('parent_id'); $parent = pages()->get($parentField->value); if ($parent->template->name === 'dashboard_customer') return; $nameField = $form->getChildByName('_pw_page_name'); $nameField->wrapClass = 'InputfieldHidden'; $nameField->value = 'Newpage'; }); Notice how I’m not using matching(). That function takes a selector string, so if you want to use it to test for a page’s template, you can probably do $page->matches('template=dashboard_customer'), but not $page->matches('dashboard_customer')! Now, if you must make the default page name depend on the selected template and also want to hide the name field from users, you have several options: Make the name field hidden the way we’ve been doing it and inject some Javascript to change its value whenever the selected template changes. Here you will still want to run the hooks only for some parent page where it makes sense. Adding the Javascript in ProcessPageAdd::buildForm could look like this: $form->appendMarkup .= '<script> const templateSelect = document.getElementById("template"); templateSelect.addEventListener("change", (e) => { const nameInput = document.getElementById("Inputfield__pw_page_name"); nameInput.value = e.target.options[e.target.selectedIndex].innerHTML; //set the name to the selected template’s label }); templateSelect.dispatchEvent(new Event("change")); //run the above function immediataly to capture the default value </script>'; Alternatively, hook ProcessPageAdd::processInput and determine the page name there. That’s the method that runs when you click „Save“ on the Page Add Screen, so at that point you’re committed to the selected template and parent. Still need to hook ProcessPageAdd::buildForm to make the name field disappear, though.
  17. The error happens because $page is not defined, so you can’t call matches() on it. Fixing it is slightly involved, because we’re hooking ProcessPageAdd::buildForm, which means you can’t just do $event->object->page. $event is the HookEvent. It has information about the hook itself, the affected object and in this case the return value. $event->object is the object whose method we’re hooking, i.e. ProcessPageAdd. ProcessPageAdd should know the parent page to which we’re about to add a child, but I’m not sure how best to access it. $event->object->page is the page ProcessPageAdd belongs to. This will be a system page with the ID 6. It’s just “this is the Page Add Screen”, so that’s not what we need. However, the form that PW has built contains a hidden field for the parent page which we can access: $event->return->getChildByName('parent_id'). This should contain the parent’s ID, but not the page object itself. So this might work: $this->addHookAfter("ProcessPageAdd::buildForm", function(HookEvent $event) { $form = $event->return; $parentField = $form->getChildByName('parent_id'); $parent = pages()->get($parentField->value); if ($parent->matches('dashboard_servicepage_totalrenovation|dashboard_service_bathroomrenovation|dashboard_service_extension|dashboard_service_demolition|dashboard_service_recycling')) return; $nameField = $form->getChildByName('_pw_page_name'); $nameField->wrapClass = 'InputfieldHidden'; $nameField->value = 'Newpage'; });
  18. If you want to have a bit of fun, I recommend the EXIF specs: 2.3 (2010) 2.3 (2012 revision, including fixes in the orientation part) 2.31 (2019) All of them say of orientation 8 “The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom,” so 90° CCW seems correct. Further down you can find such gems as “Orientation = 8 is equivalent to an arrangement that is turned Orientation = 3 90 degrees clockwise”. Skip to Orientation 3: “Orientation = 3 is equivalent to an arrangement that is turned Orientation = 6 90 degrees clockwise” … “Orientation = 6 is equivalent to an arrangement that is turned Orientation = 1 90 degrees clockwise”. Right. Thankfully, Orientation 1 is self-sufficient: “Orientation = 1 is created when 0th row of the coded image data stored in the Exif image file and the visual top of the display screen, and 0th column and visual left, will each be matched for display”. Hooray. I feel like I’m in an escape room.
  19. Ah, sorry, I could have noticed that yesterday, since it’s in the same line ? You’re using $template but haven’t defined a variable with that name. $page->template->label should work. Btw, when you do this if ($page->matches('customer_project')) return; make sure to go to that page’s settings tab and check the “unique” box to prevent any other pages from getting the same name (theoretically possible in other parts of the page tree). Additionally you can probably make this faster by comparing $page->name directly. The matches() function first needs to parse the selector string and figure out what to do with it. Alternatively, test the entire path with $page->path or $page->url, that way you guarantee uniqueness.
  20. Hi, I’m in bed but regarding maximum function nesting level, consider adding the noHooks option to your setAndSave call: $page->setAndSave('title', "($id) {$template->label} | $address", ['noHooks' => true]); I suspect you’re getting into an infinite loop because setAndSave triggers the hook on Pages::saved.
  21. I’m still not 100% on our ultimate goal here. Do you really want to see the IDs in the tree? If it’s just about the way pages look in the tree, you can configure that in the template settings. In the Advanced tab there is a setting called “List of fields to display in the admin Page List” that you could configure to something like ”({id}) {template.label} {date}“ to get pretty much what you’ve described. Depends on the default date output format that is set up in the date field. Obviously you can also just hardcode the template’s label instead of {template.label} since this is template-specific anyay. In any case, this technique is completely independent of the page’s title. In fact, pages don’t need to have titles at all. You can uncheck “global” in the title field’s advanced settings and it will stop showing up in the Add screen. If these pages don’t need titles at all, because a combination of other values is sufficient, you can then remove the title field from the templates entirely. Or, if you want to keep it around because it can be a nice convention for all pages to have a title, you can make the field hidden for these templates, and generate pages’ titles on saving the page. The hook might look like this: $this->addHookBefore("Pages::save(template=renovation|delivery|recycling)", function(HookEvent $event) { $page = $event->arguments(0); $page->of(false); $page->set('title', $page->template->label . ', ' . date('Y-m-d', $p->date)); }); If these pages are for internal use and don’t need a name (the bit that identifies the page in the url), you will spare users the need to make something up on the Page Add screen. Unfortunately I believe this is only possible if the parent page accepts only a single template for children. In that case you could go to Family tab of the parent page’s template settings and enter a “Name format for children”, pretty much like the page list fields above. The Page Add screen is then bypassed entirely, because ProcessWire knows everything it needs to know (parent, template, name). I’m always in favour of skipping the Page Add business if possible, but in your case you need to choose a template anyway. To get rid of the name input, you might hook ProcessPageAdd::buildForm: $this->addHookAfter("ProcessPageAdd::buildForm", function(HookEvent $event) { //maybe check the parent page if you don’t want this to happen indiscriminately. //also, since you have multi-language inputs, you may have to adjust for that. //feels hackish, there may be a cleaner way to achieve this. $form = $event->return; $nameField = $form->getChildByName('_pw_page_name'); $nameField->wrapClass = 'InputfieldHidden'; //ProcessWire won’t let you proceed without a name, so generate something here, or //just set a static value. PW will automatically make it unique by adding a number. //Be aware that it will increment any number at the end of the name if it’s not unique, //so if you add two pages with the name “2020-12-31”, the second one will end up as //“2021-12-32”. Also, you’ll get a warning, so it’s probably best to generate a unique //name yourself. At this point you can’t use the ID because it doesn’t exist yet, though. $nameField->value = 'schnitzelmedpommes'; }); The ability to have default page names with multiple possible templates may actully be a worthwhile feature to add to the ProcessWire core. I’m not sure why it wouldn’t work, and philosophically it would fit PW’s ideal to be a “Content Management Framework”. Not every page needs a deliberate name if it just stores data.
  22. That should be happening if you put it next to ProcessWire’s index.php unless the server refuses access or something. Look at the browser console. It probably shows an error trying to load https://www.example.com/favicon.ico. But you can also put it anywhere and add a link tag in your head, such as: <link rel="icon" type="image/x-icon" href="<?php echo $config->urls->templates?>style/favicon.ico"/>
  23. Looks like you uncommented all RewriteBase lines. AFAIK you can only have one. Probably only the last one will have any effect, but you need the one in the middle. Try putting the #s back in the first and third RewriteBase. If it still doesn’t work, maybe paste your entire .htaccess here?
  24. Sorry to unearth this thread again, but I must apologise. It was indeed a collation thing. I had only checked the relevant field tables, but after switching everything except field_password to mb4, the problem disappeared. The issue must have started when my hoster migrated from MySQL to MariaDB months ago, because I’m sure I originally installed PW with mb4, but apparently I didn’t notice until after switching to PHP 8 recently. Probably because earlier I didn’t run Tracy constantly. Not sure how exactly it was implicated, but it was entirely my fault anyway ? Just wish I had had some hints in the logs. Eventually I got an SQL collation exception when purposely searching for an emoji in the Admin, but never with the random logouts. Anyway, glad to have this thread!
×
×
  • Create New...