• Content count

  • Joined

  • Last visited

  • Days Won


BitPoet last won the day on June 13

BitPoet had the most liked content!

Community Reputation

1,795 Excellent

1 Follower

About BitPoet

  • Rank
    Hero Member

Profile Information

  • Gender
  • Location
    Near Munich / Germany
  • Interests
    programming, writing, scuba diving, long distance hiking

Recent Profile Visitors

4,617 profile views
  1. Actually, you wouldn't even have to pass the filename. If you assemble the image URL like this, you could just as well use a unique parameter that tells your hook to output the image contained in whatever field you want and can stop worrying about exposing the wrong file. Like {$page->url}?showprofileimage=1.
  2. That's likely not going to be trivial. Adding check_access=0 in a selector to display the link is quite another thing as serving the secure file to a guest user. When you have pageFileSecure enabled, the following happens: PW prefixes the file directory site/assets/files/[PAGEID] with $config->pagefileSecurePathPrefix ("-" by default so it will be site/assets/files/-[PAGEID]) When the browsers tries to show the image (i.e. open the URL /path/to/pw/site/assets/files/1258/image.jpg in a separate request), the file isn't found by .htaccess .htaccess hands off the request to index.php index.php calls PageRender::execute with the request URL PageRender::execute checks if the request is to a file, then checks if the page it belongs to is published and viewable by the current user Since $user->hasPermission('page-view', $page) returns false (the guest user doesn't have view permissions) that fails (otherwise, PW would prefix the path now and output the file) PW outputs the 404 page Since the method where the check is are done is not hookable (and some necessary properties and methods are protected, i.e. not reachable from a hook) you'd probably have to hook before ProcessPageView::execute and duplicate a lot of code from ProcessPageView or hook after User::hasPagePermission and at least duplicate ProcessPageView::checkRequestFile in both cases, match the file URL to $page->image to prevent handing out a access to other file/image fields on the page Another approach (if the images aren't too big and the protected pages aren't too many) would be to include the real image data as data URIs: <?php foreach($protected_pages as $protected_page) { echo $protected_page->title . "<br>"; $fn = $protected_page->image->filename; $imgdata = "data:" . mime_content_type($fn) . ";base64," . base64_encode(file_get_contents($fn)); echo "<img src='$imgdata' alt='{$protected_page->image->description}' />"; } If the images are small enough but you have many pages, using PW's pagination might be an option too.
  3. IMHO building your prototype with PW gives you a solid base from which you can go in every direction. You can build just a part in Vue and let the Vue app grow over time. There's a little bit of effort involved to tie PW's pages, fields and templates and Vue templates together smoothly without a lot of overhead, but an experienced Vue dev should be able to wire that up quickly and in a reusable way (Vue would be my choice there as well). Exposing PW pages and limited write actions through ajax isn't hard to do either. It's also a walk in the park to migrate PW content into less normalized "external" tables with a small bootstrap script if performance really requires it, so unlike other CMSes where you have all kinds of different things (posts, pages, parts, whatever) in different structures, you don't really lock yourself in with PW. I agree with @LostKobrakai insofar as that there are in fact a few areas where a custom tool will get you further, like if you need a full-blown discussion forum. The choices there are rather limited if you want a good integration. Invision (the software this forum runs on) seems to be rather straight forward in that regard. I have tried my hand on a phpBB3 integration module and while the basics mostly work, it's really a PITA in some parts (like outdated examples and misleading documentation) and I've run out of time to get it into a really usable shape. There are probably a few Laravel forum components I've never heard of that can get you most of the way as a half way option. I think that will be the hardest part to decide, where will PW (or any other CMS or own development, in fact) ever only be the second best choice compared to a single purpose tool you can integrate.
  4. BitPoet

    Here's a try: <?php echo (selectorsMatch("baths>1, template=listing", "template=listing, baths>1")) ? "Match" : "No match"; function selectorsMatch($sel1, $sel2) { $s1 = new Selectors($sel1); $s1->sort('field'); $s2 = new Selectors($sel2); $s2->sort('field'); return "$s1" == "$s2"; } Not sure how this behaves with OR-groups, but it should be fine for simple AND selectors.
  5. In my personal opinion the definition is rather fluid and depends on too many factors to give a generic rule, but I consider a site highly dynamic when multiple components of often visited templates (especially home and other landing pages) have user or group specific content and that content changes more often than on a daily basis. Whenever I see "social" or "communities" in a site's description, that's likely the case.
  6. Find queries are cached for the lifetime of a request. Caching them more permanently needs additional code. I think there was an example for using MarkupCache to store JSONified query results in the forum a while ago, but I might remember wrongly. With highly dynamic sites, everything you know about caching best practices is at first no longer valid. Until you start factoring out the dynamic parts, that is. Decouple searches from the database by using a dedicated in-memory search engine (Lucene, OpenSearchServer etc.) to avoid high loads and table level locks. Cache IDs and values retrieved from frequent searches in memory (like newest n posts/comments), and when you scale up, delegate the job of updating those to cronjobs to eliminate any delays caused by rebuilding expired memory caches. Retrieve dynamic parts of the page through JS in JSON format and render them with a frontend framework so the static parts and templates can be served from the filesystem (that's where ProCache ties in). Design your pages to use placeholders for dynamic content so your users don't have to wait for client side rendering of dynamic content before they can start using the page.
  7. If you use mod_security with a CMS it isn't specifically aimed at, this is exactly the kind of nonsensical errors you will get since its pattern matches will only make sense in the context of that CMS (mostly WP). Even with a supported CMS you will likely encounter that kind of error if you build a complex, dynamic site or use less popular plugins, and you will have to adapt the rule sets. I'm pretty sure you'll find log entries from mod_security that match your 403s and 404s.
  8. BitPoet

    @Xonox, have you seen Inputfield Page Autocomplete?
  9. BitPoet

    PHP probably runs under the user configured in your anonymous authentication settings. In IIS manager, click on your website, then on "Authentication". Select "Anonymous Authentication" and click "Edit" in actions bar at the right. There you will see the user (default: IUSR). Grant this user modify permissions on the assets folder.
  10. BitPoet

    Contacting them about the problem is never a bad idea. Even if it's something you can change yourself, they'll likely be able to give you pointers where to look.
  11. BitPoet

    This error is caused by PHP being unable to reach a source of randomness to generate random numbers (like, in this case, session IDs). The exact cause can vary, ranging from missing read access to /dev/urandom (check if it is included in php.ini's open_basedir if that restriction is configured) over too old PHP versions to improperly set up chroot jails (e.g. missing to include /dev/urandom) and probably some scenarios I can't think of off the top of my head.
  12. What happens if you extend FieldtypeMulti instead of Fieldtype in FildtypeMapRoom?
  13. Site Profile Exporter doesn't account for function code in config.php, as it has very limited line parsing capabilities. Basically, it concatenates lines until it encounters a ";" at the end of the line. I don't think there's a quick fix to the exporter, but perhaps setting $config->sessionAllow in the init method of an autoload module might work.
  14. BitPoet

    Yes, you can use the code from InputfieldText::getConfigInputfields almost verbatim in a site/ready.php hook, but since that configuration property isn't initialized in InputfieldDatetime and not set in the field's attributes, you have to add that logic too in another hook. A possible place to do that is in Field::getInputfield: <?php namespace ProcessWire; // Add the configuration field: $wire->addHookAfter("InputfieldDatetime::getConfigInputfields", function(HookEvent $event) { $inputfields = $event->return; $required = $inputfields->getChildByName('required'); if($required) { $required->set('columnWidth', 50); /** @var InputfieldCheckbox $field */ $field = wire('modules')->get('InputfieldCheckbox'); $field->attr('name', 'requiredAttr'); $field->label = $event->object->_('Also use HTML5 “required” attribute?'); $field->showIf = "required=1, showIf='', requiredIf=''"; $field->description = $event->object->_('Use only on fields *always* visible to the user.'); $field->icon = 'html5'; $field->columnWidth = 50; if($event->object->requiredAttr) $field->attr('checked', 'checked'); $required->getParent()->insertAfter($field, $required); } }); // This populates the requiredAttr property and sets the HTML attribute // on the InputfieldDatetime instance: $wire->addHookAfter("Field::getInputfield", function(HookEvent $event) { $input = $event->return; if(! $input instanceof InputfieldDatetime) return; $field = $event->object; // Configuration value retrieved from the field's settings in the database: $requiredAttr = $field->requiredAttr; // Probably not necessary but there for consistiency: if($requiredAttr) $input->requiredAttr = $requiredAttr; // This sets the HTML attribute if($input->required && $requiredAttr && !$input->getSetting('showIf') && !$input->getSetting('requiredIf')) { $input->setAttribute('required', 'required'); } });
  15. BitPoet

    Three solutions immediately spring to mind: a) Create different comments fields for each group of pages (downsides: you have to keep other settings in sync and page queries may have to run over both fields) b) If all comments pages are at the same depth (or not too deeply nested) and each has a unique (might also be grand-) parent, you can create a field on those ancestors that holds the admin contact email and use the "field:" syntax in Admin notification email: field:parent.adminemail // or, for grandchildren field:parent.parent.adminemail You could even set multiple sources this way if the adminemail might be either on the parent or the grandparent (just make sure it isn't set on both). The comments field will only use valid emails, so if a parent or grandparent doesn't have the field (or doesn't exist), that entry will be ignored. field:parent.adminemail,field:parent.parent.adminemail c) In some scenarios, you want to send notifications to the user that created the page. In that case, you can use The big downside of that approach is that when the creator of the page is no longer available to approve comments, the createdUser field has to be changed or a different email address assigned in their profile settings (and comment notifications might get lost if nobody thinks of that). It should also be possible to populate $field->notificationEmail through a hook, but from the top of my head, I can't name a convenient method to hook into.