Jump to content

Leaderboard

Popular Content

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

  1. Just celebrated the creation of my 25000th page on the first website www.birthfactdeathcalendar.net I made with ProcessWire, about five years ago. 25000 pages means over 17000 individual public pages and a few thousand as selectlists (cities, states, countries, occupations,....). All of this would never have been possible with the great support of members here. Thank you all! And the lucky winner is Sabine Pass, Texas, United States, where Jiles Perry Richardson aka The Big Bopper was born on 24 October 1930.
    5 points
  2. I got the news yesterday, did you was aware that Github let you have unlimited private repositories for free since January, 7 ? ? Precisions from Github Support : Comparisons : Free functionality GitLab GitHub Private repositories Yes Yes Number of collaborators Unlimited 3 Wiki Yes No (public or paid only) Pages Yes No (public or paid only) Capacity 10GB 1GB Indicates who is paying No Yes Free CI 2,000 min. Maybe a free tier for Actions on Azure Entire DevOps lifecycle Yes No Location of the repo Anywhere Not in groups/orgs API concurrent rate limit 36000 5000
    4 points
  3. Changelog The changelog can now be found in the module directory itself, see CHANGELOG.md.
    4 points
  4. Hi Matt, Your code looks like it should work okay so not sure why it isn't. But a few general observations... Making the connection between pages with the Listing template and pages with the PriceSpy template via only the title is not very robust. What if one of these pages needed to change title? You'd then have to do maintenance on all related pages or else the connection would break. I think it would be better to make the connection via Page Reference fields or possibly a parent-child relationship. Using a text field for prices is not ideal, and I think you should exclude the currency symbol from the field (I'm assuming the $ sign is in the field because I can't see it being added separately in your code). Better to use a decimal field type and prepend the currency symbol in your template. Then there would be fewer complications with sorting like you're experiencing now. It looks like you're using a templating language (is that Smarty?), but there is business logic in the template also which sort of defeats the most common reason for choosing to use a template language separate from PHP. If you're not bothered about enforcing a strict MVC pattern it would be simpler just to stick to plain PHP in your template files.
    4 points
  5. Sure, i don't see any reason I couldn't maintain the module; I think it is basically stable and we'd just need to all contribute our changes, test it and then it should be good to go... I'll try and get that setup soon..
    3 points
  6. Microsoft acquired GitHub last October. They likely need to present some growth figures for the first quarter to the board. So probably no catch (in the short run).
    3 points
  7. @neophron Please open another thread for this, because it has almost nothing to do with the german language pack and is more a general PHP question. However I will try to give you advice in the right direction. For locales to work, they have to be existent on the system. You can get a list of all installed locales on Linux if you run `locales -a` in a shell. The name of a locale depends on the OS and which derivate you are using. So for german for example the locales name could be one of the following: $loc_de = setlocale(LC_ALL, 'de_DE@euro', 'de_DE', 'deu_deu'); or it might even be `de_DE.UTF8`or something else. @bernhard: strftime is dependent on the locale, so it won't work if the correct locale isn't set. Here is a little script I wrote that shows you the preferred locale on your system. However, there might be locales missing like in my german example. So please run `locale -a ` in a shell to see whats the correct locale name. <?php echo '<h1>test for locales</h1>'; /* try different possible locale names for english GB as of PHP 4.3.0 */ echo '<p>'; $loc_en = setlocale(LC_ALL, 'english_gbr', 'english_britain', 'english_england', 'english_great britain', 'english_uk', 'english_united kingdom', 'english_united-kingdom'); echo "Preferred locale for english GB on this system is '$loc_en'"; echo '<br/>' . strftime("%A %d %B %Y", mktime(0, 0, 0, 12, 22, 1978)); echo '<p>'; $loc_fr = setlocale(LC_ALL, "fr_FR", "fra", "fr_FR.UTF8", "French_France"); echo "Preferred locale for France on this system is '$loc_fr'"; echo '<br/>' . strftime("%A %d %B %Y", mktime(0, 0, 0, 12, 22, 1978)); /* try different possible locale names for english USA as of PHP 4.3.0 */ echo '<p>'; $loc_enusa = setlocale(LC_ALL, 'english_usa', 'english_america', 'english_united states', 'english_united-states', 'english_us'); echo "Preferred locale for english USA on this system is '$loc_enusa'"; echo '<br/>' . strftime("%A %d %B %Y", mktime(0, 0, 0, 12, 22, 1978)); /* try different possible locale names for german as of PHP 4.3.0 */ echo '<p>'; $loc_de = setlocale(LC_ALL, 'de_DE@euro', 'de_DE', 'deu_deu'); echo "Preferred locale for german on this system is '$loc_de'"; echo '<br/>' . strftime("%A %d %B %Y", mktime(0, 0, 0, 12, 22, 1978)); /* try different possible locale names for spanish as of PHP 4.3.0 */ echo '<p>'; $loc_es = setlocale(LC_ALL, 'esp_esp', 'esp_spain', 'spanish_esp', 'spanish_spain'); echo "Preferred locale for spanish on this system is '$loc_es'"; echo '<br/>' . strftime("%A %d %B %Y", mktime(0, 0, 0, 12, 22, 1978)); /* try different possible locale names for dutch as of PHP 4.3.0 */ echo '<p>'; $loc_nl = setlocale(LC_ALL, 'nld_nld'); echo "Preferred locale for dutch on this system is '$loc_nl'"; echo '<br/>' . strftime("%A %d %B %Y", mktime(0, 0, 0, 12, 22, 1978)); function smarty_modifier_number_format( $string, $decimals = 2 ) { $locale = localeconv(); // setlocale( LC_NUMERIC, null ); $string = str_replace(',', '.', $string); $thousand_separator = ( $locale['thousands_sep'] == '' ) ? '.' : $locale['thousands_sep']; $decimal_separator = $locale['decimal_point']; return @utf8_encode(number_format( $string, $decimals, $decimal_separator, $thousand_separator )); } echo "<br>"; echo smarty_modifier_number_format('12,90 g'); After finding the correct locale you have to write it into the "C" setting in ProcessWire like described here https://processwire.com/talk/topic/15691-warning-about-server-locale-after-update-from-3052-3053-help/?do=findComment&amp;comment=155654
    3 points
  8. Correction to this: in the blog post Ryan mentions the wire-prefixed Functions API methods and explains that they have the benefit of being always available regardless of config settings (essentially the same thing that the comments in the FunctionsWireAPI.php file say) – but there is a comment to the blog post in which he mentions that these are actually "for an internal core purpose". @ryan, this might be one of the things that should be clarified somewhere: if wire-versions of the Functions API methods are indeed not intended for public use, it should probably be mentioned somewhere (other than a single comment to the Functions API announcement blog post). If one reads the blog post and doesn't check all the comments, or checks the code / code comments directly (which is a common thing to do in our context), this is currently not obvious.
    3 points
  9. $out = ''; if(count($story->galleria)) { $firstImage = $story->galleria->first(); $out = "<img src='{$firstImage->url}' alt='{$firstImage->description}'>"; } else { // no images; do something else } echo $out;
    3 points
  10. ---DEPRECATED--- Please use RockSkinUikit Just install the module and you can change the look&feel of your admin instantly by changing only one color: Download: https://modules.processwire.com/modules/rock-skin-uikit/ https://github.com/BernhardBaumrock/RockSkinUikit I'd be very happy if any of the CSS pro's could do some final improvements to the default.less theme - though I'm already very happy with the result! Happy Admin-Theming ? PS: At the moment this downloads a fork of the original AdminThemeUikit module because one method is not yet hookable. You can support this request here: https://github.com/ryancramerdesign/AdminThemeUikit/pull/77 and then I can update my module to pull the original theme from ryan.
    2 points
  11. This will be more of a quick tip, and maybe obvious to many of you, but it's a technique I found very useful when building display options. By display options I mean fields that control how parts of the page are displayed on the frontend, for example background colors, sizing, spacing and alignment of certain elements. I'll also touch on how to make those options intuitive and comfortable to use for clients. It basically involves setting up option values that can be used directly in CSS classes or as HTML elements and mapping those to CSS styling (which can be quickly generated in a couple of lines using a pre-processor such as SASS). Another important aspect is to keep the option values seperate from their corresponding labels; the former can be technical, the latter should be semantically meaningful. The field type that lends itself to this this seperation of concerns is the Selectable Options field, the following examples mostly use this field type. Note that this module is part of the ProcessWire core, but not installed by default. The following examples all come from real projects I built (though some are slightly modified to better demonstrate the principle). #1: Headline levels & semantics For a project that had many pages with long texts, I used a Repeater field to represent sections of text. Each section has a headline. Those sections may have a hierarchical order, so I used a Selectable Option field to allow setting the headline level for each section (you can guess where this is going). The definition of the options looks something like this (those are all in the format value|label, with each line representing one option, see the blogpost above for details): h2|Section headline h3|Sub-section headline Of course, the PHP code that generates the corresponding HTML can use those values : // "sections" is the repeater field foreach ($page->sections as $section) { // create an h2 / h3 tag depending on the selected option (called headline_level here) echo "<{$section->headline_level->value}>{$section->headline}</{$section->headline_level->value}>"; echo $section->body; } That's a pretty obvious example, but there are two important takeaways: I only used two options. Just because there are six levels of headlines in HTML, doesn't mean those are all relevant to the client. The less options there are, the easier it is to understand them, so only the options that are relevant should be provided. In this case, the client had provided detailed, structured documents containing his articles, so I could determine how many levels of hierarchy were actually needed. I also started at h2, since there should be only one h1 per page, so that became it's own field separate from the repeater. The two options have a label that is semantically relevant to the client. It's much easier for a client who doesn't know anything about HTML to understand the options "Section headline" and "Sub-section headline" than "h2" and "h3". Sure, it can be cleared up in the field description, but this way it goes from something that's quickly explained to something that needs no explanation at all. #2: Image width and SASS In the same project, there was also an image section; in our layout, some images spanned the entire width of the text body, others only half of it. So again, I created an options field: 50|Half width 100|Full width In this case, I expected the client to request different sizes at some point, so I wanted it to be extensible. Of course, the values could be used to generate inline styles, but that's not a very clean solution (since inline styled break the cascade, and it's not semantic as HTML should be). Instead, I used it to create a class (admittedly, this isn't strictly semantic as well): <img src="..." class="w-<?= $section->image_width->value ?>"> With pure CSS, the amount of code needed to write out those class definitions will increase linearly with the number of options. In SASS however, you only need a couple of lines: @each $width in (50, 100) { .w-#{$width}{ max-width: percentage($width/100); } } This way, if you ever need to add other options like 25% or 75%, you only need to add those numbers to the list in parenthesis and you're done. You can even put the definition of the list in a variable that's defined in a central variables.scss file. Something like this also exists in Bootstrap 4 as a utility, by the way. It also becomes easier to modifiy those all at once. For example, if you decide all images should be full-width on mobile, you only need to add that once, no need to throw around !important's or modify multiple CSS definitions (this is also where the inline styles approach would break down) : # _variables.scss $image-widths: (25, 50, 75, 100); $breakpoint-mobile: 576px; # _images.scss @import "variables"; @each $width in $image-widths { .w-#{$width}{ max-width: percentage($width/100); @media (max-width: $breakpoint-mobile) { max-width: 100%; } } } One important gotcha: It might be tempting to just use an integer field with allowed values between 10 - 100. In fact, the amount of SASS code would be identical with a @for-directive to loop throuh the numbers. But that's exactly what makes point-and-click page builders so terrible for clients: too many options. No client wants to manually set numerical values for size, position and margins for each and every element (looking at you, Visual Composer). In fact, having too many options makes it much harder to create a consistent layout. So in those cases, less is more. #3: Multiple options in one field Another example for repeatable page sections, this time for a two-column layout. The design included multiple variants regarding column-span and alignment. Using a 12-column grid, we needed a 6-6 split, a centered 5-5 split, a left-aligned 6-4 split and a right-aligned 4-6 split. I didn't want to litter the repeater items with options, so I decided to put both settings in one field (called something like Column layout) : center_6_6|6 / 6 (Centered) center_5_5|5 / 5 (Centered) left_6_4|6 / 4 (Left-aligned) right_4_6|4 / 6 (Right-aligned) As long as the value format is consistent, the individual options can be quickly extracted and applied in PHP: [$alignment, $width['left'], $width['right']] = explode('_', $section->column_layout->value); echo '<section class="row justify-content-' . $alignment . '">'; foreach (['left', 'right'] as $side) { echo '<div class="col-lg-' . $width[$side] . '">'; echo $section->get("body_{$side}"); echo '</div>'; } echo '</section>'; If you don't recognize the syntax in the first line, it's symmetric array destructuring, introduced in PHP 7.1. For older versions you can use list() instead. This example uses Bootstrap 4 grid classes and flexbox utility classes for alignment. The corresponding CSS can be quickly generated in SASS as well, check the Bootstrap source code for a pointer. Again, I'm limiting the options to what is actually needed, while keeping it extensible. With this format, I can easily add other column layouts without having to touch the code at all. #4: Sorting page elements A final example. In this case I was working on a template for reference projects that had three main content sections in the frontend: A project description, an image gallery and embedded videos (each using their own set of fields). The client requested an option to change the order in which those sections appeared on the page. Had I known this earlier, I maybe would have gone for a Repeater Matrix approach once again, but that would have required restructuring all the fields (and the corresponding code), so instead I used a Selectable Option field (labelled "Display order"). My approach is similar to the one from the last example: body_gallery_embeds|Description - Gallery - Videos body_embeds_gallery|Description - Videos - Gallery gallery_body_embeds|Gallery - Description - Videos gallery_embeds_body|Gallery - Videos - Description embeds_body_gallery|Videos - Description - Gallery embeds_gallery_body|Videos - Gallery - Description Since there are six possibilities to sort three items, this is the expected number of options. So I decided to include them all, even though some are probably never going to be used. I also tried to use a predictable order for the options (i.e. the options come in pairs, depending on what element is first). And here is the code used on the frontend: // render the template files for each section and store the result in an associative array $contents = [ 'body' => wireRenderFile('partials/_section-body.php', $page), 'gallery' => wireRenderFile('partials/_section-gallery.php', $page), 'embeds' => wireRenderFile('partials/_section-embeds.php', $page), ]; // e.g. 'gallery_body_embeds' => ['gallery', 'body', 'embeds']; $order = explode('_', $page->display_order->value); // echo the contents in the order defined by the option value foreach ($order as $item) { echo $contents[$item]; } You can see how it will be easy to add an additional section and integrate it into the existing solution. Though a fourth item would result in 4! = 24 possibilities to sort them, so at that point I'd talk to my client about which layouts they actually need ? Conclusion I always try to keep my code and the interfaces I create with ProcessWire extensible and intuitive. Those are a couple of solutions I came up with for projects at work. They are certainly not the only approach, and there is nothing super special about those examples, but I found that putting a little more effort into defining options with meaningful labels and using option values that I can use directly in my templates makes the result less verbose and more maintainable. Some or most of this tutorial may be immediately obvious to you, but if you made it this far, hopefully you got something out of it ? Feel free to share your own methods to create display options, or how you would've approached those problems differently. Thanks for reading!
    2 points
  12. For the wiki, there was two issues addressed about that. I will be able to give more infos in the next weeks. But yes, wiki are gone for free private repos on personal accounts. More precisions from the support about Accounts, Private repos and Organization as I tried to make an organization with free private repos but it not worked - of course ?
    2 points
  13. As far as I can tell, it might not be possible yet. There seems be some "work arounds" that can be found here: https://stackoverflow.com/questions/30121969/making-a-private-githubs-wiki-public https://help.github.com/articles/changing-access-permissions-for-wikis/ (though I am not sure what can truly be done here, as I dont have github pro account. With the "free" private repo, you lose access to wikis)
    2 points
  14. Hello, no, there is no need to change the vendor .htaccess file to do this. At first sight I also thought it would be necessary but it is not.
    2 points
  15. By the way, I was just wondering what might be the recommended alternative to defining custom API variables (particularly by modules) for the Functions API? Is there one? I for one have found these very useful, as they provide a way for module authors to add developer features that feel consistent with the "native" API. In case custom API variables are only feasible with the non-Functions API, then perhaps that should be documented as well; or am I just overthinking this? ?
    2 points
  16. OT, but though to mention it here. I have been working on a site profile (still in alpha >>> it's been ages! other things got in the way) inspired by the Electron API Demos app that will do this and more. Essentially, it teaches you to use the API. On install, you get nothing but the 'blank profile'. You choose a topic and It teaches how to accomplish what is covered in that topic, e.g. the AP to create/edit/delete fields, templates, pages, etc.
    2 points
  17. Hello, we found the following solution that is quite similar to the suggestion from Autofahrn. Our setup includes two languages - de (german) as default for *.de domain (default language) - en (english) for *.com domain In _init.php there is just: if (preg_match("/(:2284|\.com)/", $config->httpHost)) { $user->language = $languages->get('englisch'); } Your question no. 2: It is important that you configure the settings for your root page to "/" for each language. In that case PW doesn't prefix your URL paths for the children. Be careful! In case you use the front page editor - when a child page has the same path for every language, the front page editor is not able to save the page correctly. You have to use the backend. But if there are differences, for example *.com/imprint and *.de/impressum - the front page editor works fine.
    2 points
  18. Clever idea. I've just test-implemented that on one of my multi-language sites with .de and .com domains and it works pretty smooth following these steps: all DNS entries point to the same PW instance root in site/config.php I've added all allowed domain names in _init.php I've quickly added this (only for com, should match a field in language setting): if(strpos($config->httpHost, ".com") > 0) { foreach($languages as $lang) { if($lang->name == 'en') { $user->language = $lang; break; } } } That's it, now all language fields follow the selected language. Switching between languages is now switching between domain names. Thanks for that hint!
    2 points
  19. Here I'm writing up about my first ProcessWire site, Reached.space, a blog and directory about shops which offer international shipping. I'm from The GrayFly Group, which is the registered trade name for GrayFly Stationery, LLC, a limited liability company registered in the state of Kentucky, USA. You might ask, why is a stationery company creating websites?! Well, in a way both activities are very similar: both activities have the goal of getting written messages across in a pleasing manner to the reader. With that out of the way, let's move on and explain what went on behind the scenes of the Reached.space site: Template I used a free CSS-based template from W3CSS at https://www.w3schools.com/w3css/w3css_templates.asp , using mainly the "Architect" template as the basis and modifying it as needed. Pagination The pagination feature of ProcessWire was very helpful here; I kept the home page to just two blogroll articles so that the reader was not overwhelmed, but upon pressing "more articles" the remainder of the blogroll is paginated with 4 articles to a page. Screen reader I made adjustments to my usage of the template to make it screen-reader-friendly. I used the Google Chrome extension to test out how the site would be handled with a screen reader. Security Security is always important, so I was thrilled to find a great all-in-one-place security guide in the ProcessWire docs at https://processwire.com/docs/security/ - I simply went through the guide and did what it said, using it as a checklist. Modules As far as I'm aware, the only additional modules I used (that were not already activated by default in standard PW install) were the Upgrade and Upgrade Checker modules. The main reason for this was security considerations, but it was also an added convenience and peace of mind to have it check for updates every time I logged in. However, I did use additional software that was not modules, as described below. Other software - Simple HTML DOM Here I was very fortunate to receive help from the ProcessWire community on the forum. Due to the site's monetization model being affiliate marketing, I wished to make all my external links nofollow and target _blank by default. User @Robin S was instrumental in showing me how to do this using Simple HTML DOM in the forum post https://processwire.com/talk/topic/17295-solved-how-to-make-external-links-nofollow-and-target-_blank-by-default-if-using-source-code-toggle-in-editor/ Other software - Google Analytics cookie manager My site requirements for GDPR were specific enough that I felt I would rather develop my own code to handle Google Analytics tracking, which I'll describe here. I wanted to be certain GA tracking was disabled by default requiring opt-in, instead of opt-out. I also included in the Cookie Manager some written info about third party cookies (these are placed when clicking on affiliate links) and how the user can avoid such tracking (turn off third party cookies in their browser settings). I also disabled front-end PW cookies as described here: https://processwire.com/talk/topic/15270-session-storage-and-lifetime/ Google Analytics cookie settings The Google Analytics cookie setting code was done using JavaScript. I used a session storage variable to indicate whether the user had a) accepted GA tracking cookies b) declined them or c) had not made a choice yet. I also had to make some changes also to the <head> code to ensure Google Analytics cookies were not set unless the user had accepted them. Efficiency - optimizing 404s I used the guide at https://processwire.com/blog/posts/optimizing-404s-in-processwire/ to sinkhole bot-driven 404 requests to a static 404 file. Back office pic Below is an image of how ProcessWire allows helpful field descriptions and displays them when used in templates, so that when I come to actually use or enter content in fields I created months ago, I know what the ramifications are. Very helpful. Also, when using the back office I found the Reno admin theme to be very pleasing, efficient, and easy to use.
    1 point
  20. RockLESS Download: https://modules.processwire.com/modules/rock-less/ Docs: https://github.com/BernhardBaumrock/RockLESS
    1 point
  21. A few more minor bits and pieces... The left-side-only border on the three columns under the home page code samples looks a little off: It would look better if the borders were only on the inside edges of the columns, like the three column example in the footer: I think others have already commented about the blog overview layout. I find this layout confusing to parse because the box alignment is stronger vertically than it is horizontally, which makes me scan the posts top to bottom when actually the order is left to right. Having equal box heights within each row would improve this somewhat but I think there will still be some confusion for readers trying to work out the order. Maybe we should consider an entirely different layout for this page? Also regarding the blue box style - the are some small issues with the little circles on the corners. Sometimes they are stacking behind a neighbouring box so the line goes through the circle instead of behind it. This can be seen in the screenshot above. And perhaps there should be a circle in every corner of each box (it doesn't matter if the circles are doubled-up where two boxes meet) because the visual logic of where the circles are missing doesn't make much sense in some places: Lastly, I spotted a couple of little issues in some code blocks. 1. LSEP character showing here: https://processwire.com/docs/start/templates/ 2. $ variable symbol sometimes gets wrong colour here: https://processwire.com/docs/selectors/
    1 point
  22. Introduced in ProcessWire 3.0.117 https://processwire.com/blog/posts/processwire-3.0.117-core-updates/
    1 point
  23. @MoritzLost Great tutorial I often use Repeater Matrix field with an added Fieldset Page containing the styling options for that section. FS page means it's easy to add a single field to different templates. Like you, I only give the client what options they need rather than the complete set. In the example below, the HTML theme is Canvas which is based on Bootstrap.
    1 point
  24. No authentication whatsoever? Surely you don't mean 'free-for -all' editing? I'm sure I'm missing something. Please explain.
    1 point
  25. I still really like this solution:
    1 point
  26. Literally days before this announcement I needed a private repository for a new project, and registered a Bitbucket account for that. Haven't migrated back yet, but probably will ? GitHub provides free private repositories for max 3 collaborators, while Bitbucket has a limit of 5 collaborators for a free private repository. Not a huge difference... unless, of course, you're running a team of 4-5 developers and want to save a few bucks ?
    1 point
  27. Yeah, they are helpful in several situations. And they could also be tweaked for better mobile support. See https://modules.processwire.com/modules/admin-modalception/ for example. Maybe if you encounter real problems you could file an issue on github which describes the problems.
    1 point
  28. Such a script could be a nice troubleshooter for beginners if it were included in the backend somewhere - maybe worth a PR? ? It could be a simple InputfieldMarkup where the Locale translation happens.
    1 point
  29. Perhaps you need to change this $pages->find("template=PriceSpy, sort=price, title=$item_title, limit=1") to this: $pages->find("template=PriceSpy, sort=price, title=$item_title")->first()
    1 point
  30. Hey @Macrura - these sound like very useful additions - I haven't had to deal with multiple domains for the one site just yet, but I can see it coming up for me shortly. I'd love to see this module have a new life. I used to use WireMailSMTP with MailGun, but recently it started having issues with CC'ing so I decided to start using this and it's so much faster using the MailGun API compared with SMTP. I don't suppose you'd like to step up and take on supporting this? I'd like to, but I already have way too many modules. Cheers!
    1 point
  31. I also have made some simple customizations to this module that I feel are worth putting into the official version, and for at least 1 site that run this on, these changes are critical for the module to work. If anyone were to take it over, I could submit a pull request, or describe the change/requirement and let the maintainer implement in their interpretation of best practice. for one, you might notice that this module's config provides a field for the 'Domain Name'. However, in my case, the 'from' email may use different domains. My Mailgun account has many domains configured. So instead of the $options array item called CURLOPT_URL using the module's entered domain name, i need it to use the domain from the $mail instance's from/sender. To this end i created a method getDomainName() as follows: private function getDomainName() { return substr(strrchr($this->mail['from'], "@"), 1); } then replace the CURLOPT_URL with CURLOPT_URL => "{$this->apiUrl}" . $this->getDomainName() . "/messages", I guess for this module to be flexible enough going forward, there may need to be an additional setting, where you either enter a domain name in the module config, or you tell the module to 'auto' populate the domain name from the sender domain.
    1 point
  32. Hi Moritz, big thanks for this one too! ? I use a similar setup, but with page references instead of option fields.
    1 point
  33. I've been following this topic from the sidelines with mixed feelings. I've always considered ProcessWire's API exceptionally clean and easy to understand, and technically that hasn't changed, but I do find it confusing as well that there are so many ways to achieve essentially the same thing – except that some will only work on certain situations (bootstrap, templates, modules, multi-instance, ...) or may have performance benefits or perhaps won't be available on all sites depending on config settings, etc. I'm very eager to hear what you've got to say about this, and I'm hoping that it'll make everything crystal clear again ? --- Either way, the tab idea (different approaches in different tabs) is, in my opinion, awesome. Combined with per-tab instructions on where and how to use each approach (could be a tooltip with short summary and a link to full documentation page) this would be a huge improvement. If functions API calls are shorter, then show those by default – it won't take anything away from the marketing / functions API promotion perspective, and it may in fact give users a better understanding of what they're missing if they're not using the functions API. --- On a completely different topic, one thing I've been wondering is if it would make sense to provide some kind of "interactive editor" for the API features – "tweak the code and see the result here". I know, ProcessWire isn't a JavaScript app, and the API has loads of stuff that wouldn't make any sense to implement in JavaScript, but perhaps as some kind of a virtual box (not sure how one would set that up securely, though) or a limited scope JavaScript mock API with a set of mock data behind it? Just an idea for now.
    1 point
  34. Sorry guys - I was never given site submissions approval and I actually don't have a login for the website backend anymore either so I'm afraid I can't help with this one. Maybe just an oversight by Ryan, but I really don't know.
    1 point
  35. Absolutely this needs to be covered in the official documentation. It's foundational stuff and too important leave to a scattering of forum discussions. I'd hazard to say there are many here who have been working with PW for years and are not 100% clear on this stuff (myself included).
    1 point
  36. Sorry for the confusion @Robin S - it was a failed attempt at humor ? I was trying to make the point that there are way too many options - some are intentionally provided and some are just due to class inheritance etc, but I personally think we should be very careful to document just one default approach for all examples and then properly explain the other options and where they can/need to be different to the chosen default approach.
    1 point
  37. I have used these functions in the past for search excerpts: https://github.com/boyter/php-excerpt Together with this jQuery library for highlighting: http://bartaz.github.io/sandbox.js/jquery.highlight.html You might like to consider maintaining a hidden "index" field in your templates that merges the text content from other fields in a Page::saveReady hook. Then you use this field for searching/excerpting/highlighting.
    1 point
  38. Maybe @adrian knows. Let's get his thoughts.
    1 point
  39. @Robin S and @adrian, a great discussion and follow-up solution(s). This is the type of stuff that makes this Forum so valuable and worth reading on a daily basis.
    1 point
  40. As always, excellent write-up! Clear and concise ?. If I had the money and you had the time and interest, I'd pay you to write many more ProcessWire tutorials ?.
    1 point
  41. The site looks good! I did notice a couple of grammar errors in the docs, but otherwise, it looks good.
    1 point
  42. I landed here from a somewhat related issue I was having. The API now supports strings, objects, ints and arrays as valid. LINK
    1 point
  43. Just a few days before christmas we relaunched our own agency website at schwarzdesign.de using ProcessWire! The old Drupal-based site was getting a bit outdated, we wanted to rebuilt it with fewer, more focused content pages, clean & minimalistic design and better performance for mobile visitors. Note that the site copy is only available in German. After a couple of successful ProcessWire projects such as Engfer Consulting and Joachim Kobuss, we decided to use it for our own site as well, mostly for it's small footprint and developer-focused API. We also have a dedicated ProcessWire page on our new site, check it out here! Modules used ProFields Automatically Link Page Titles TinyPNG Image Compression Color Tracy Debugger Sitemap Duplicator ALIF - Admin Links In Frontend A focus on content We went for a minimalistic approach with a limited set of design elements to highlight our content, which is mostly copy about our services and approach to web design. The two-column layout is built with a single Repeater Matrix section with fields for left and right copy, left and right images and a couple of display options for column width and alignment. Other Repeater Matrix types include a full-width image with some additional links (used on the homepage), teaser sections for current news and projects as well as a list of services. We used dedicated page types (templates) for services, projects and news. This allowed us to use those as taxonomies for our reference projects, and create cross-references to those pages in one go. For this purpose, there's also a dedicated CMS template and pages for all Content-Management-Systems we use, allowing us to categorize our projects and news in regards to the CMS used and show appropriate pages in the recommended content sections. Performance Loading times become ever more important with the rising amount of mobile traffic, both for the bounce rate and for SEO purposes. For client-side performance, we got rid of all external libraries (CSS and JavaScript). All CSS is written in SASS; we use a very stripped down version of Bootstrap 4 that includes only the grid system, the utility classes and a select few of the components. We also avoided the components requiring jQuery, allowing us to get rid of jQuery entirely. The few interactive parts of the site (flyout menus, the theme switch, adding the blur filter for the background image on scroll) are written in simple vanilla JavaScript. Server-side, we use the ProcessWire page cache to minimize server response times, as well as Cache-Control headers and GZIP compression to make sure all assets are as lightweight as possible and cached client-side. One problem we had were the large header images requiring transparency. We ended up combining a couple of approaches to minimize image loading times: SVG assets where possible (for example, all the service pages (Kompetenzen) use SVG for the header images. Responsive images to serve the smallest possible image for each device. PNG compression using the TinyPNG service and the TinyPNG module. This had possibly the highest impact, sometimes reducing the image size by about 80%! Design highlights One of the adornments of the site are the large, variable sized header images. Position and size can be controlled through the backend: We built display settings for size in viewport width or height, vertical and horizontal alignment as well as optional offsets. The header images are fixed to the viewport, so they always stay in the background. The blurred background uses CSS filters, with a fallback to a simple opacity reduction for older browsers. As a gimmick, there is a light and a dark theme for the website, the latter being the default. You can switch between themes using the sun icon in the menu. On the technical sides, both themes have their own stylesheets, compiled using the same SASS source files with different variables. Only the active theme's CSS is directly loaded on the site, the other is included as a preloaded asset. The active theme is saved in the session, so it stays active for the duration of the browser session. For our reference projects (Referenzen), we replaced the background color with the primary color of the project (each project has a color field for that purpose). We determine the luminance of the primary color programmatically to find if the color has higher contrast to black or white, and use the light or dark theme accordingly. Screenshots
    1 point
  44. PageListSelect is different because it doesn't get pages via Pages::find, but rather gets the children of individual pages if they are listable. This is what I came up with: $wire->addHookAfter('Page::listable', function(HookEvent $event) { $page = $event->object; // Page is listable if it is the Users parent or a user page and the current user has a given role if(($page->id === 29 || $page->template == 'user') && $this->wire()->user->hasRole('editor')) { $event->return = true; } }); $wire->addHookBefore('ProcessPageList::find', function(HookEvent $event) { $selector = $event->arguments(0); $page = $event->arguments(1); // Don't check access if getting children of the Users parent and the current user has a given role if($page->id === 29 && $this->wire()->user->hasRole('editor')) { $event->arguments(0, $selector . ', check_access=0'); } });
    1 point
  45. There is a hacky way around this. This comes direct from the ready.php file from one of my sites - in this case it's for the autocomplete inputfield, but maybe something like this would be useful for you also? // hack to overcome this: https://github.com/processwire/processwire-issues/issues/550 $this->addHookBefore('Pages::find', function(HookEvent $event) { $selector = $event->arguments(0); if(is_string($selector) && strpos($selector, 'template=user') !== false && strpos($selector, 'name|first_name|last_name%=') !== false) { $selector .= ', check_access=0'; } $event->arguments(0, $selector); });
    1 point
  46. See this note: Because of this requirement this input type won't be suitable for non-superusers to select users because you don't have the possibility to specify check_access=0.
    1 point
  47. Not sure if that's the best approach ? With page reference fields I think you want to go with a custom selector and add "check_access=0" to the selector.
    1 point
  48. hi donald, the module is not intended to be used on the frontend. though it is not that hard to do it... example home.php <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title><?php echo $page->title; ?></title> <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/handsontable/0.34.5/handsontable.full.min.css" /> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/handsontable/0.34.5/handsontable.full.min.js" /> </head> <body> <h1><?php echo $page->title; ?></h1> <?php if($page->editable()) echo "<p><a href='$page->editURL'>Edit</a></p>"; ?> <?php bd($page->cars); ?> <div id="example"></div> <script type="text/javascript"> var container = document.getElementById('example'); var hot = new Handsontable(container, { data: <?= json_encode($page->cars->data) ?>, rowHeaders: false, colHeaders: <?= json_encode($page->cars->colHeaders) ?>, }); </script> </body> </html> the field config for the backend: $(document).on('afterInit.rht', '.handsontable', function(e, hot) { var colheaders = ['Volvo', 'Audi', 'BMW']; hot.updateSettings({ colHeaders: colheaders, minCols: colheaders.length, maxCols: colheaders.length, maxRows: 1, minRows: 1, rowHeaders: false, }); }); i don't know any technical details of the other module. i built this module to have a quick and easy way to INPUT some table data and be able to copy&paste from excel. for me the benefits of this module compared to the matrix field is the look&feel. it's more compact and more excel-like, so it's easier to grasp for my clients. but the field has some major limitations you have to keep in mind. for example changing inputfield config after some data already has been stored would lead in data destruction. its also not possible to use this data in selectors. and multilang values are not supported. thats no problem as long as you have only have numbers as data because you can translate column headers (see above example).
    1 point
  49. No, doing this would only allow the exact URL segment 'category'. Instead, don't place any restrictions on the segment in the template settings and do your segment validation inside the 'news' template. Rather than rewrite or render anything from a category page you can handle all the output within your 'news' template. Here is an example from a recent project: $limit = 5; $news_selector = "template=news_item, post_date<=today, limit=$limit, sort=sort"; $categories = $pages(1139)->children(); $segment_1 = $sanitizer->pageName($input->urlSegment1, true); // URL segments are already sanitized as page names but not to lowercase if($segment_1) { $current_category = $categories->get("name=$segment_1"); if($current_category) { // the segment is a valid news category $news_selector .= ", news_category=$current_category"; $page_title = "$current_category->title news"; } else { // the segment is invalid so throw 404 throw new Wire404Exception(); } } $news_items = $pages->find($news_selector); $total_pages = ceil($news_items->getTotal() / $limit); The effect of this is that if there is a valid URL segment then only news items from that category are listed, but if there is no URL segment then all news items are listed.
    1 point
  50. Here's how it worked for me in CKEditor (in case you persist on this route - but I would go for Hanna Code as Adrian suggested. As usual, the "culprit" is our friend HTML Purifier (read from here up to and including Ryan's comment here about its pros and cons before deciding whether to implement #5 below!) For iframes, the Extra allowed content seems to have no effect - btw, the correct syntax here is for example, div(*) not div[*] Add 'Iframe' (note the spelling) to your CKEditor Toolbar Leave ACF on No need to switch the field's "Content Type" from "Markup/HTML" to "Unknown" Turn HTML Purifier off (gasp! ) Enjoy your embedded video
    1 point
×
×
  • Create New...