
abdus
Members-
Posts
743 -
Joined
-
Last visited
-
Days Won
42
Everything posted by abdus
-
-
Well, if you're going to get your hands dirty, can I make a request? This has been bothering me for a long time. https://processwire.com/talk/topic/15983-better-mobile-reading-experience-for-code-snippets-in-forum/
-
I dont think it's too bad, I kinda like it.
-
@bernhard, I've found a way. Hooking ProcessPageEdit::buildForm works wire()->addHookAfter('ProcessPageEdit::buildForm', function (HookEvent $e) { /** @var ProcessPageEdit $edit */ $templates = ['post', 'basic']; $edit = $e->object; $page = $edit->getPage(); if (!in_array($page->template->name, $templates)) return; /** @var InputfieldForm $form */ $form = $e->return; /** @var InputfieldImage $imageField */ $imageField = $form->children->findOne('name=images'); if (!$imageField) return; $imageField->maxFiles = 1; }); When I try to add more images, field just replaces the first one, not allowing more than one. If there were multiple images before, they disappear after page save, only the first one remains.
-
You're absolutely right, @bernhard. It's certainly possible. When an exception is thrown, page doesn't save and whatever changes has been made will be reverted back. It was more of a proof of concept. I guess showing a warning instead of throwing exception would be a better, non-destructive way of warning the editors. I'm not sure if I can hook into ProcessPageEdit and change image field settings before it's rendered. I'm going to look into it.
-
passing data between PW installations via scripts
abdus replied to Peter Falkenberg Brown's topic in API & Templates
Oh, try prefixing Page with that namespace: $d1Page = $DOMAIN_1_site->wire(new \ProcessWire\Page()); -
passing data between PW installations via scripts
abdus replied to Peter Falkenberg Brown's topic in API & Templates
Does this help? In many core modules @ryan uses this method to build multi-instance aware modules. Give your object to wire() function, it injects a specific instance to it $d1Page = $DOMAIN_1_site->wire(new Page()); $d2Page = $DOMAIN_2_site->wire(new Page()); /** * Get an API variable, create an API variable, or inject dependencies. * * This method provides the following: * * // ... * * // Inject dependencies during construct * $newPage = $this->wire(new Page()); * ~~~~~ * * @param string|object $name Name of API variable to retrieve, set, or omit to retrieve the master ProcessWire object. * @param null|mixed $value Value to set if using this as a setter, otherwise omit. * @param bool $lock When using as a setter, specify true if you want to lock the value from future changes (default=false). * @return ProcessWire|Wire|Session|Page|Pages|Modules|User|Users|Roles|Permissions|Templates|Fields|Fieldtypes|Sanitizer|Config|Notices|WireDatabasePDO|WireHooks|WireDateTime|WireFileTools|WireMailTools|WireInput|string|mixed * @throws WireException * * */ public function wire($name = '', $value = null, $lock = false) { if(is_null($this->_wire)) { // this object has not yet been wired! use last known current instance as fallback // note this condition is unsafe in multi-instance mode $wire = ProcessWire::getCurrentInstance(); if(!$wire) return null; // For live hunting objects that are using the fallback, uncomment the following: // echo "<hr /><p>Non-wired object: '$name' in " . get_class($this) . ($value ? " (value=$value)" : "") . "</p>"; // echo "<pre>" . print_r(debug_backtrace(), true) . "</pre>"; } else { // this instance is wired $wire = $this->_wire; } if(is_object($name)) { // make an object wired (inject ProcessWire instance to object) if($name instanceof WireFuelable) { if($this->_wire) $name->setWire($wire); // inject fuel, PW 3.0 if(is_string($value) && $value) { // set as new API var if API var name specified in $value $wire->fuel()->set($value, $name, $lock); } $value = $name; // return the provided instance } else { throw new WireException("Wire::wire(\$o) expected WireFuelable for \$o and was given " . get_class($name)); } } // ... } -
While I was reading Smashing Magazine, I discovered this handy tool called XRespond that lets you load webpages in iframes that are designed to simulate different devices, (similar to how browsers' mobile simulators work). I think it's quite useful for local development. In fact it works for any website as long as it doesnt have `X-Frame-Options` headers set to `sameorigin`. I highly recommend using it with browser-sync with live loading as well. I use this settings when using it with PHPStorm to live reload my dev site on pw.dev. // remember set cwd to /site/templates/ or call it from templates directory path/to/browser-sync.cmd start --proxy pw.dev --port 8080 --files "**/*.php" --files "assets/**/*.css" --files "assets/**/*.css" What other tools/utilities do you use for testing your responsive designs?
-
Some points: You can get inputs in an array if you name them as profession[] instead of profession_1, profession_2 ... etc. $input->post->profession will give you an array directly Using this method for the input field outside foreach() block (one with count + 1) will achieve what you want without using indices. Also you can clone that field indefinitely to let user create as many jobs as he/she wants Is there a reason why you're outputting professions on the frontend, only to replace with $page's on form submit? Thrashing and creating a lot of pages at once will probably slow the page down to a crawl. I simplified the code a bit <?php namespace ProcessWire; /** @var $input WireInput */ /** @var $page Page */ if ($input->post->submit) { // check if there are any professions if ($input->post->professions && count($input->post->professions)) { $page->of(false); $newItems = []; foreach ($input->post->professions as $val) { // always sanitize user input /** @var $sanitizer Sanitizer */ $val = $sanitizer->entities1($val); $val = $sanitizer->text($val); if (!$val) continue; $item = $page->professions->getNewItem(); $item->profession = $val; $item->save(); $newItems[] = $item; } if (count($newItems)) { $page->professions->removeAll($newItems); $page->professions->add($newItems); $page->save('professions'); } } } ?> <form method="post"> <?php foreach ($page->professions as $i => $prof): ?> <input type="text" name="professions[]" value="<?= $prof->profession ?>"/> <?php endforeach; ?> <!-- I guess for a new profession? --> <input type="text" name="professions[]" value=""/> <input type="submit" name="submit" value="submit"/> </form> Frankly, I can't say I fully understand what this form really does, so it'd be better if you explain your requirements a bit more
-
When reloading the page, you might be repeating the POST request. Refreshing the form page might create the same items over and over. You should get a popup warning you like this. After dismissing it once, you might not be warned again but still keep sending the request. Also can you share your code, so that we can help you better?
-
Let me introduce you to Field - Template Contexts https://processwire.com/videos/field-template-context/ As for the multiple/single image fields, I usually have a single image field that is set to return an array, and use only what I need by getting the first image or filtering with tags. I rarely, if ever need to create a second images or files field. With template contexts, change the description and notes to guide the editor and use it in the templates however you want. You might add some checks with hooks and throw error if someone added more than one image to a template. wire()->addHookBefore('Pages::saveReady', function (HookEvent $e) { $limitedTemplates = ['post', 'event']; // limit to only one image /** @var Page $page */ $page = $e->arguments('page'); if(!in_array($page->template->name, $limitedTemplates)) return; if ($page->images->count > 1) throw new WireException('Only one image is allowed'); });
-
Try changing <?php to <?php namespace ProcessWire; on the first line of ServicePages.module file
-
Before you buy you can see all options for the module on the skyscrapers demo website. http://demo.processwire.com/admin/
-
All of your requirements can be met with native template caching and maybe some hooks. Have you tried using it? You might not even need to purchase ProCache.
-
Also, while adding fields to the fieldset, unless I am missing something, the field's _END counterpart shouldn't show up: Inside FieldgroupConfig.php, I tried removing closing field, but the solution I found isn't really pretty. $f instanceof FieldtypeFieldsetClose always return false for all FieldsetClose (fieldset, tabs, fieldsetfieldgroups etc) fields public function getConfigInputfields(Field $field, InputfieldWrapper $inputfields) { // ... foreach ($this->wire('fields') as $f) { if ($f->id == $field->id) continue; if ($template && $template->fieldgroup->has($f)) continue; if ($f->name == $field->name) continue; // WORKING skip its own closing field if ($f->name === "{$field->name}_END") continue; // NOT WORKING // $f instanceof FieldtypeFieldsetClose is never true for _END fields if($f instanceof FieldtypeFieldsetClose && strpos($f->name, $field->name) === 0) continue; // ... $select->addOption($f->id, $name, $attrs); } // ... }
-
Displaying the most recent blog posts using different layouts for each
abdus replied to mike62's topic in Getting Started
Optionally, you can create a select field, or better, a page field and select flavors for each post while editing and render items depending on that https://processwire.com/blog/posts/making-efficient-use-of-fields-in-processwire/#use-page-fields-rather-than-individual-checkboxes if($item->flavors->get("name=hoverable")) { // this page has the "hoverable" flavor set } -
Displaying the most recent blog posts using different layouts for each
abdus replied to mike62's topic in Getting Started
Here are two ways: <?php namespace ProcessWire; /** @var $pages Pages */ $posts = $pages->find('template=post, sort=-published'); $latest = $posts->shift(); // removes first item off of $posts ?> <ul class="post-list"> <li class="item--latest item"> <?= $latest->title ?> </li> <?php if ($posts->count): ?> <?php foreach ($posts as $i => $p): ?> <?php $itemClass = ($i % 3 == 0) ? "item--hoverable" : ''; ?> <li class="<?= $itemClass ?> item"><?= $p->title ?></li> <?php endforeach; ?> <?php endif; ?> </ul> <!-- OR --> <?php if ($posts->count): ?> <ul class="post-list"> <?php foreach ($posts as $i => $post): ?> <?php if ($i === 0): // LATEST POST ?> <li class="item--latest item"> Latest: <?= $post->title ?> </li> <?php elseif ($i === 1): // BASIC ?> <li class="item--basic item"> Basic: <?= $post->title ?> </li> <?php elseif ($i % 3 === 0): // HOVERABLE ?> <li class="item--hoverable item"> Hover Me: <?= $post->title ?> </li> <?php endif; ?> <?php endforeach; ?> </ul> <?php else: ?> <p>No posts found</p> <?php endif; ?> -
Hey @ryan, thanks for the update as always. I may have found a bug. Or it might be specific to my system too. I'm not sure. When I create a FieldsetGroup, I can't edit it, and I get this error: (I'm on v3.0.74) Putting a breakpoint inside the method, I see: $this->wire('modules')->get('InputfieldFieldsetOpen') returns null. I've searched the core for that module. It appears inside FieldtypeFieldsetOpen.module like this: class InputfieldFieldsetOpen extends InputfieldWrapper { } // empty definition class FieldtypeFieldsetOpen extends Fieldtype { /* ... */ } When I try to get the module manually using $modules->InputfieldFieldsetOpen, it doesnt work either. I tried refreshing module cache, but it didnt help. Then I refactored InputfieldFieldsetOpen into its own module file under /wire/modules/Inputfields/InputfieldFieldsetOpen.module (without removing it from FieldtypeFieldsetOpen.module), and refreshed module cache (and remove the definition from FieldtypeFieldsetOpen.module), PW recognizes the module and I can edit the field now.
-
Eyvallah, kolay gelsin
-
Ok, in my test setup `country` field may include spaces, so urlSegments is out of question. In these situations you can use query strings and send encoded parameters with urls. If user goes to a nonexistent url, it redirects back to summary list <?php namespace ProcessWire; $detailMode = false; // show people in a country? $grouped = []; if ($input->get->country) { // always sanitize user input $country = $sanitizer->selectorValue($input->get->country); $persons = $pages->find("template=person, country=$country"); $detailMode = true; if (!$persons->count) $session->redirect('./'); } else { // summary mode $persons = $pages->find('template=person'); foreach ($persons as $person) { $country = $person->country; if (isset($grouped[$country])) { $grouped[$country][] = $person; } else { $grouped[$country] = [$person]; } } } ?> <?php if($detailMode): // showing single country ?> <h1><?= $persons->first->country ?></h1> <?php foreach ($persons as $person): ?> <?= $person->title ?><br> <?php endforeach; ?> <?php else: // showing all countries ?> <?php foreach ($grouped as $country => $people): ?> <?php $encoded = "./?" . http_build_query(['country' => $country]) ?> <?= $country ?> <a href="<?= $encoded ?>">[<?= count($people) ?>]</a><br> <?php endforeach; ?> <?php endif; ?> Result looks like this One drawback of using query parameters is that the url looks like mysite.com/url?param=value, instead of mysite.com/url/value.
-
To get an output like you want, you can use: <?php foreach ($grouped as $country => $people): ?> <h2><?= $country ?> [<?= count($people) ?>]</h2> <?php endforeach; ?> Which gives