Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 04/24/2018 in all areas

  1. Hi Guys, Here's is our most recent website built in collaboration with the Design studio DITHO from Cologne, who designed and coordinated all the process. For now the website is only in German, but there will be a English version soon. https://bedrohte-ordnungen.de/ "Bedrohte Ordnungen" (Threatened Orders) is the display of an ongoing research by the University of Tübingen. Best described on their own words. Here on a hopefully accurate translation Here's a nice showcase video made by DITHO: This is a quite complex website. It's also quite heavy on images, videos and CSS animations, so old computers might struggle a bit to process it. All the website is dynamic and inside PW, including those animations. This is probably the most interesting part of how the website was built, since all the animations were created by DITHO themselves in ProcessWire thanks to a system that I created for them using a repeater field. You can have an idea through these screenshots: The content blocks of each case represent a question each and repeat throughout all the presented cases. Each question has a main content and most have also a hidden block that can be opened by clicking a button. They are created in PW using the very recent FieldGroups https://processwire.com/blog/posts/processwire-3.0.73-and-new-fieldset-types/: The only two third party modules used were AdminOnSteroids by @tpr and the very useful ColorPicker by @Soma. There would be more to talk about, but I don't want to extend myself too much. Hope you guys like it! Just a shout out to DITHO to say again how much fun this collaboration has been
    11 points
  2. https://processwire.com/blog/posts/processwire-3.0.62-and-more-on-markup-regions/ try in main <div id="page-content"> <!-- Fill content --> </div> and like the blogpost in overview <div pw-replace="page-content"> <h1><?=$page->title?></h1> Overview page </div> it should work this way...you have a lot of other options like append, prepend and so on... best regards mr-fan
    3 points
  3. Thx @FrancisChung and @kongondo, the quickest possible fix was to just copy laragon's php binary folder, rename it to php...-noXDebug and remove the .dll and comment out the section for xdebug in php.ini You can enable/disable php extensions with a simple rightclick in laragon:
    2 points
  4. I would probably just override the CSS on these fieldsets (by loading a CSS file to the admin).
    2 points
  5. Nothing fancy, just solid basic sites for two different companies. Both happen to work mainly in construction sector. Both sites are only in finnish, but feel free to browse around. After a decade of Joomla I'm quite taken with Processwire, although having no background in any sort of programming the dive into PHP felt akin to jumping from 10 and landing on your stomach. ;-) Site 1: http://www.lahdenrakennusurakointi.fi/ site 2: http://www.peltityo.com/ If the sites look somewhat similar, it's on purpose. Some structural pieces are being recycled to make work more efficient. Aside from Processwire we started using UIKIT and it's been a pleasant experience. Although I'd love to have automated way of using UIKIT lightbox for images added with CK editor.
    2 points
  6. @Robin S - I'll see what comes of those discussions over on the tracy github account, but if they don't implement an option to fix position, I will add one to the config settings that uses your css - thanks!
    2 points
  7. xdebug has always been slow (all over Google). Some things you can do Disable xdebug Profiler Disable xdebug Profiler enable trigger Disable xdebug auto trace Disable xdebug auto start (if you can) Helpful hints http://www.devinzuczek.com/anything-at-all/i-have-xdebug-and-php-is-slow/
    2 points
  8. You can also add class names on the ProcessPageEditImageSelect module options, but unfortunately UiKit lightbox plugin (https://getuikit.com/docs/lightbox) needs a wrapper div , so the code should be something like: <div uk-lightbox> <a href="image.jpg" data-caption="Caption"></a> </div> @Hurme, maybe you can try creating a new module based on@Martijn Geerts's Image Interceptor for this.
    2 points
  9. I am right now working on a quite similar project. In my case I import from an XML that I get through an API and populate product pages, check for there status etc. I can encourage you to go on the way you started. It is all pretty straight forward and nice to handle with the PW API. Your import code looks basically fine. So you shouldn't have major problems there. I set up a process module that creates a page in the backend where admins can manually trigger imports. If you would like to go that route, there is a skeleton Hello Process module that you can use and @bernhard wrote a great article on building admin pages with process modules. I find this approach much cleaner than doing all the logic in a template file. Regarding your concerns Use lazy cron module for automation. Each time you get a new JSON, loop through it and compare it to the single-movie pages you have and act on them (modify/delete) or create new ones. You can use custom fields on the single-movie template to store that Have a look at https://github.com/webcreate/infinite-ajax-scroll You can use kongondos Blog module or at least get a lot of inspiration from it ;-)
    2 points
  10. Non-exhaustive list of css ressources that we may need for some projects (if not mistaken, I haven't used any of them for the moment, except the Mozilla one): https://jonathantneal.github.io/sanitize.css/ https://github.com/jonathantneal/postcss-normalize http://browserl.ist/ https://github.com/browserslist/browserslist https://css-tricks.com/browserlist-good-idea/ https://evilmartians.com/chronicles/autoprefixer-7-browserslist-2-released https://leaverou.github.io/prefixfree/ https://github.com/ismay/stylelint-no-unsupported-browser-features https://github.com/anandthakker/doiuse https://stylelint.io/ https://github.com/ntwb/awesome-stylelint http://cssnano.co/ https://www.10bestdesign.com/dirtymarkup/ https://www.styled-components.com/ ( https://marksheet.io/ ) [ https://developer.mozilla.org/en-US/ ]
    1 point
  11. I love TracyDebugger, but today I had a hard time debugging some stuff and tried XDebug to get support for breakpoints. It was a quite straightforward setup: create a file on your server and output phpinfo() Copy the content of this page to the wizard: https://xdebug.org/wizard.php DON'T follow the instructions there, it's simpler with laragon (choose your files and paths of course): Download php_xdebug-2.6.0-7.1-vc14-x86_64.dll Move the downloaded file to C:\laragon\bin\php\php-7.1.14-Win32-VC14-x64\ext Enable xdebug via laragon check if everything worked by visiting the phpinfo() page again - it should show a section about xdebug now enable validaton in vscode by adjusting the user settings: "php.validate.enable": true, "php.validate.executablePath": "C:/laragon/bin/php/php-7.1.14-Win32-VC14-x64/php.exe", "php.validate.run": "onType", install "PHP Debug" extension by Felix Becker and read the instructions enable remote debugging by xdebug by adding this to your php.ini [XDebug] xdebug.remote_enable = 1 xdebug.remote_autostart = 1 create a testfile, eg home.php and set the debug config to "PHP" add breakpoints and start debugging by pressing the green play icon reload your page in the browser and the debugger will stop on lines 2 and 3 where we set the breakpoints. open vscode (if you don't have two screens) and follow code execution step by step. There are also some videos on youtube: https://www.youtube.com/watch?v=poty5nKk2m4 If XDebug slows down your server you can simple enable/disable it via laragon. This will require only two clicks and reload apache automatically
    1 point
  12. I've added a new filter called replacesubs that allows adding placeholders in format ((name)) to fields, and then use an array or a textarea content to fill them with values. You can apply it to a field content and all available placeholders will be replaced. Unlike getlines you can add new placeholders and data sources at any time, no need to touch the code. Plus you / your client can add HTML and formatting to them in the CKEditor.
    1 point
  13. Try: $datetofind=strtotime($date); foreach($page->special_days->find("date_value={$datetofind}, time_from!='', time_to!=''") as $special_day) { $slot_txt.=$special_day->time_from." to ".$special_day->time_to."<br/>"; }
    1 point
  14. I'm surprised this hasn't come up yet: https://tympanus.net/codrops/
    1 point
  15. Really impressive, Diogo! Excellent implementation of the design. And cool stuff having the animations settings manageable by the design team. Congratulations to you and the team!!
    1 point
  16. <distraction> Sonderforschungsbereich 923! Gotta love the German language! Sorry, but I just can't help myself. It sounds at the same time so bureaucratical and military, but also beautiful. I've heard many standup-comedians making fun of this simple fact, that in German it's easy (and allowed) to put words together to create a new one. For us, it's natural and normal, but for many other people it's like "what the heck"? </distraction>
    1 point
  17. Congrats. That's really well-done. I only found a slight responsive glitch where original and translated text overlap each other somewhere ("letter from A to B"), but that should be easy enough to fix.
    1 point
  18. That would only catch flat recursion though. The only way to catch deeper nesting I can think of would be to pass the starting object along. Something like this (untested): public function resetTrackChanges($trackChanges = true, $startingObj = null) { parent::resetTrackChanges($trackChanges); if(!$startingObj) $startingObj = $this; foreach($this->data as $key => $value) { if(is_object($value) && $value instanceof Wire && $value !== $startingObj) $value->resetTrackChanges($trackChanges, $startingObj); } return $this; } Of course, that method signature and logic might have to be implemented by all Wire derived classes that implement their own resetTrackChanges method. On second thought, that doesn't help either. You're spot on with keeping track of seen pages outside of recursion. On the other hand, multiple resetTrackChanges calls might happen in the same program run, so there needs to be a mechanism that cleans up the tracking list.
    1 point
  19. @BitPoet - You're a legend! I had dumped everything I could think of, including your suggestion, but this comment: triggered something in my tired brain It's because one of the other page fields points back to the initial user. I didn't think about the recursion happening from another field. The question of course now is how to prevent it happening. I feel like this is a PW bug because I think it's valid to tag a user from one as a "subscriber" and yet still tag the original as a "tester" for that user. I feel like that foreach loop in resetTrackChanges() needs to keep track of page ids that have already been processed. What do you think about this for a solution to propose to Ryan: public function resetTrackChanges($trackChanges = true) { parent::resetTrackChanges($trackChanges); $processedPages = new PageArray(); foreach($this->data as $key => $value) { $processedPages->add($value); if(is_object($value) && $value instanceof Wire && $value !== $this && !$processedPages->has($value)) $value->resetTrackChanges($trackChanges); } return $this; } PS I probably need to check that $value is an instance of Page before trying to add it
    1 point
  20. You might find out more if you print out the names ($key) of all properties of type page and their value's (page) ids. There should be some kind of repeating pattern then that leads from subscriber to tester back to subscriber, but their might be (quite) some hops in between.
    1 point
  21. Wow @gebeer, that info is really valuable! Thank you very very much!
    1 point
  22. Hey, thanks for the feedback @giannisok and for the solution @wbmnfktr. I have just updated to version 0.0.2 with the ability to unsubscribe and delete users. I also removed the 'string' type declarations, hope it works now with your PHP version @giannisok . When I have the time I'll change my dev machine setup, so I can test with different PHP versions. But since I use Valet, I think I can only downgrade to php5.6 anyway.
    1 point
  23. I also did some research the last days about GDPR and want to share some notes on that. Most of the information is taken off official sources, but is without engagement. To add one thing to @szabesz note: Beginning with GDPR in May 18 the state will be that you are allowed to set cookies without any further approval from the user, if they (the cookies) are necessary so that you site or service works. Usually that are session cookies, or cookies that store the user's language. Every other cookie (to track or analyse user data) needs permission to be set (the so called "opt-in"). In this case you are not allowed to set the cookie without user permission. In general (and in most situations enough) you need some things in order to be compliant with GDPR: a up-to-date data protection policy on the website frontend a GDPR compliant data processing contract with all companies that handle personal user data according to your order (like the hosting provider, or e.g. Google Analytics, or whatever..) a documentation of technical and organisational measures a list of all data processing activities That does not take into account if you handle very sensitive personal data (e.g. race or relegion). So of course, not all is related to ProcessWire, but only implementing technical measures is not enough to get compliant. At the end the note, that a very important part is also to document all things related to data privacy (regulations). We - as the data processors - have to burden of proof.
    1 point
  24. Just two words: Awesome & Insane A really nice and different design combined with such a nice animation-builder-toolkit. Great Work. Love it.
    1 point
  25. Congrats. Another very well crafted website of yours. I don't really like the scroll-jacking, but I really really like the menu. You also might want to look into hiding the video pop out button on opera.
    1 point
  26. Thanks @adrian, and in AOS there's also a "Add Trash action also for non-SuperUsers" feature that might come handy.
    1 point
  27. I personally would always create pages instead of repeater items. Pages can become almost everything later on as repeaters are more or less part of a page and a little more difficult to handle. A while back I created something to manage course bookings. Every booking ended as a single page in the backend. From there on the client was able to generate confirmation-, contract- and invoice-PDFs. Doing that with repeaters in a page might work in some kind but will end in way more work/hassle. Creating log entries is always a good idea as well. Kind of fallback.
    1 point
  28. Of course the core now has the "trash" page list action, but AOS also has a great "delete" action implementation with an inline confirmation step.
    1 point
  29. Hi @kongondo, Thanks for the quick reply, despite all the collusion against you . I'm not sure where it should live. I do think you shouldn't get to many categories/media types. From a user perspective it would make sense to be able to add them to /video/. But I'm not sure how how much work it would be to integrate this into your current Media Manager. Right now I've created a Inputfield and Fieldtype module (for both Vimeo and YouTube). In a simple input field you enter the URL of the video and the module then retrieves thumbnails and additional data form the video using the Vimeo and Google API's. In the config of the module you can set an image field where the thumbnails will be stored. Once additional data has been retrieved you get a video embedded into the backend and an Object with the embed code and additional data to the Frondend. I'll send you the Bitbucket repo's in a PM. I'm curious what you think of the integration possibilities. Best, Harm
    1 point
  30. There's a little gotcha related to this module: if you have it enabled on a late version of ProcessWire, it could break the language translation UI if one or more of your translation strings include the phrase "</head>". ProcessPageDelete inserts a script block in front of all of those, which breaks the scripts on the page. None of such phrases in the core (by default) as far as I can tell, but it is found from some rather popular modules (Minify, FormBuilder). Not sure if this module is even needed on newer installations – just happened to have it installed on a site I'm currently updating from 2.x to 3.x, ran into this issue, and thought I'd mention it in case it will save someone else a bit of debugging time
    1 point
  31. You're right about XDebug slowing everything to a crawl. Have you tried these tricks involving the profiler and remote host? http://www.sinaru.com/2015/09/25/improving-php-xdebug-speed/
    1 point
  32. @Zeka you need to go to Gmail settings and allow access for less secure apps there. Then it should work.
    1 point
  33. I think you'll find it easier if you use a plain PHP array so that you can make it nested/multidimensional. You can't have nested PageArrays you see. I'm not sure I 100% understand your scenario, but hopefully this helps: // Get $allPlayers somehow $uniqueGroups = []; foreach($allPlayers as $player) { // Define the $groupId // Use an underscore (or other non-integer) in the $groupId to force it to be a string, not an integer // That way when array_multisort() is used later the keys will be preserved $groupId = $player->team->id . '_' . $player->group->id; // Optional: add $groupId to $player as a custom property in case you need it later $player->groupId = $groupId; // Add player to $uniqueGroups using $groupId as key $uniqueGroups[$groupId]['players'][] = $player; } bd($uniqueGroups, 'uniqueGroups'); // have a look at what's in $uniqueGroups foreach($uniqueGroups as $groupId => $data) { $uniqueGroups[$groupId]['karma'] = 0; // initialise to zero $uniqueGroups[$groupId]['bonus'] = 0; // initialise to zero // Tally up the group's karma foreach($data['players'] as $player) { $uniqueGroups[$groupId]['karma'] += $player->karma; } // Do the same for bonus //... } bd($uniqueGroups, 'uniqueGroups'); // have a look at what's in $uniqueGroups // Sort the $uniqueGroups by karma (for example) array_multisort(array_map(function($group) { return $group['karma']; // return the value you want to sort by }, $uniqueGroups), SORT_ASC, $uniqueGroups); bd($uniqueGroups, 'uniqueGroups'); // have a look at what's in $uniqueGroups See this article for a good introduction to array_multisort() - in the code above array_map() is used to get the sort values instead of another foreach().
    1 point
  34. This CSS seems to be working well for me so far... #tracy-debug-bar { position:fixed !important; left:auto !important; top:auto !important; right:0 !important; bottom:0 !important; }
    1 point
  35. Not sure what you mean with automated way but the CKEditor allows for using customized css under the Source button in the menu bar. Using UIKits lightbox css there should do the trick doesn't it ?
    1 point
  36. That's really a strange way for the host to answer, because ssl is really not related to the cms (besides maybe generating https links and redirecting). But enabling ssl does need to be setup on the webserver. For redirection to https see the .htaccess file and urls in processwire are most often relative ones, so there's probably not much to do on the url generation side.
    1 point
  37. This thread is literally years old. See here for the options regarding disabling the session: https://processwire.com/blog/posts/multi-instance-pw3/#more-session-control
    1 point
  38. You can use page.fieldname on the right hand side in your selector, so you need something like this: parent=/hotels/, template=hotel, hotel_country=page.destination_country, sort=title There's a discussion with a similar setup here:
    1 point
  39. Is anyone interested in the sticky implementation shown two posts above? I think it's a simple but reliable implementation that can be handy not only in the admin but on frontend too.
    1 point
  40. I made it work with PHP 5.x just by changing one line. SubscribeToMailchimp.module - Line 23 - before: public function subscribe(string $email, array $data = [], string $list = "") { SubscribeToMailchimp.module - Line 23 - after: public function subscribe( $email, $data = [], $list = "") { This works without any problems so far.
    1 point
  41. You're correct that data string values are only translated for find queries, but not runtime selectors. But processwire just uses `strtotime` so you can easily use that on your own: strtotime('today')
    1 point
  42. Thanks for sharing Daniels! It would be a good idea to make it backwards compatible with PHP 5.5 so that it works on older installations otherwise mention that it has PHP 7 dependency. Regards!
    1 point
  43. Very welcome additions, thank you to all who participated!
    1 point
  44. Hi, just wanted to share something I came across while working on an import module for XML data from a web service. The XML I got was not huge, but still, loading around 3.5 MB of XML with 250+ large child nodes into memory at once with simplexml_load_file() and then looping over it had significant impact on performance. I searched for a solution and found this great article about how to parse large XML files. It basically explains how to utilize the native XMLReader class together with SimpleXMLElement to handle such situations in a memory efficient way. After implementing it I got a significant improval on perceived performance. No comparison in numbers to share here as I'm a bit short on time.
    1 point
  45. @theo Thanks - does it help if you change "get" to "findOne"? I'm experimenting with a new sticky pagelist action, loosely based on the ProcessPageListMultipleSorting module. The idea is to create a global "sticky" field and hook into ProcessPageList::find to prepend sort=-sticky to the original selector (keeping template and page level sort intact). This way un-stickying a page will restore the original sort order. When sticky-ing a page it finds the sibling with the highest sticky value and sets it to an even greater value, so it will go to the top. It works fine so far, the minor glitch is that if you would like to move eg the second to topmost sticky page to top you'll need to unstuck first and then re-sticky (or edit the sticky field value manally). I find the idea to add extra move up/down sticky actions an overkill. The order also can be queried on the frontend because the new sticky field is a real field.
    1 point
  46. You need to use $page argument. Also remember to check if field is actually the field you want. wire()->addHookAfter('InputfieldRepeater::renderRepeaterLabel', function (HookEvent $e) { /** @var Page $page */ $field = $e->object->hasField; // check the field if ($field != "events_detail_dates") return; $page = $e->arguments('page'); $e->return = date('D. j F Y', $page->events_detail_dates_start_date); });
    1 point
  47. Just in case someone's looking for an example to get all tags that are referenced by pages of specific template types, ordered by count, limited to 10: if ( ! $config->ajax) throw new Wire404Exception(); $input->whitelist('query', $sanitizer->selectorValue(urldecode($input->get('query')))); $query = $input->whitelist('query'); $typeTemplateIds = join(', ', $templates->find('name=templateNameA|templateNameB')->getKeys()); $proposalTable = $fields->get('tagsPageReferenceFieldName')->getTable(); $titleTable = $fields->get('title')->getTable(); $sql = <<<SQL SELECT proposals.name, {$titleTable}.data as title FROM pages INNER JOIN {$proposalTable} ON pages.id = {$proposalTable}.pages_id INNER JOIN pages as proposals ON {$proposalTable}.data = proposals.id INNER JOIN {$titleTable} ON proposals.id = {$titleTable}.pages_id WHERE pages.templates_id IN ({$typeTemplateIds}) AND {$titleTable}.data LIKE :query GROUP BY {$proposalTable}.data ORDER BY count({$proposalTable}.data) DESC LIMIT 0, 10; SQL; $statement = $database->prepare($sql); $statement->bindValue(':query', '%' . $query . '%', PDO::PARAM_STR); $statement->execute(); $proposals = $statement->fetchAll(PDO::FETCH_ASSOC); header('Content-Type: application/json; charset=utf-8'); echo json_encode($proposals); Enjoy
    1 point
  48. I'm not entirely sure I know how to answer all your questions here because it sounds like you may trying to do things with InputfieldFile is may not necessarily be designed for. If that's the case, you may be better off extending it as a new PHP class, or copying its code to new module, rather than trying to achieve these all with hooks. Another thing I'm not sure about is whether you are talking about a front-end or back-end context. If dealing with a front-end context, the ajax uploading will not work. In some cases you may have to disable it on back-end use too (see the commented line below for how to do that). InputfieldFile is really meant to be used in combination with FieldtypeFile and within the page editor. But it is possible to use it outside of that context. Though you will still need to supply it a Page object so it has a known storage location, but the given Page doesn't need to have a files field. Meaning, it can be any Page, even an admin one. Here's an example of how you might use InputfieldFile on it's own: // page the file will be stored with (doesn't have to have a files field) $myPage = $pages->get('/path/to/your/page/'); // optionally set the name of existing file(s) that will be present (or leave it blank) $myFiles = array( $myPage->filesManager->path . 'myfile.txt' ); // file extensions you allow $myExts = 'pdf csv txt'; // -------------------------------------------- // create the form $form = wire('modules')->get('InputfieldForm'); // create the files field $f = wire('modules')->get('InputfieldFile'); $f->name = 'my_files'; $f->label = 'My Files'; $f->extensions = $myExts; $f->overwrite = true; // $f->noAjax = true; // uncomment if necessary $pagefiles = new Pagefiles($myPage); foreach($myFiles as $filename) { $pagefile = new Pagefile($pagefiles, $filename); $pagefiles->add($pagefile); } $f->attr('value', $pagefiles); $form->add($f); // add a submit button $f = wire('modules')->get('InputfieldSubmit'); $f->attr('name', 'submit_form'); $form->add($f); // ------------------------------------------- // process the form if(wire('input')->post('submit_form')) { $form->processInput(wire('input')->post); $pagefiles = $form->get('my_files')->value; foreach($pagefiles as $pagefile) { echo "<p>Your file: $pagefile->url</p>"; } }
    1 point
  49. I'm not sure why you are getting that behavior with the redirects. I don't personally use this style of redirect, so don't know the options available. It does appear that it's getting your redirects mixed in with ProcessWire's rewrite rules. When you use a RewriteRule redirect, you add the 'L' option to it to prevent processing any more rules, like this: RewriteRule ^about-us/?$ /about/ [R=301,L] So I'm thinking you need the equivalent of the 'L' option in your redirects, but I don't know what the equivalent is for that type. If it were me, I'd just use the above style of Rewrite Engine rules, rather than Redirect/RedirectMatch. Though if you prefer the type you are using, I bet there would be a solution in Apache's Redirect/RedirectMatch docs. However, I find these a little difficult to wade through sometimes.
    1 point
×
×
  • Create New...