Leaderboard
Popular Content
Showing content with the highest reputation on 04/23/2020 in all areas
-
I use the classLoader in my TrelloWire module, you can look at the source code here. As you can see, this adds the src directory inside the module files to the WireClassLoader as the location to look for classes inside the namespace ProcessWire\TrelloWire. Almost; it doesn't preload the classes, but only on demand. This way, once I instantiate the class ProcessWire\TrelloWire\TrelloWireApi, the WireClassLoader looks for the PHP file for this class inside the src directory (the one registered for that namespace through addNamespace). If it couldn't find it, an error would be thrown. (If you're wondering why I don't use the fully qualified namespace, note the use statement at the top). Two main advantages: Using an autoloader, you can map classes to directories. The exact mapping (how namespaces are resolved to file paths) is defined in the PSR-4 standard. As far as I know, the WireClassLoader loosely complies with that. Composer mostly does the same thing (although a bit more elaborate, with optimizations for production usage etc.). Basically, you have a root directory mapped to a root namespace (in this case ProcessWire\TrelloWire -> src/ directory), and from there resolve sub-namespaces to sub-directories and the class name to a file name (so ProcessWire\TrelloWire\TrelloWireApi -> src/TrelloWireApi.php). The advantage is that you add namespaces wholesale. So you only need to add the mapping for the root namespace, and can then add as many classes and nested namespaces and classes without having to worry about including any class files manually because they will be autoloaded. Because class files are only included on-demand, only the classes you actually need for a request will be loaded. This of course cuts down on processing time, since otherwise you'd usually include all classes at the top for every request. Hope this clears up some of the confusion!5 points
-
This is my very first module, and I'm sure it needs a lot of improvements, so I'd like to get some feedback. I've kept it as simple as possible to fit my basic needs. Adapted from Ryan Cramer's TextformatterVideoEmbed, this TextFormatter module replaces plain YouTube links pasted in a CKEditor field with Paul Irish's blazing fast Lite YouTube Embed script: https://github.com/jacmaes/TextformatterLiteYouTubeEmbed Why? The Lite YouTube Embed script is indeed a lot faster than the standard iframe embed. The difference is pretty spectacular when you need to embed a series of videos. It's also more private as it uses youtube-nocookie.com (so no need for a cookie banner).4 points
-
I would say you can do anything with ProcessWire. You need to have proper knowledge and skills but the guys here really helpful that makes life much easier. Gideon3 points
-
Given that your field is named images, I am guessing it is a multi image field. This means the field can contain more than one image. This depends on how you set up the field (see its settings when editing the field. Assuming this is a multi image field, you code above won't work. Speaking in very general terms, there are two types of fields: Ones that return only a single value and ones that return multiple values. For instance, an email field will return only one value; the@email.tld. For the fields that can return multiple items, think about it this way... Imagine you have a basket. The basket can contain several fruits. If someone asked you to "give me the fruit"? Your natural response (assuming you are willing to give;-)) would be "which one"? This is because there are multiple fruits in the basket. By requesting the fruit, it implies they want not just any fruit but a particular fruit. That is the same thing you are asking in your code above; "Give me the URL" and ProcessWire is responding with which one? There are several images here, which one do you want? Back to the images, you will need to either specify which image's URL you want or have ProcessWire return the URLs of all the images in the collection (the field on that page). The latter means you have to loop through the images field (collection) as well. Some code.. foreach ($entries as $entry) { $images = $entry->name_of_your_image_field;// e.g. $entry->logo // we want all images so we loop through the image field foreach($images as $image) { // just an example echo $image->url; } } Edit You access a field of a page using its (the field's) name. @see my edit above ($entry->logo). If the image field is of type single, you don't need to loop through it. Just echo its content, e.g. echo $entry->logo;. In other words, there is no API variable called images in ProcessWire.3 points
-
Piece of cake with ProcessWire I say ?! Registration with LoginRegister Pro, feedback/rating with comments module and probably I'd think of an admin dashboard or someway to present comments/rating in a nicer way than just going to the video page and look at the fields.3 points
-
Sweet! How about integrating lite-vimeo-embed too? Then the module could be a drop-in replacement for TextformatterVideoEmbed. ?3 points
-
After forgetting the class name of the wonderful AdminPageFieldEditLinks module for what feels like the 100th time I decided I needed to give my failing memory a helping hand... Autocomplete Module Class Name Provides class name autocomplete suggestions for the "Add Module From Directory" and "Add Module From URL" fields at Modules > New. Requires ProcessWire >= v3.0.16. Screencast Installation Install the Autocomplete Module Class Name module. Configuration Add Module From Directory Choose the type of autocomplete suggestions list: "Module class names from directory" or "Custom list of module class names". The latter could be useful if you regularly install some modules and would prefer a shorter list of autocomplete suggestions. The list of class names in the modules directory is generated when the Autocomplete Module Class Name module is installed. It doesn't update automatically (because the retrieval of the class names is quite slow), but you can use the button underneath when you want to retrieve an updated list of class names from the directory. Add Module From URL If you want to see autocomplete suggestions for the "Add Module From URL" field then enter them in the following format: [autocomplete suggestion] > [module ZIP url] Example: RepeaterImages > https://github.com/Toutouwai/RepeaterImages/archive/master.zip Awesomplete options The "fuzzy search" option uses custom filter and item functions for Awesomplete so that the characters you type just have to exist in the autocomplete suggestion item and occur after preceding matches but do not need to be contiguous. Uncheck this option if you prefer the standard Awesomplete matching. Custom settings for Awesomplete can be entered in the "Awesomplete options" field if needed. See the Awesomplete documentation for more information. https://github.com/Toutouwai/AutocompleteModuleClassName https://modules.processwire.com/modules/autocomplete-module-class-name/2 points
-
it works now. Your solution actually worked, there was another problem with the naming. thanks you all2 points
-
Thank you so much for your help! Both for the components I proposed and for the extra components! ? I Try ?2 points
-
My top 3: TracyDebugger TracyDebugger TracyDebugger ? We already have such a thread here:2 points
-
A couple of issues I can see there. You need to set the $event->return instead of returning a value. And if you are hooking before and replacing a method with your own code then you need $event->replace = true. See Ryan's example in the topic I linked to. But in your case a simpler approach could be this (note that this is hooking after because it is modifying the $event->return): $wire->addHookAfter('Page::path', function(HookEvent $event) { $page = $event->object; if($page->rootParent->template != '_site') return; $event->return = str_replace('/' . $page->rootParent->name, '', $event->return); });2 points
-
Thanks, but not necessary. Pretty much all my modules get created because I have a need for them in work that I get paid to do, and it doesn't cost me anything to make them available for others to use too.2 points
-
Breadcrumb Dropdowns Adds dropdown menus of page edit links to the breadcrumbs in Page Edit. The module also adds dropdowns in Edit Template, Edit Field, Edit User, Edit Role, Edit Permission, Edit Language, and when viewing a log file at Setup > Logs. Configuration options Features/details The module adds an additional breadcrumb item at the end for the currently edited page. That's because I think it's more intuitive for the dropdown under each breadcrumb item to show the item's sibling pages rather than the item's child pages. In the dropdown menus the current page and the current page's parents are highlighted in a crimson colour to make it easier to quickly locate them in case you want to edit the next or previous sibling page. Unpublished and hidden pages are indicated in the dropdowns with similar styling to that used in Page List. If the option to include uneditable pages is selected then those pages are indicated by italics with a reduced text opacity and the "not-allowed" cursor is shown on hover. There is a limit of 25 pages per dropdown for performance reasons and to avoid the dropdown becoming unwieldy. If the current user is allowed to add new pages under the parent page an "Add New" link is shown at the bottom of the breadcrumb dropdown. If the currently edited page has children or the user may add children, a caret at the end of the breadcrumbs reveals a dropdown of up to the first 25 children and/or an "Add New" link. Overriding the listed siblings for a page If you want to override the siblings that are listed in the Page Edit dropdowns you can hook the BreadcrumbDropdowns::getSiblings method and change the returned PageArray. For most use cases this won't be necessary. Incompatibilities This module replaces the AdminThemeUikit::renderBreadcrumbs method so will potentially be incompatible with other modules that hook the same method. https://modules.processwire.com/modules/breadcrumb-dropdowns/ https://github.com/Toutouwai/BreadcrumbDropdowns1 point
-
Hello, I got an inquiry with a new project, its a website to show catalogued educational videos. The website frontend will have List of Classes ( Class 5, 6, 7 ) List of Chapters List of Videos to each chapters This is a simple straight forward CMS website, but client also asked to provide below features a full featured registration form ( name, phone, address, etc ) for each user a rating with feedback meesage for each videos Admin should see the list of students registered / who watched which videos such info Admin should see the rating / feedback message of each videos Well, because of these extra features, I got confused, whether its possible to do with ProcessWire or not. Can any one share some info on these ? Such custom requirements can be met by ProcessWire or should I choose a framework like Laravel / CodeIgniter for such work ? thank you1 point
-
--- There might be some changes to this module in the near future! Please see this comment --- I guess we have all been there... We need to store a price to a product. "Ok, easy, let's create a new field for that in the PW backend!" might be the first thought. But then the headache starts... What about TAX? What about NET and GROSS values? And what about rounding problems when not using the correct float or decimal values ( https://processwire.com/talk/topic/7542-development-fieldtypefloat-fieldtypedecimal/ )? Meet RockPrice - a brand new (and not well tested!) module to save you from those headaches and make the UI more compact and reactive (nobody wants to calc tax/net/gross manually!). If you discover any issues or have suggestions for improvement please let me know! ? --- Download: https://github.com/BernhardBaumrock/RockPrice --- RockPrice Price Fieldtype + Inputfield for ProcessWire CMS Settings Usage The field always returns a RockPriceMulti object. This object contains an array of items and the totals vor vat, net and gross (where tax stands for the tax rate in percent and vat for the actual tax value, eg. Euros or Dollars): d($page->price); d($page->price->items->first()); API Saving field value: $page->setAndSave('price', [1000, 20]); $page->setAndSave('price', [ [1000, 20], [3000, 10], ]); Comparisons $p1 = new RockPrice(1000, 20); $p2 = new RockPrice(1000, 10); d($p1->equals($p2)); // false $m1 = new RockPriceMulti([$p1, $p2]); $m2 = new RockPriceMulti([$p1, $p2]); $m3 = new RockPriceMulti([$p2, $p1]); // flipped! d($m1->equals($m2)); // true d($m1->equals($m3)); // false d($m1->equals($m3, true)); // true (ignoring sort order)1 point
-
1 point
-
Set this up for the first time tonight, works really well over here. Just to save someone else some head-scratching, if you do this: Consider adding include=all to your selector to also iterate through unpublished and hidden pages when synchronizing your relationships.. // Get all pages where page_field_a is not empty, including hidden and unpublished pages $pgs = $pages->find("page_field_a.count>0, include=all"); ... Great work on the module @Robin S, coming in very handy ?1 point
-
1 point
-
@Andi – interesting… I'm sure this could be achieved with a hook that gets triggered when iterating pages. Haven't worked with the hook system in a while, but I guess that adding support for addHookBefore('Sitemap::page') would be a decent idea. Unfortunately though, I don't have the time to get to this right now. If you or anyone else is willing to look into implementing this, please feel free to sumit a PR. If that hasn't happened and I find some time in the next week or so, then I'll jump on it. As a last resort, there's always the getAdditionalPages hook that was recently added. It would mean that you exclude your posts from the sitemap and use that hook to add all your posts with the correct paths.1 point
-
If you didnt want to build an admin module you could add functionality to your templates depending on the user role. e.g. Superuser can see who has watched each video on the video's page, and you could provide a page which only exists for the admin that displays a list of videos and users who have watched them etc etc1 point
-
Way better with Processwire, since all you need to handle is content management.1 point
-
In that case what you want is to rewrite the URL. It is a divisive topic :-). Have you considered alternative, e.g. restructuring your site? Anyway, if you are sure you want to rewrite the URL, this is the go to topic: See the section on URLs. This post might also be relevant:1 point
-
Thanks for pointing me in the right direction. I've add a hook to the ready.php file. If someone is interested, below i've added a snippet of what i'm using: wire()->addHookAfter('Pages::saveReady', function(HookEvent $event) { $page = $event->arguments(0); foreach ($page->body_extended as $item) { // $body_extended is the name of the matrix field if ($item->type == 'text') { // Looking for a 'text' matrix field $seo_description = substr(strip_tags($item->body), 0, 255); // Find the body text and strip/trim the html tags break; } } $page->seo_description = $seo_description; // Save the body inside the seo_description field on the page });1 point
-
@bedak might be referring to images in CKEditor fields, which would all probably benefit from being lazy loaded. By the way, it looks like we developers should not be using the "loading" attribute on iframes until it's part of the spec. Yes, Chrome has implemented it, but they went ahead as usual without much consideration for cross-browser interoperability ("innovation first, standards later" seems like their M.O., even if that's caused problems a few times before).1 point
-
Thanks guys. I'll see what I can do this weekend, if I finally manage to have some free time. PS: although I built the following page before this module, it does use the lite-youtube-embed script, so you can check how it looks and how fast the page loads with 14 videos: https://www.spainculture.us/digital-projects/14-days-14-artists/1 point
-
I made a fork because i needed some changes for my use - maybe it can be useful. https://github.com/dauni/TextformatterSrcset/releases/tag/1.0.61 point
-
1 point
-
It always depends on what you want to do with the system. If you only want to create single pages with text and a blog, then Wordpress might be the right choice. However, if you want to create customized pages with specific functions, tailored to a customer or a project, Wordpress gets very complicated. This is where Processwire can make the most of its advantages: - easily extendable - the edit surfaces are almost perfectly adapted to the pages - high-level flexibility But to use Processwire, you need to know HTML and PHP. But if you want to use Wordpress not only with ready-made themes and modules, you need the same knowledge. In my opinion Processwire is even easier.1 point
-
@Robin S ah !.. Makes sense! :D Thanks a lot for such a quick reply! Seems perfect. I'll look into it! Tak care :) All the best, Jonatan.1 point
-
@jonatan, what you're describing doesn't relate to the Connect Page Fields module - this module doesn't get involved with whatever inputfield you have chosen to select pages with. Maybe take a look at the Inputfield Selectize module - it shows an example with thumbnails in the readme.1 point
-
Hi @flydev ?? It would be cool to be able to backup the site and files because of the nice zip-functionality and installer in Duplicator, without backing up the database. I was on a shared Linux host. I guess the timeout limit was set too low. Anyway now I am on a much better host (Linode).1 point
-
I am not a web developer pro, but I understand that a (piece of) code or a (programming) concept can be "beautiful". If you make yourself familiar with Processwire, you will find such very often.1 point
-
@bernhard Oh so true! Pdf's can look different between browser views and Acrobat Reader too.1 point
-
Exactly what @flydev ?? said, but for 5.) you alternatively may use core image fields with the lately added functionality of adding custom fields to them. So it depends on how you want to structure that part. And additionally, also if you haven't asked for it yet, but maybe the question arises later: 9) Search = https://modules.processwire.com/modules/search-engine/ 10) Privacy & Cookies = https://modules.processwire.com/modules/privacy-wire/ ?1 point
-
Thx for sharing your experience @psy ? mPdf is unfortunately not really a pleasure to work with ? It feels a bit like designing websites 20 years ago with lots of custom table layouts, custom styles, paddings, margins etc... But as you said: I also got there almost everytime and I didn't find a better solution yet. Writing your styles as LESS can be helpful because you can create simple custom classes for any element and to the complex styling in CSS. Using LESS ensures that your style stays easy to maintain because you can use class inheritance and variables. RockPdf plays really well together with RockLESS. I added an example to the readme: Combine RockPdf and RockLESS $pdf = $modules->get('RockPdf'); $less = $modules->get('RockLESS'); $style = " @padding-s: 10pt; .border { border: 1pt solid #afafaf; } .hello { .border; color: blue; padding-top: @padding-s; } .world { .border; color: red; padding-top: @padding-s * 2; } "; $css = "\n".$less->parse($style); $pdf->write("<style>$css</style>"); $pdf->write("<div class='hello'>hello</div>"); $pdf->write("<div class='world'>world</div>"); d($pdf->save()); This is the result of $pdf->html() <style> .border { border: 1pt solid #afafaf; } .hello { border: 1pt solid #afafaf; color: blue; padding-top: 10pt; } .world { border: 1pt solid #afafaf; color: red; padding-top: 20pt; } </style> <div class='hello'>hello</div> <div class='world'>world</div>1 point
-
1 point
-
I can only thank @bernhard again for this module and for the support he provided, for example in finding a solution for option fields. RockFinder2 can not only be used to load masses of pages faster, it can also be used at field level. For example, I used it to load about 40 to 60 fields per repeater matrix type, which are also further nested in FieldsetPages (for design settings) in one query. This amount of fields caused 700 or more single SQL queries to be executed and up to 140 PW-Page objects to be loaded into RAM. This caused a significant loading delay. By using RockFinder2 the SQL queries could be reduced to 200 on average. About 60 page objects less are loaded in RAM, the CPU is also happy and the loading time for pages without cache was also reduced on average to 700 ms to 1 second. Good job Bernhard! ?1 point
-
@netcarver Field is showing "PLACEHOLDER" when empty, is that intentional or is there a way to configure the placeholder value? Also a default value option would be very, very neat. I'm running this on an event planner that has events almost always starting around the same time of day. Would that be hard to implement? Running version 0.2.2, field is inside a repeater in this case. Thanks a bunch!1 point
-
v0.0.3 adds user templates to restore complicated recurring prices (I was too lazy to always input the same complicated numbers for my internet invoice ? ) User templates You can save custom user templates to easily restore complicated recurring pricings:1 point
-
I've put huge amounts of work into that module in the last few days. I had to take two steps back to take the next step forward: It turned out, that I needed a more robust and flexible setup when dealing with date ranges. And what I did is - thinking about it now - quite obvious: A RockDaterange now consists of two RockDatetimes. I've put a lot of effort into developing the RockDatetime module. It is already available on Github and has lots of examples and docs in the readme: https://github.com/BernhardBaumrock/RockDatetime Highlights: // calculating FROM/TO for RockDaterange case 'hour': $from = new RockDatetime("{$obj->date} {$obj->time}:00:00"); if($isTo) $to = $from; else $to = $from->copy()->move("+1 hour"); break; // check if FROM starts at 00:00 on that day if($this->from->equals($this->from->firstOfDay()) ... // formatting $d = new RockDatetime("25.02.2020 14:00"); echo $d->format(); // 25.02.2020 14:00 echo $d->format("%A, %d.%m.%y (%H:%M Uhr)"); // Dienstag, 25.02.20 (14:00 Uhr) echo $d->format(['time' => "%H|%M|%S"]); // 25.02.2020 14|30|00 I've also totally rebuilt the date parsing engine! Finding pages using the API $tpl = "template=event"; $pages->find("$tpl,range=2020"); // find all events in 2020 $pages->find("$tpl,range=2020-02"); // find all events in Feb 2020 $pages->find("$tpl,range=2020-02-26"); // find all events on 26. Feb 2020 // other possible selectors $pages->find("$tpl,range=2020-02-10 - 2020-02-20"); $pages->find("$tpl,range=2020-02-10 7:30 - 17:30"); $pages->find("$tpl,range=2020-02-10 7 - 9"); $pages->find("$tpl,range=2020-02-10 12:00 - 2020-02-20 18:00"); // find events in Feb 2020 sorted by range duration $pages->find("$tpl,range=2020-02, sort=-range.duration"); Creating pages using the API $p = new Page(); $p->setAndSave("range", "2020"); // from = 2020-01-01 00:00:00 // _to = 2020-12-31 23:59:59 // to = 2021-01-01 00:00:00 $p->setAndSave("range", "2020-12-24 16:00 - 18:00"); // from = 2020-12-24 16:00:00 // _to = 2020-12-24 17:59:59 // to = 2020-12-24 18:00:00 Formatting in action: // left column echo $range->format(['date' => "%A, %d.%m.%Y", 'time' => '']); // right column echo $range->format(['date' => "%a, %d.%m.%Y"]); Note that the last date does NOT show "07.03.2020 09:00 - 07.03.2020 12:00" - since the event ends on the same day as it starts we don't show that date again. RockDaterange will take care of all those tedious details!1 point
-
I think providing an option for this would indeed be sensible ? While testing the module I found it quite simple to regenerate the template stubs content on the local environment – this way there's no real need to sync stub files, and if you've got a full environment locally you can do this just by changing the prefix for something else and then restoring the old value. I'm currently running a slightly modified version of the module with a regenerate option in module config; seemed like a good idea at first, but not sure anymore. Might send a PR and let Robin decide ? Also, just in case there are other VSCode users here, a couple of pointers for getting things up and running: If you've excluded the /site/assets/cache/ directory (I had), you'll have to change the exclude setting. Sadly VSCode doesn't support full glob syntax, but ignoring everything except certain subdirectories is still doable with a hacky workaround (more discussion here) : "files.exclude": { "**/site/assets/cache/{[^A],?[^u],??[^t],???[^o],????[^T],?????[^e],??????[^m],???????[^p],????????[^l]}*": true, }, Suggested syntax for var (/* @var tpl_basic_page $page */) won't work, since VSCode expects valid PHPDoc syntax. Use /** @var tpl_basic_page $page */ instead. I'm using the PHP Intelephense plugin (bmewburn.vscode-intelephense-client), and after resolving aforementioned inconveniences things are working just fine ? Edit: sent a PR for the regenerate stubs option (https://github.com/Toutouwai/AutoTemplateStubs/pull/4).1 point
-
1 point
-
@Robin S really really nice would be, if we can load a custom list with names AND optionally individual download URLs, so that we also can include modules that are not in the official directory. Priority: If a module is selected that has a individual download URL, paste it into the "Add Module From URL" field. What do you think?1 point
-
1 point