Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 04/17/2019 in all areas

  1. Here's a way to find all self-referencing page fields. Open your MySQL interface (MySQL Workbench, phpMyAdmin, adminer, whatever...) and execute the following query: SET @oldgcmaxlen = @@group_concat_max_len; SET SESSION group_concat_max_len = 32768; SELECT GROUP_CONCAT(querystring SEPARATOR 'UNION\n') as sqlstring FROM ( SELECT 1 as something, CONCAT( 'SELECT x.pages_id as id, y.name, z.data as title, \'', a.name, '\' as fieldname\n', 'FROM field_', a.name, ' x\n', 'JOIN pages y ON y.id = x.pages_id JOIN field_title z ON z.pages_id = x.pages_id WHERE x.pages_id = x.data\n' ) as querystring FROM fields a WHERE a.type = 'FieldtypePage' ) as inmemtbl GROUP BY something ; SET SESSION group_concat_max_len = @oldgcmaxlen; The result will be a UNION query that checks all your page fields for direct recursions. Here's an example: SELECT x.pages_id as id, y.name, z.data as title, 'permissions' as fieldname FROM field_permissions x JOIN pages y ON y.id = x.pages_id JOIN field_title z ON z.pages_id = x.pages_id WHERE x.pages_id = x.data UNION SELECT x.pages_id as id, y.name, z.data as title, 'roles' as fieldname FROM field_roles x JOIN pages y ON y.id = x.pages_id JOIN field_title z ON z.pages_id = x.pages_id WHERE x.pages_id = x.data UNION SELECT x.pages_id as id, y.name, z.data as title, 'language' as fieldname FROM field_language x JOIN pages y ON y.id = x.pages_id JOIN field_title z ON z.pages_id = x.pages_id WHERE x.pages_id = x.data UNION SELECT x.pages_id as id, y.name, z.data as title, 'pagesel' as fieldname FROM field_pagesel x JOIN pages y ON y.id = x.pages_id JOIN field_title z ON z.pages_id = x.pages_id WHERE x.pages_id = x.data Copy that query into the SQL editor and execute it. If there are any recursions, you will see them listed with the page id, page name, page title and field name.
    6 points
  2. Mystique Module for ProcessWire CMS/CMF Github repo : https://github.com/trk/Mystique Mystique module allow you to create dynamic fields and store dynamic fields data on database by using a config file. Requirements ProcessWire 3.0 or newer PHP 7.0 or newer FieldtypeMystique InputfieldMystique Installation Install the module from the modules directory: Via Composer: composer require trk/mystique Via git clone: cd your-processwire-project-folder/ cd site/modules/ git clone https://github.com/trk/Mystique.git Module in live reaction with your Mystique config file This mean if you remove a field from your config file, field will be removed from edit screen. As you see on youtube video. Using Mystique with your module or use different configs path, autoload need to be true for modules Default configs path is site/templates/configs/, and your config file name need to start with Mystique. and need to end with .php extension. Adding custom path not supporting anymore ! // Add your custom path inside your module class`init` function, didn't tested outside public function init() { $path = __DIR__ . DIRECTORY_SEPARATOR . 'configs' . DIRECTORY_SEPARATOR; Mystique::add($path); } Mystique module will search site/modules/**/configs/Mystique.*.php and site/templates/Mystique.*.php paths for Mystique config files. All config files need to return a PHP ARRAY like examples. Usage almost same with ProcessWire Inputfield Api, only difference is set and showIf usage like on example. <?php namespace ProcessWire; /** * Resource : testing-mystique */ return [ 'title' => __('Testing Mystique'), 'fields' => [ 'text_field' => [ 'label' => __('You can use short named types'), 'description' => __('In file showIf working like example'), 'notes' => __('Also you can use $input->set() method'), 'type' => 'text', 'showIf' => [ 'another_text' => "=''" ], 'set' => [ 'showCount' => InputfieldText::showCountChars, 'maxlength' => 255 ], 'attr' => [ 'attr-foo' => 'bar', 'attr-bar' => 'foo' ] ], 'another_text' => [ 'label' => __('Another text field (default type is text)') ] ] ]; Example: site/templates/configs/Mystique.seo-fields.php <?php namespace ProcessWire; /** * Resource : seo-fields */ return [ 'title' => __('Seo fields'), 'fields' => [ 'window_title' => [ 'label' => __('Window title'), 'type' => Mystique::TEXT, // or InputfieldText 'useLanguages' => true, 'attr' => [ 'placeholder' => __('Enter a window title') ] ], 'navigation_title' => [ 'label' => __('Navigation title'), 'type' => Mystique::TEXT, // or InputfieldText 'useLanguages' => true, 'showIf' => [ 'window_title' => "!=''" ], 'attr' => [ 'placeholder' => __('Enter a navigation title') ] ], 'description' => [ 'label' => __('Description for search engines'), 'type' => Mystique::TEXTAREA, 'useLanguages' => true ], 'page_tpye' => [ 'label' => __('Type'), 'type' => Mystique::SELECT, 'options' => [ 'basic' => __('Basic page'), 'gallery' => __('Gallery'), 'blog' => __('Blog') ] ], 'show_on_nav' => [ 'label' => __('Display this page on navigation'), 'type' => Mystique::CHECKBOX ] ] ]; Searching data on Mystique field is limited. Because, Mystique saving data to database in json format. When you make search for Mystique field, operator not important. Operator will be changed with %= operator. Search example $navigationPages = pages()->find('my_mystique_field.show_on_nav=1'); $navigationPages = pages()->find('my_mystique_field.page_tpye=gallery');
    2 points
  3. Good Morning ProcessWIre Community, PW Review is a website that has a lofty goal of covering ProcessWire on a regular basis. That may seem like an impossible task, however I believe I'm up to the challenge. First, this is a strictly non-commercial endeavor and a project I believe in. This is not Wired Magazine or anything like that. I'm not a serious programmer or pretending to be one. My goal is to cover the modules (commercial and non-commercial) that may not get that much press or attention. I will also be covering modules that maybe you haven't heard about in awhile. There will also be screenshots, information and videos regarding the Commercial modules. I've been with this community since 2012 and have benefitted tremendously from ProcessWire. So this is my way of giving back, which is important to me. It's my hope that over time that what I'm doing myself will get some community participation. One person that I've had nothing but positive support from is Ryan Cramer. That's enough to keep me going at this for some time. That's it. Have a nice day and I hope you find something to like with PW Review. If not, please send me an email. I'm a great listener. Best Regards, Charles
    2 points
  4. Thx to @Robin S I realized that GitHub now also offers unlimited private Repos for free. In some discussion about it I found another interesting alternative (if you don't want to host private code on external servers): https://gitea.io/en-us/
    2 points
  5. You are saying "parent" here, but according to your explanation you are not looking for the "parent" (in the PW meaning), but for the page containing the reference to istanbul, correct? Such things depend a lot on your setup of the page tree. This might be a good read: If you have a setup like this (I guess that's your setup?) /countries (tpl=countries) /countries/austria (tpl=country, referenced cities: vienna,salzburg) /countries/turkey (tpl=country, cities: istanbul, ankara) /cities (tpl=cities) /cities/vienna (tpl=city) /cities/salzburg /cities/istanbul /cities/ankara And you visit page "vienna" the selectors could be: $page; // vienna $country = $pages->findOne([ 'template' => 'country', 'cities' => $page, ]); $siblings = $country->cities("id!=$page"); But it might make more sense (or might not) to sturcture your pages like this: /countries (tpl=countries) /countries/austria (tpl=country) /countries/austria/vienna (tpl=city) /countries/austria/salzburg /countries/turkey /countries/turkey/ankara /countries/turkey/istanbul Then it would be: $page; // austria $country = $page->parent; $siblings = $page->siblings("id!=$page"); This setup would have the benefit, that you can never assign one city to two countries. Well - if that is what you need, the other approach could make more sense (https://en.wikipedia.org/wiki/List_of_divided_cities) @elabx s is also correct, but $page->id is actually not necessary, because when you put your $page variable in the selector string, it will automatically return the page id ? Other than that it's a matter of preferance if you use array syntax or not or if you use "id!=$page" or ->remove($page) ?
    2 points
  6. Thanks for bringing this to my attention @szabesz! My favourite: Best wishes to him, best wishes for ProcessWire and of course best wishes to you @cstevensjr and your project! ? PS: @cstevensjr is there a way how we can subscribe to new topics on your site?
    2 points
  7. Manuel, I'd love it if you could add your experience to that issue: https://github.com/processwire/processwire-issues/issues/572 These problems have been going on for so long and really need to be fixed - I think Ryan needs a nudge to move this to the top of his TODO list. Thanks!
    2 points
  8. But they do. Not as directly as I first suggested, but there is a kind of circularity within the pages you are loading... As soon as your loaded pages form a circularity the out of memory occurs. This kind of problem seems to happen particularly when a "single page" value type is defined in the field settings. I expect that if you change the field setting to "multiple pages" then the error won't occur. To be clear, I think that it ought to be possible to load pages like this using a single page field without any error occurring. I encourage you to make a report in the PW issues repo: https://github.com/processwire/processwire-issues/issues add a comment to the existing issue: https://github.com/processwire/processwire-issues/issues/572
    2 points
  9. Gitea is great. I had gogs (which gitea forked) running on a server of mine for a while, but gitea is more active and open. But I must also say I only use it locally to move repos from my laptop to the desktop for all the WIP stuff, which doesn't need to be in some cloud already.
    1 point
  10. @Manuel, could you try commenting out the setTrackChanges method in core/Wire.php and replacing it with the following code? protected static $resetTrackChangesItems = array(); public function resetTrackChanges($trackChanges = true) { $isRoot = count(self::$resetTrackChangesItems) == 0; self::$resetTrackChangesItems[$this->id] = true; parent::resetTrackChanges($trackChanges); foreach($this->data as $key => $value) { if(is_object($value) && $value instanceof Wire && $value !== $this) { if($value instanceof Page && isset(self::$resetTrackChangesItems[$value->id])) continue; $value->resetTrackChanges($trackChanges); } } if($isRoot) self::$resetTrackChangesItems = array(); return $this; }
    1 point
  11. Wouldn't that be fixed too with the correction in the linked issue? The cited error (Wire.php line 1069) points to setTrackChanges.
    1 point
  12. And page 1017 references page 1018, right? It's a circular reference issue that seems to happen when two pages that reference each other are both loaded into memory. Probably connected to this issue: https://github.com/processwire/processwire-issues/issues/572
    1 point
  13. This statement seems like you didn't get what I tried to say. Means that you have maybe selected page 1018 in the page-reference-field "planet_reference" of page 1018. That means the planet_reference of 1018 points to page 1018 (itself) and could maybe end in an endless loop? No idea if that is possible and it would throw such an error. I think PW should be clever enough to prevent such errors. If not, that would be worth an issue report!
    1 point
  14. Great. Give me a few days please to update the dev branch to include a few changes first, including the recent suggestions by @adrian. This way, we can work on one clean (dev) base. I'll also namespace it. Moving forward, we only support PW 3. I missed the memo it seems. Which ones are these?
    1 point
  15. I have not installed this module and I have the same problem. On my current installation I have only installed a few modules. So I guess it has nothing to do with other modules.
    1 point
  16. Looks like that code needs a change to account for "single" Page Reference fields: // Get all pages where page_field_a is not empty $pgs = $pages->find("page_field_a.count>0"); // Get derefAsPage property of page_field_b to distinguish multiple/single page fields $deref = $fields->get('page_field_b')->derefAsPage; foreach($pgs as $p) { // For this page, get the pages selected in page_field_a $selected_pages = $p->page_field_a; // Standardise $selected_pages to PageArray in case of "single" field if($selected_pages instanceof Page) $selected_pages = $selected_pages->and(); foreach($selected_pages as $selected_page) { // Add this page to page_field_b on the selected page $selected_page->of(false); if($deref) { $selected_page->page_field_b = $p; } else { $selected_page->page_field_b->add($p); } $selected_page->save(); } } I don't fully understand what you're asking here, but in general you can switch "page_field_a" and "page_field_b" and run the code again if you need to. Of course make a DB backup before running any bulk API action in case something unexpected happens.
    1 point
  17. No particular reason as far as I remember - probably I was just trying different things and stopped as soon as I found a way to get the job done. Usually in PW there are several different way to achieve any goal.
    1 point
  18. I think is an issue when the module Helper Field Links is installed with SeoMaestro Note on the left screen, each field has display issues with the field name. I could probably hide it with some CSS but wondered if you'd consider making it work out of the box.
    1 point
  19. Hey Charles, I've just read The Inerview: https://pwreview.com/series/interviews/featured-professionals/ryan-cramer/ big thanks for that, too! My favorite messages in it: "...just go with the flow..." "...working through the issues... ...it's about solving mysteries..."
    1 point
  20. I am using this module for SEO, LANGUAGE and ELEMENTS (uikit components) USAGE EXAMPLE : LANGUAGE On my private module, i added my custom configs path to Mystique module by using : Mystique::add('my-module-configs-path'); - Create config file <?php namespace ProcessWire; // Filename: MyModule/configs/Mystique.language.php // This options normally coming from a file array, i added 2 options for example $options = [ 'tr' => 'Türkçe', 'en' => 'English' ]; $defaultValue = 'en'; /** * Resource : MyModule => Language */ return [ 'title' => __('MyModule: Language'), 'fields' => [ 'title' => [ 'label' => __('Language title'), 'description' => __('Title of language'), 'type' => Mystique::TEXT, 'columnWidth' => 50 ], 'code' => [ 'label' => __('Code'), 'description' => __('Language short code'), 'type' => Mystique::SELECT, 'options' => $options, 'defaultValue' => $defaultValue, 'required' => true, 'columnWidth' => 50 ], 'flag' => [ 'label' => __('Flag'), 'description' => __('Language flag code'), 'type' => Mystique::TEXT, 'columnWidth' => 50 ], 'direction' => [ 'label' => __('Direction'), 'checkboxLabel' => __('Right to left'), 'description' => __('Direction of language'), 'type' => Mystique::TOGGLE_CHECKBOX, 'type_fallback' => Mystique::CHECKBOX, 'columnWidth' => 50 ], 'currency' => [ 'label' => __('Currency'), 'description' => __('Code of currency'), 'type' => Mystique::TEXT, 'columnWidth' => 50 ], 'symbol' => [ 'label' => __('Symbol'), 'description' => __('Symbol of currency'), 'type' => Mystique::TEXT, 'columnWidth' => 50 ], 'grouping_separator' => [ 'label' => __('Grouping separator'), 'description' => __('Thousand separator for amount'), 'type' => Mystique::TEXT, 'columnWidth' => 50 ], 'decimal_separator' => [ 'label' => __('Decimal separator'), 'description' => __('Decimal separator for amount'), 'type' => Mystique::TEXT, 'columnWidth' => 50 ], 'separator' => [ 'label' => __('Use separator'), 'checkboxLabel' => __('YES'), 'description' => __('Apply space between amount and currency symbol ?'), 'type' => Mystique::TOGGLE_CHECKBOX, 'type_fallback' => Mystique::CHECKBOX, 'columnWidth' => 33 ], 'show_decimal' => [ 'label' => __('Decimal'), 'checkboxLabel' => __('YES'), 'description' => __('Show amount decimals ?'), 'type' => Mystique::TOGGLE_CHECKBOX, 'type_fallback' => Mystique::CHECKBOX, 'columnWidth' => 33 ], 'symbol_after' => [ 'label' => __('Symbol after'), 'checkboxLabel' => __('YES'), 'description' => __('Display symbol after amount ?'), 'type' => Mystique::TOGGLE_CHECKBOX, 'type_fallback' => Mystique::CHECKBOX, 'columnWidth' => 33 ], ] ]; - Select config file from Mystique field settings - Add Mystique field to language template Access data via api (in this example mystique field name is : lang) <?php $language = $user->language; // lang is Mystique field echo 'Title : ' . $language->lang->title . '<br>'; echo 'Code : ' . $language->lang->code . '<br>'; echo 'Flag : ' . $language->lang->flag . '<br>'; echo 'Direction : ' . $language->lang->direction . '<br>'; echo 'Currency : ' . $language->lang->currency . '<br>'; echo 'Symbol : ' . $language->lang->symbol . '<br>'; echo 'Grouping separator : ' . $language->lang->grouping_separator . '<br>'; echo 'Decimal separator : ' . $language->lang->decimal_separator . '<br>'; echo 'Separator between amount and symbol : ' . $language->lang->separator . '<br>'; echo 'Show decimal : ' . $language->lang->show_decimal . '<br>'; echo 'Show symbol after amount : ' . $language->lang->symbol_after . '<br>'; Output: Title : English Code : en Flag : gb Direction : 0 Currency : GBP Symbol : £ Grouping separator : , Decimal separator : . Separator between amount and symbol : 1 Show decimal : 1 Show symbol after amount : 0
    1 point
  21. Keep the field name same, do what you want. Because all data on database in string format (i am not checking user posted data), you can set field settings by using processwire fields api and you can limit user by settings. Hook methods could be used for custom usages.
    1 point
  22. Well... me neither. I'd also prefer to have one common and stable solution, so if you are now willing to accept those changes (I also read the thread again and was confused by my own explanations sometimes. One point was misleading (that I was requesting to place the files in the module's folder which would break on every update, of course) and it's always a little hard to have such conversations via internen + non-native language ? ) I'll try to send a PR for your module as soon as I start working on the related modules!
    1 point
  23. PageHitCounter Version 1.2.4 Thanks to @wbmnfktr for reporting the issues. And thanks to @Sergio for the corrections. Both issues have been fixed in version 1.2.4 and the corrections have been applied. Changelog as always updated in the first post. Explanations of the bugs below. The functionality has always been and is correct. The module sends the data to a fictitious endpoint of the current page. Then the module hooked in before a 404 is triggered and writes the data. The problem here was that the module "Jumplinks" had a lower priority than PageHitCounter. Therefore the request was logged as 404, because jumplinks were executed earlier. Now fixed, PageHits are not logged as 404, regular 404s will be. Here was the problem that system templates or pages are excluded in the normal search, without the selector "include=all". This is now included by default. Oh, my gosh, there were a lot of typos in there. So if you have a lot on your mind what you're going to code next, you don't look at the comments. Anyway, many thanks for the corrections! And by the way, I'd love to. Take the code and build something new out of it! ?
    1 point
  24. Maybe you could get some inspiration there from (or even improve on) my JsonNativeField module since MySQL supports searching inside JSON data.
    1 point
  25. No problem! Resolution is not the problem per se, but next time, for the sake of old fellas like myself, bump the font-size on your editor. ?
    1 point
  26. Looks very cool, @ukyo! Thanks for that, but the font-size on the video was hard on my eyes. ?
    1 point
  27. Hey Mike, is there anything the community could do to support you with v2? The new version is highly anticipated ?
    1 point
  28. There's a bit more more work needed before my module could be released publicly but I'll put it on my "to do" list. Yes, but in my use cases that's a good thing. This approach only suits certain types of search needs, where you want to implement a broad text search across most/all content. In my cases I want the search to match as many pages as possible, so I do things like explode the search phrase on space characters and then match each term with the %= LIKE operator so I'm catching part words too and without regard to the order of terms: $search_terms = $sanitizer->selectorValue($input->get->search); $search_terms = preg_replace("/\s+/", " ", $search_terms); // replace multiple spaces with single space $terms = explode(' ', $search_terms); foreach($terms as $term) { $selector .= "index%=$term, "; } //... And I want the excerpt to be Google-like in that it deals with the page's text content as a whole rather than caring about what fields were used behind the scenes.
    1 point
  29. Looks fine, if you inspect the source code you will see the XML markup. This is not a sitemap for users, but one you can submit to search engines, see here: https://support.google.com/webmasters/answer/183668?hl=en Here is a quick how-to, i did not find this feature in the docs: Create a new field of type "FieldsetTab", e.g. "Seo Settings" Use this field to group other fields that should be displayed in the new tab A screenshot is probably easier ?
    1 point
  30. I don't think there's an inbuilt method for that, but you can quickly built your own! For the excerpt, you just need to find the first occurance of the search term inside the field you're searching, then display the text around that. A quick example: // get the search term from the GET-parameter and sanitize it $term = $sanitizer->text($input->get->q); // how many characters to include before and after the search term $include_around = 50; foreach ($pages->find('body~={$term}') as $result) { echo '<h2>' . $result->title . '</h2>'; // start and end positions of the search result in the body field $term_start = mb_strpos($result->body, $term); $term_end = $term_start + mb_strlen($term); // where to start and end the output, and additional // checks to make sure it's not out of bounds $offset_start = $term_start - $include_around; if ($offset_start < 0) $offset_start = 0; $offset_end = $term_end + $include_around; if ($offset_end > mb_strlen($result->body)) $offset_end = mb_strlen($result->body); $output = mb_substr($result->body, $offset_start, $term_start); $output .= '<mark>' . $result . '</mark>'; $output .= mb_substr($result->body, $term_end, $offset_end); echo '<p>&hellip; ' . $output . ' &hellip;</p>'; } I don't have a ProcessWire installation to test this right now, so might be some errors in there, but you get the idea ^^ Basically, find the term inside the field you're searching, then include some characters before and after it for context, and wrap the search term in <mark> tags for highlighting (you can also add a CSS class to target the search result for styling). You can of course refine this as much as you want, for example you can check for full stops to include complete sentences; you'll also want to make sure to find matches in the title as well, and in this case maybe only display the first X characters of the body ...
    1 point
  31. I have puzzled over this too, but I think the confusion comes from a non-standard use of the word "absolute" in relation to the URL. So ProcessPageEditLink never inserts an absolute URL in that it never includes the protocol or domain. But I think the absolute option means absolute relative to the site root. So the link URL starts with '/' as opposed to the two relative options which can give a link URL like '../some-page/'. The current behaviour is a good thing, because otherwise all links would break when the root domain changes (e.g. going from dev to live environment). But it would help if the meaning of the absolute option was clarified.
    1 point
  32. Ok, the simplest thing is the worst thing somethimes... uninstalled the SessionHandlerDB Module and all worked like a charm...so PW showed how secure it is - even a complete systemchange under the radar is detected and you are locked out Best regards mr-fan
    1 point
  33. Put this in your site/ready.php file: $this->addHookAfter('Session::loginSuccess', null, function($event) { if($this->wire('user')->hasRole("target-role")) $this->wire('session')->redirect("other-url"); });
    1 point
  34. Hello Jozsef, for the generation of many large image variations, ImageMagick comes in handy. Of course you have to enable it first on your webspace, but most hosters have an manual for the activation, if they support it. Usually I visit the page I added images in to generate the variations. You could probably achieve this also by an hook. But for me it seems more natural to check the changes I made after saving a page. For the lazy loading of images in the front end, I can highly recommend using the plugin lazysizes. It is easy to setup, supports responsive images, background images and so on. There is also the module Markup SrcSet, which uses lazysizes. Regards, Andreas
    1 point
  35. Something like this will work: <?php /** * On a page that loads the widgets * */ $widgets = $pages->find("parent=/widgets/"); foreach($widgets as $widget) { $widget->set('motherPage', $page); echo "<div class='widget {$widget->template->name}'>"; echo $widget->render(); echo "</div>"; } <?php /** * logic on a widget page * */ // The $page variable of the mother Page bound to $motherPage. $motherPage = $page->motherPage; // Throw 404 if a guest access the widget directly if(!$motherPage && !$user->isLoggedin()) throw new Wire404Exception(); echo $page->body;
    1 point
×
×
  • Create New...