Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by kixe

  1. I don't know how well you know the PW API but it's easy to hook in Pages::delete() and Pages::save() In your sattelite instances you just need a name for each user, nothing else. Manage the users in your main instance only and update users via PW API in the others. What is your special usecase? Why do you have multiple PW Installs for the same users?
  2. If a user is succesfully loggedin in another instance you can force login in the current (only if the user name matches) – no password required. Checkout the code I posted: and add this: $xy->users->setCurrentUser($_user); // search for this wire('session')->forceLogin($_user->name); // add this I would assign profile-edit permission only in the main instance. All this needs a bit coding experience. Be careful and don't create security holes!
  3. I can provide a module for this usecase: https://github.com/kixe/AdminHidePageTreeByRole ... or try one of them: https://processwire.com/modules/admin-restrict-page-tree/ https://processwire.com/modules/admin-restrict-branch/
  4. You can use multiple instances of processwire and include one in another. $pwComments = new ProcessWire($config->paths->root . 'site-comments'); $home = $pages->get(1); $homeOfComments = $pwComments->pages->get(1); https://processwire.com/docs/more/multi-site-support/ use Option #1 https://processwire.com/blog/posts/multi-instance-pw3/#using-multi-instance-in-pw3 This is also possible under a single domain if you do not need a frontend at one of the two installations and use different names for your /admin/ pages and session cookies. Under special circumstances you can also access the current user of one instance within the other. Look here: https://github.com/processwire/processwire-issues/issues/1294#issuecomment-759351593
  5. It's not exactly what you're asking for, but it could be helpful or a first approach to solve your problem: In a ProcessWire multi-instance environment, I needed to get the logged-in user of the central PW instance in all the others and found the following solution. Requires to use different session cookie names in each installation and SessionHandlerDB installed. $config->sessionName = wire0; $config->sessionName = wire1; https://github.com/processwire/processwire-issues/issues/1294#issuecomment-759351593
  6. /** * allowed flag constants (bitmask) for context * @see core/field.php * */ Field::flagAccess // 32 Field::flagAccessAPI // 64 Field::flagAccessEditor // 128 /** * set context via fieldgroup * @see core/fieldgroup.php * */ $fieldGroup->setFieldContextArray($field_title->id, ['flagsAdd' => 192, 'flagsDel' => 32]); $fieldGroup->saveContext(); /** * set context via fields * @see core/fields.php * */ $field_title = wire('fields')->get('title'); $field_title->addFlag(128); // runtime wire('fields')->saveFieldgroupContext($field_title, $fieldGroup); not tested, but should work
  7. Possible solution to set $user using a setup with multiple sites (multiple databases Option #1), module SessionHandlerDB and different session names for each instance. Put this code in your ready.php $xy = new ProcessWire($config->paths->root . 'site-xy/'); /** * if a session AND a challenge cookie is present we check if the user is still loggedin in xy * if yes we set the @var wire('user') to the xy instance * */ if ($xy->session->hasCookie() && $xy->session->hasCookie(true)) { // get xy session ID if ($xy>config->https && $xy->config->sessionCookieSecure) { $cn = $xy->config->sessionNameSecure; if (!$cn) $cn = $xy->config->sessionName . 's'; } else { $cn = $xy->config->sessionName; } $SID = $input->cookie->$cn; // set the wire('user') if loggedin if ($SID) { $SHDB = $xy->modules->getModule('SessionHandlerDB', array('noPermissionCheck' => true))->getSessionData($SID); if ($SHDB['user_id'] != 40) { // get fingerprint and session timestamp $fp = isset($SHDB['data']['Session']['_user']['fingerprint'])? $SHDB['data']['Session']['_user']['fingerprint'] : false; $ts = isset($SHDB['data']['Session']['_user']['ts'])? (int) $SHDB['data']['Session']['_user']['ts'] : 0; // validate fingerprint if ($xy->session->getFingerprint() !== $fp) { $this->session->error(__('Unable to assign XY user. XY-Session fingerprint does not match.'), Notice::debug | Notice::log); } // check if session timed out else if ($xy->config->sessionExpireSeconds && $ts < (time() - $xy->config->sessionExpireSeconds)) { $this->session->error(__('Unable to assign XY user. XY-Session timed out.'), Notice::debug | Notice::log); } else { $_user = $xy->users->get($SHDB['user_id']); if ($_user->id) { // session valid, assign user & user_id will be set correctly in DB via SessionHandlerDB::write() $xy->users->setCurrentUser($_user); } } } } }
  8. or simply ... $s = $modules->get('SessionHandlerDB')->getSessions(); // seconds = 300, limit = 100 $online_user_ids = array_filter(array_column($s,'user_id'), function($id) {return $id != 40;}); // with all arguments $seconds = 86400; // one day $limit = 200; $s = $modules->get('SessionHandlerDB')->getSessions($seconds, $limit); $online_user_ids = array_filter(array_column($s,'user_id'), function($id) {return $id != 40;}); Unfortunately this doesn't work if ProcessWire is bootstrapped https://github.com/processwire/processwire-issues/issues/1294#issuecomment-748057420 I have to correct myself. It works also if ProcessWire instance is bootstrapped $otherPwInstance = new ProcessWire($config->paths->root . 'site/'); $s = $otherPwInstance->modules->getModule('SessionHandlerDB', array('noPermissionCheck' => true))->getSessions(); $online_user_ids = array_filter(array_column($s,'user_id'), function($id) {return $id != 40;});
  9. // 'include=all' includes access restricted pages, check access via function viewable() before using render() foreach ($page->children('include=all') as $p) { if ($p->viewable()) $p->render(); } // without argument (selector) access restricted pages are excluded by default foreach ($page->children() as $p) { $p->render(); } Why do you want to render multiple pages?
  10. I have 2 ProcessWire instances running under the same domain, each with own session name and cookie. $config->sessionName = 'wire0'; $config->sessionName = 'wire1'; The assignment of the correct instance via url is done in index.config.php. One of the 2 instances is without frontend and accessible only under the related admin url. In this instance (wire0) the user with ID=14179 is logged in. If I check if the session of the related user in this instance is valid I get false. The user var returns unexpected results as well. $xy = new ProcessWire($config->paths->root . 'site-xy/'); var_dump($xy->session->isValidSession(14179)); // false, should be true var_dump($xy->user->isLoggedin()); // false, should be true If I use the $pages, the $users, $config or any other API of the $xy instance I get what I expect. $userIDs = $xy->users->findIDs('check_access=0'); var_dump(count($userIDs)); // correct number of users in related instance var_dump($xy->config->sessionName); // wire0 var_dump($config->sessionName); // wire1 How can I get the $user or $session vars of another PW instance?
  11. I think you don't need a workaround with a hidden field if you do the hook after and change the PageArray instead of the selector. $wire->addHookAfter('ProcessPageList::find', function($e) { $pages = $e->return; if ($pages->first()->parent->id != 111111) return; // quick exit if parent doesn't match $zeroDatePages = $pages->find("date=''"); // empty date pages $result = $pages->filter('date>0,sort=-date'); // pages with date, sort descending $result->prepend($zeroDatePages); // prepend empty date pages $e->return = $result; });
  12. try // ... $results->setStart(6); // index = 7 - 1 $pagination = $pager->render($results);
  13. I use a hook for something similar /** CUSTOM PAGE SORT * related for InputfieldPageListSelect, ProcessPageList (Page tree) * */ $wire->addHookBefore('ProcessPageList::find', function($e) { $parent = $e->arguments(1); $selectorString = $e->arguments(0); // modify $selectorString, remove, modify, add ',sort= ...' $e->arguments(0, $selectorString); });
  14. Do not overwrite the field object (loop item) with the field value. Try: foreach ($page->fields as $field) { $fieldValue = ''; foreach($languageFallback as $languageID) { $fieldValue = $page->getLanguageValue($languageID, $field); if ($fieldValue) break; } $page->$field = $fieldValue; }
  15. Example with 'body' field. Define a language fallback order in ready.php and render first match in template. (not tested ... ) // in ready.php $languageFallback = [1046,1042,1033]; // array of Language-IDs in fallback order $body = ''; $pageActiveLanguageIds = $page->getLanguages()->each('id'); $languageFallback = array_intersect($languageFallback, $pageActiveLanguageIds); foreach($languageFallback as $languageID) { $body = $page->getLanguageValue($languageID, 'body'); if ($body) break; } $page->body = $body; // in your template file echo $page->body; // render field body
  16. @LostKobrakai If the thread doesn't reveal any ListerPro secrets and provide interesting informations about FieldtypeSelector/ InputfieldSelector, it could be moved and made available to everybody, since FieldtypeSelector is not Pro. 🤔
  17. https://processwire.com/talk/topic/13116-or-selecters-for-different-fields/ Unfortunately the thread is not accessible for everybody. Why? ... which could be found here: https://github.com/processwire/processwire-requests/issues/317 For everyone who is interested in this function. Please vote or add a comment.
  18. Nearly nothing. Displays a warning in the backend and "HTML Markup Quality Assurance" displays a message in debug mode when sleepLinks() detects an absolute URL in a textarea field that does not refer to an allowed host. However, you can add functionality to check the current host. $this->wire('config')->httpHost https://processwire.com/api/ref/config/#pwapi-methods-HTTP-and-input https://processwire.com/docs/start/variables/config/#httphosts
  19. @fruid never touch the core (wire folder). If you need another Uikit version for the frontend. Install in your site/template folder.
  20. If minimum one field is present in the template the other field should be created/ added. No need to go on with the loop.
  21. Small remarks. You should break the loop when work is done: foreach ($page->fields as $field) { if ( $field->type instanceof FieldtypePageTableExtendedGrid ) { // ... break; } } Another approach without loop. Fields is an instance of WireSaveableItems providing a find($selector) function: $selector = implode('|',$fields->find('type=FieldtypePageTableExtendedGrid')->each('name')); if ($page->hasField($selector)) { // ... do something }
  22. The output of the path history on the settings-tab is only visible to superusers. However, you can access the path history of a page through the API. The module has no access restrictions. You may want to output the information somewhere else. $modules->get('PagePathHistory')->getPathHistory($page); Just in case, if you need to access a module with access restriction: $modules->getModule('ModuleWithRequiredPermission', ['noPermissionCheck' => true]);
  23. Maybe useful for you @teppo. In one of my last projects I integrated a lightbox gallery that outputs both videos and pictures. The data source for the videos and images was a PageFile field. Here is an excerpt from the template in which the gallery was integrated via Javascript. Resizing works similarly as suggested by @Robin S // galleries $page->_galleriesJS = ''; $galleriePages = $pages->find('template=gallery'); // 16:9 inline video $markup = '<div class="mfp-video-wrapper"><div class="mfp-video-inner"><video width="854" height="480" controls autoplay preload> <source src="{src}" type="video/mp4"> Leider wird dieses Video von ihrem Browser nicht unterstützt. </video></div></div>'; if ($galleriePages->count) { $galleries = ''; foreach ($galleriePages as $gp) { if ($gp->files->count == 0) continue; $items = []; $filesDirPath = $gp->files->path; foreach ($gp->files as $gi) { if (!fileExists($gi->url)) continue; // inline video if (in_array($gi->ext, array('mp4','m4v','ogg','ogv','mpg'))) { $src = str_replace('{src}', $gi->url, $markup); $items[] = ['type' => 'inline', 'src' => $src]; } // wrong file type else if (!in_array($gi->ext, array('png','jpg','jpeg'))) throw new WireException("Unallowed Fileformat $gi->ext for magnificPopup Gallery"); // any image with youtube video source in description else if (strpos($gi->description, 'youtube')) { $oembed = getVideo($gi->description); if ($oembed) { // nocookie source used $items[] = ['type' => 'iframe', 'src' => $oembed->frameUrl]; } } // image else { $src = $gi->url; $copyFileName = strstr($gi->filename, $gi->ext, true) . '1200x0.' . $gi->ext; list($width, $height) = getimagesize($gi->filename); if ($width > 1200) { if (!file_exists($copyFileName)) { $files->copy($gi->filename, $copyFileName, ['limitPath' => true]); $imageSizer = new ImageSizer($copyFileName); $imageSizer->resize(1200, 0); } $src = str_replace($config->paths->root, '', $copyFileName); } $items[] = ['title' => $gi->description, 'src' => $src]; } } $gallery = [ 'gallery' => ['enabled' => true], 'type' => 'image', 'midClick' => true, 'mainClass' => 'mfp-lightbox-wrapper', 'items' => $items, 'tClose' => 'Schließen (esc)' ]; $gallery = json_encode($gallery); $galleries .= "$('.mfp-open-$gp->id').magnificPopup({$gallery})\n"; } $page->_galleriesJS = "<script> $galleries</script> "; }
  24. Do not use global unless you really know what you are doing. Read this: https://stackoverflow.com/questions/16959576/reference-what-is-variable-scope-which-variables-are-accessible-from-where-and $this->wire() is another option to assign global vars, especially for more complex stuff ... like class instances. /** * Get an API variable, create an API variable, or inject dependencies. * * * @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 object|string|mixed * @throws WireException * * */ public function wire($name = '', $value = null, $lock = false) {}
  • Create New...