Jump to content

teppo

PW-Moderators
  • Posts

    3,259
  • Joined

  • Last visited

  • Days Won

    112

Everything posted by teppo

  1. Thanks @flydev ?? for identifying the error, and sorry @Roych for the inconvenience. This is now fixed in version 1.7.2 of Login History, display date format should no longer intervene with date difference calculations ?
  2. Out of the box (without third party modules) your best option is the Page Table ("ProFields: Page Table") fieldtype. It's included with the core package, but might be uninstalled by default. The user interface for Page Table is a bit different in that you'll edit content in modal windows instead of "in context", but I'd suggest that you give it a try. You can save your content items under current page, or a different location in your page tree. If third party modules are an option, the Repeater Matrix module is worth checking out. It's commercial (paid) module, but if that's not an issue, it's really quite amazing. Other (non-commercial) module options include PageTableNext and PageTableExtended.
  3. wire('pages')->get('template=template_custom_orders')->delete() uses $pages->get(), which means that it will include pages that are either in trash, or unpublished/hidden. Meanwhile this part... $tcos = pages('template=template_custom_order'); foreach ($tcos as $tco) : $tco->delete(); endforeach; ... will only find non-trashed public pages. One thing to check is that it matches every possible page: $tcos = pages('template=template_custom_order, include=all'); foreach ($tcos as $tco) : $tco->delete(); endforeach; BUT that being said, there's potentially an even easier method: wire('pages')->get('template=template_custom_orders')->delete(true); If you pass "true" to the delete method, it will automatically (attempt to) remove child pages.
  4. Hey @Zeka! I assume you're referring to "method aliases" from MethodPropsTrait? If so, this is a feature that, to be honest, I've not had much use for myself. As far as I can remember, the original intention was two-fold: 1) Whether to make code cleaner or to mitigate issues resulting from partial rewrites, one can create an alias or "virtual method" that calls another local method behind the scenes. Say, if a controller class had method called "words", but later it was decided that it should be "terms" instead (or for some reason front-end code requires it to be that) yet changing it now could potentially cause other issues, one could handle this via an alias: class DictonaryController extends \Wireframe\Controller { protected $method_aliases = [ 'terms' => [ 'callable' => ['self', 'words'], 'params' => [], ], ]; public function words(): array { return $this->pages->findRaw('parent=' . $this->page->id . ', template=Word', [ 'name', 'title', 'dictionary_category.title', ], [ 'objects' => true, 'entities' => true, ]); } } Here I'm defining the $method_aliases property directly on class declaration, but in some cases it could make more sense to define individual aliases via the API: $this->setAlias($alias, $callable, $params). 2) Another use case is referring to a method defined somewhere else — another controller, utility class, third party library, etc. Essentially this makes it easy to inject new methods or properties into classes implementing the MethodPropsTrait (such as controllers and components): class DictonaryController extends \Wireframe\Controller { public function init() { $this->setAlias('terms', '\Wireframe\Lib\Utils::getWords', ['page' => $this->page]); } } You can do the same with ProcessWire hooks or just have a method that calls another method, so this is largely a matter of preference ? --- As I mentioned above, I've not had much use for this feature myself. It's been there since the very beginning, and it's a concept that seemed potentially useful (not to mention fun) while I was working on the initial implementation of Wireframe, but real world use cases have been few and far between. If you can think of other use cases, let me know ?
  5. What the error you posted says is basically that your code doesn't found a page matching the path you've provided. This is why it returns a NullPage object, which is kind of like saying "sorry, didn't find anything, here's a placeholder object for you instead". And since you can't remove a NullPage, that explains the error you saw. Now, what you're describing here sounds like some kind of a bug, though it's a hard to pinpoint exactly without access to the code, site, and/or database. Couple of suggestions: When this happens, I would first check if logging out and then in again removes that "page" from the menu. Admin menu is cached independently, so this could be the reason. Though I'm not sure why said cache wouldn't reset automatically. If that doesn't help and there is indeed an actual page there, it would be interesting to know what kind of data it has in the "pages" table in the database. Another reason why this might happen would be if a page is somehow corrupted. A typical signal of that would be that it exists in the database, but has a strange value in the "status" column. If you post your current code, I would be happy to take a closer look (at some point) in case there's some sort of issue there ?
  6. The problem here is that $pages->get() can return either a Page or a NullPage. NullPage is a null object that (in terms of API usage) behaves like a Page, but doesn't have any content, and doesn't actually match any page on the system. Thus you can't delete a NullPage. NullPage doesn't have an ID, so here's one way you can solve this, checking for an object with an ID: public function ___uninstall() { // ... $dashboard = wire('pages')->get('/admin/kiosk_dashboard/'); if($dashboard->id){ $dashboard->delete(); } // ... } Edit: just for the record, admin pages can be renamed or moved, so keep in mind that at least technically your uninstall routine may leave "orphaned" pages behind. In case your dashboard page uses your Process module as it's process, here's what you could do instead of relying on the path/name always being /admin/kiosk_dashboard/: public function ___uninstall() { // ... $module_id = wire('modules')->getModuleID($this); $dashboard = wire('pages')->get('template=admin, process=' . $module_id); if($dashboard->id){ $dashboard->delete(); } // ... }
  7. HTTP/2 makes things more efficient, but it doesn't completely eliminate the overhead of downloading multiple files. As long as those files are the kind that "must always be loaded" (and "must always be loaded together"), I'd still say that the best practice is to merge and offer only one file to download. Cases where merging makes little sense or might even have negative effect include scripts/styles that are only needed some of the time (e.g. big JS app related to single page/template, which the visitor may never encounter), JS/CSS that is intentionally split so that it gets loaded before other content (e.g. styles for the above the fold content), bundles where some parts are regularly updated while others remain as-is for long periods of time (i.e. having to invalidate cache for entire bundle unnecessarily often), etc. If merging has to happen real-time, server resource usage / resulting delay would further diminish the benefits. So merged scripts/styles should preferably be served directly from disk, as static files. Just my two cents. Not exactly a simple topic ?
  8. Looking at your code, and specifically your ___uninstall() method, I can spot at least a few potential issues. $custom_order_pages = wire('pages')->find('template=template_custom_orders|template_custom_order')->count(); // if ($custom_order_pages > 0) // throw new WireException("There are pages using custom-order-templates. Remove those first before uninstall"); foreach($custom_order_pages as $custom_order_page){ $custom_order_page->delete(); } The foreach loop above doesn't make any sense. You're essentially trying to iterate over the count() value, which is an integer. If you remove the "->count()" part, it's more likely to work — unless your pages are hidden/unpublished, in which case you should also add "include=all" to the selector string. if($fields->get('custom_order_id')) : foreach ($fields->get('custom_order_id')->getFieldgroups() as $fieldgroup) { $fieldgroups->delete($fieldgroup); } endif; if($fields->get('custom_order_products')) : foreach ($fields->get('custom_order_products')->getFieldgroups() as $fieldgroup) { $fieldgroups->delete($fieldgroup); } endif; if($fields->get('custom_order_customer_name')) : foreach ($fields->get('custom_order_customer_name')->getFieldgroups() as $fieldgroup) { $fieldgroups->delete($fieldgroup); } endif; if($fields->get('custom_order_customer_address')) : foreach ($fields->get('custom_order_customer_address')->getFieldgroups() as $fieldgroup) { $fieldgroups->delete($fieldgroup); } endif; if($fields->get('custom_order_customer_emailaddress')) : foreach ($fields->get('custom_order_customer_emailaddress')->getFieldgroups() as $fieldgroup) { $fieldgroups->delete($fieldgroup); } endif; The part above looks fine, but keep in mind that none of these fields were added to the "fieldgroup_custom_orders" fieldgroup, so that won't get removed. You should probably add something like this right after the lines above: $fieldgroups->delete($fieldgroups->get('fieldgroup_custom_orders')); Also this is likely unrelated to your bigger issue(s) here, but note that this part doesn't seem quite right: $template_custom_orders->childrenTemplates = array($template_custom_order->id); There's no "childrenTemplates" property on Templates. What you probably meant was childTemplates. Finally, your ___install() method is rather error prone. In case any of the fields already exist, you will run into problems. For an example, look at these lines here: if(!$fields->get('custom_order_id')) : $custom_order_id = new Field(); // int or text $custom_order_id->type = $this->modules->get("FieldtypeInteger"); $custom_order_id->title = 'Custom Order ID'; $custom_order_id->name = wire('sanitizer')->pageName($custom_order_id->title, true); $custom_order_id->label = 'Order ID'; $custom_order_id->tags = 'kiosk'; $custom_order_id->save(); endif; What happens here is that a) if custom_order_id field is not found, it will be created and stored in $custom_order_id, but b) if it doesn't exist, then it won't be created and it also won't be stored in $custom_order_id. Basically if install/uninstall has been only partially completed, even once, then you're likely going to run into issues. Here's one approach that should work a bit more reliably: $custom_order_id = $fields->get('custom_order_id'); if(!$custom_order_id) : $custom_order_id = new Field(); // int or text $custom_order_id->type = $this->modules->get("FieldtypeInteger"); $custom_order_id->title = 'Custom Order ID'; $custom_order_id->name = wire('sanitizer')->pageName($custom_order_id->title, true); $custom_order_id->label = 'Order ID'; $custom_order_id->tags = 'kiosk'; $custom_order_id->save(); endif; It's quite likely that this error is linked to the issue I mentioned above about your install/uninstall method being error prone: if the process has failed even once, this part will not work as expected: if(!$fieldgroups->get('fieldgroup_custom_orders')) : $fieldgroup_custom_orders = new Fieldgroup(); $fieldgroup_custom_orders->name = 'fieldgroup_custom_orders'; $fieldgroup_custom_orders->add($this->fields->get('title')); $fieldgroup_custom_orders->save(); $this->message('creating fieldgroup fieldgroup_custom_orders'); endif; This — and every other code snippet that uses similar approach — should be replaced with something like this instead: $fieldgroup_custom_orders = $fieldgroups->get('fieldgroup_custom_orders'); if(!$fieldgroup_custom_orders) : $fieldgroup_custom_orders = new Fieldgroup(); $fieldgroup_custom_orders->name = 'fieldgroup_custom_orders'; $fieldgroup_custom_orders->add($this->fields->get('title')); $fieldgroup_custom_orders->save(); $this->message('creating fieldgroup fieldgroup_custom_orders'); endif; If your module needs to create templates via the API and add fields to said templates, you do need fieldgroups. There's no way around that.
  9. You've stumbled upon a concept that is, admittedly, a little obscure. The Fieldgroup class comments explain what Fieldgroups are all about, and it boils down to this: Fieldgroups are something that most users don't need to concern themselves with, but technically there's always a fieldgroup behind a template — fields don't belong directly to template, but rather to a fieldgroup, which in turn may be used by one or more templates. Multiple templates using one fieldgroup is, though, pretty rare — I don't think I've ever had that need myself ? All the examples I've seen so far have created a Fieldgroup and then applied it to a Template. If there's a way to create template with fields without creating a fieldgroup to hold said fields, I'm not aware of it (or can't remember it right now — to be honest creating templates via API is not something I do often). No. RockMigrations can make things easier and provide you with many useful tools, but it's not required by any means. If you just need to create a few templates and fields in a module, I personally feel that it's probably overkill to add a dependency to a third party module for that task alone. (Though it could be quite helpful in the future in case you also want to keep those templates/fields in sync with new versions of your module.) I would recommend opening a request for (additional) documentation at https://github.com/processwire/processwire-requests. In my opinion you have a valid point when it comes to fieldgroups — creating templates with fields (and fieldgroups) via API could be more clearly documented. As for "many other things", I don't know what those things would be, but if you can think of some then by all means open a request for those as well. Based on your latest message it seems that you've already solved this — nice! ?
  10. Thanks for reporting the issue, @ngrmm. This should be fixed in SE 0.35.1. I wasn't able to reproduce this issue myself, so please let me know if the problem still persists and I'll be happy to take a closer look ?
  11. This is not particularly helpful, I'm afraid, but if this is a constant / easily reproducible thing, I would start debugging this by checking what page these errors apply to — i.e. what's the "this page" in that particular case? Is it current page being edited, or perhaps a Repeater page? (Might have to edito ProcessPageEdit.module to add Page ID to that error. Or install Tracy.) There was only one issue mentioning this specific error (https://github.com/processwire/processwire-issues/issues/736), but that seems to apply to a rather specific situation with front-end editing and Repeaters. Not sure if it has anything to do with your issue. Of course it would also be helpful to rule out any third party modules that might be causing this. And/or try to reproduce this on a blank installation ? If that's the real PW version, I would recommend updating. I wouldn't be surprised if there were at least some quirks in this version, not to mention that it might not be 100% compatible with PHP 8.
  12. As a security feature ProcessWire's .htaccess file blocks access to any PHP files in assets directory: https://github.com/processwire/processwire/blob/master/htaccess.txt#L383:L384. And there's also a separate (fallback) .htaccess file in /site/ or /site/assets/, which does the same. If you want to provide direct access to a .php file, you'll have to... poke a hole in these rules on your own site (you could do that by creating a .htaccess file that you put on a specific folder, in which you specifically allow access to the file you know to be safe), or route the request via ProcessWire, or put it into a directory that is not protected in this way (such as root path).
  13. This module is an optional (and still somewhat experimental) add-on for SearchEngine. It adds support for indexing file contents, replacing earlier SearchEngine PDF indexer module. Features SearchEngine by itself will only store the name, description, tags, and custom field values for file/image fields. This module, on the other hand, attempts to extract human-readable text from the file itself. As for file types, at least in theory this module supports any filetype that can be reasonably converted to text. It has built-in support (mostly via third party libraries) for... office documents (.doc, .docx, .rtf, .odf), pdf documents (.pdf), spreadsheets (.xls, .xlsx, .ods, .csv) and plain text (.txt). The module also ships with a FileIndexer base class and exposes the SearchEngineFileIndexer::addFileIndexer() method for introducing indexers for file types that are not yet supported. Links GitHub: https://github.com/teppokoivula/SearchEngineFileIndexer Composer: composer require teppokoivula/search-engine-file-indexer Modules directory: https://processwire.com/modules/search-engine-file-indexer/ Getting started install and configure SearchEngine (version 0.34.0 or later), install SearchEngine File Indexer, install third party dependencies — if you installed SearchEngineFileIndexer via Composer you should already have these available, otherwise you'll need to run "composer install" in the SearchEngineFileIndexer module directory, choose which file indexers you'd like to enable. The rest should happen automagically behind the scenes. Additional notes The important thing to note here is that we're going to rely on third party libraries to handle parsing (most) files, and things can still go wrong, so please consider this a beta release. It did work in my early tests, but there's little guarantee that it will work in real life use cases. Just to be safe it is recommended to back up your site before installing and enabling this module. Another thing to keep in mind is that indexing files can be resource intensive and take plenty of time. As such, this module provides some settings for limiting files by size etc. Regardless, this is something that likely needs further consideration in the future; some future version of this module, or an additional add-on module, may e.g. add support for indexing pages/files "lazily" in the background.
  14. Quick heads-up: As of version 0.35.0 SearchEngine supports indexing file/image custom fields. In order to avoid surprises, I ended up adding these as separately selectable indexed fields. For an example: in order to have custom field "author_email" for image field "photo" indexed, you'll have to select "photo.author_email" from the "indexed fields" list in module config. There's a "file_field.*" setting available as well, in case you want to index all existing custom fields for a specific file field. Note that description and tags also need to be specifically selected. In earlier versions description text was always indexed, but now if you select the file field name and nothing more, only file name(s) (and content, if you have a suitable file indexing module installed and enabled) are indexed. -- In order to index file/image custom fields I had to refactor parts of the Indexer class. I hope I didn't break too many hooks, but there's a possibility that something goes wrong. Please test carefully, and let me know if you run into any issues!
  15. The Twig renderer for Wireframe has been around a while already, it just didn't have a support forum thread of its own, so here we go. This optional add-on module lets one author layouts, views, partials, and component views using Twig instead of PHP. By design you can have view files that are either Twig or PHP — with this module enabled Wireframe will initially look for a .twig file, but if that doesn't exist, it'll fall back to a regular .php file instead. GitHub repository: https://github.com/wireframe-framework/WireframeRendererTwig Composer installation: composer require wireframe-framework/wireframe-twig-renderer Here's a small sample of what Twig looks like: {% if page.numChildren(true) %} <ul class="menu"> {% for child in page.children %} <li> <a href="{{ child.url }}"> {{ child.title }} </a> </li> {% endfor %} </ul> {% endif %} You can read more about Twig from https://twig.symfony.com/doc/. Twig syntax in specific is covered in Twig for Template Designers. For more details about Wireframe renderers and how they are enabled and used, check out https://wireframe-framework.com/docs/view/renderers/.
  16. Cross-posting in case any Wireframe user wants to give Latte a try: there's a renderer for it now. Somewhat experimental, since I have a rather miniscule understanding of Latte myself ? Slightly annoying marketing shenanigans aside (I didn't know how to do a single thing in Latte without reading the docs, "Latte is the only system with an effective defense, thanks to context-sensitive escaping" is a silly thing to claim, etc.) Latte does look quite nice. I dig the n:attributes in particular, they remind me a lot of the AngularJS (v1) syntax. Apart from that, Latte seems largely the same as other engines/languages I've used (e.g. Twig, Blade, and Dust). Admittedly I've just scratched the surface, so there's likely a lot more there ? I'm not sure yet whether it's a good thing or not that Latte syntax is so close to plain PHP, just with auto-escaping enabled and <?php ?> replaced with curly brackets. Among other things a) the PHP syntax isn't necessarily the easiest to grasp or nicest to look at, especially for non-developers (though this is admittedly highly opinionated), and b) there's a slight fear in the back of my head that this actually makes it extra tempting for developers to put unnecessarily complex code within their views. So far among the templating languages I've used Blade has been my personal favourite. It's easy to grasp, familiar to PHP users but also for everyone who's ever used another templating language (like Twig), has some very handy shortcuts available (particularly when it comes to loops), the syntax looks nice and clean (in my opinion), and components in particular are just brilliant in terms of both implementation and use. But enough advertising ?
  17. Following recent discussion about the Latte templating language, I figured I'd give it a try too and put together a Latte renderer for Wireframe: GitHub repository at https://github.com/wireframe-framework/WireframeRendererLatte Composer installation: composer require wireframe-framework/wireframe-renderer-latte In case anyone wants to try this, it would be interesting to hear your thoughts. I'm honestly not sure if I'll be using it much myself, and I built the module without any real Latte experience under my belt, so it's possible that it does things in surprising ways. Let me know if you run into any issues ? Syntax wise, Latte doesn't differ much from regular PHP templates — you just write your PHP code within {curly brackets}, and it gets automatically escaped (with what they call context-aware escaping). They have this thing called n:attributes though, which is actually quite nice shortcut, especially if you happen to dislike if..else and foreach: <ul n:if="$page->numChildren(true)" class="menu"> <li n:foreach="$page->children as $child"> <a n:tag-if="!$child->hide_from_menu" href="{$child->url}"> {$item->title} </a> </li> </ul> You can read more about Latte from https://latte.nette.org/en/. For more details about Wireframe renderers and how they are enabled and used, check out https://wireframe-framework.com/docs/view/renderers/.
  18. You know what they say about opinions ? Seriously though, I get your point, and I'm a big fan of keeping code (or rather unnecessarily complex logic) out of the view layer myself. That being said, I don't mind a few foreach and if/else blocks here and there, as long as it doesn't get out of hand. Looking at my example above, that first "if" seems to be pointless; for a simple use case like this, here's all we really need: <?php foreach ($footer_scripts as $script): ?> <script src="<?= $buster->url($config->urls->resources . $script) ?>"></script> <?php endforeach; ?> That's three lines. There's also no cache busting required here, since we're using $buster (and there are also non-commercial alternatives, like Pete's Minify module or AIOM) ? This is absolutely true. FilenameArray is a rather limited/limiting tool, best suited for relatively simple use cases. In the example above I used that because it was enough for that particular use case. And, to be honest, it's been enough for most use cases for me — but if something more nuanced is needed, then another data type (or another approach altogether) is likely going to be a better choice. From my point of view the first one here is not a big issue (I don't usually have that many scripts, so this can be handled with a couple of if-else blocks at tops, or a variation of the technique mentioned above, or Wireframe's placeholders) while other two I prefer to handle via build tools. This is not to say that these are not real concerns, mind you — just that they are (mostly) non-issues for me in my workflow ?‍♂️? Anywho, it'll be interesting to check out RockFrontend once it's available. It sounds like an interesting tool ?
  19. Have to agree with this one — it would be nice if we had a standard approach for this. Having built some plugins for WordPress recently, I must say that it's nice to have a "standard" way to inject scripts/styles. And of course that applies to site development as well ? $config->scripts and $config->styles are currently the closest equivalent to wp_enqueue_script/wp_enqueue_style we have, and some folks do indeed use them for their front-ends. But this is not particularly "well supported", there's nothing like the "deps" array from WordPress, etc. Additionally there's one pretty big issue: some modules don't check for e.g. admin context before pushing stuff to said config arrays, and that can easily lead to admin stuff "leaking" into the front-end. This is the biggest reason why I don't rely on these (on the front-end) myself ? If this was to be implemented in the core (not saying that it should, just thinking out loud), it might require a whole new concept — something like wireEnqueueScript($script, $deps). And, of course, we'd need to accept that it depends on the site whether this would work or not. To be fair, it's really the same for WordPress: unless theme calls wp_head() and wp_footer(), enqueue functions won't do much. So even there it's up to the theme to make sure that they work. Site-specific things can of course be cooked up already. Or approaches specific to individual output modules/frameworks, like the approach that Bernhard mentioned above. -- Just for reference, here's what I've done on some sites — probably not a big surprise that I'm using Wireframe here, and also running things through ProCacheBuster: // site/templates/wireframe.php echo $wireframe->render([ ... 'footer_scripts' => new FilenameArray(), ... ]); And then in layout file: // site/templates/layouts/default.php <?php if ($footer_scripts->count()): ?> <?php foreach ($footer_scripts as $footer_script): ?> <script src="<?= $buster->url($config->urls->resources . $footer_script) ?>"></script> <?php endforeach; ?> <?php endif; ?> </body> </html> This way I can push scripts to $view->footer_scripts from anywhere within the site (usually from Controller classes or individual views), and those get injected to the site's (global) footer.
  20. Another example of creating fields/templates during module install: https://github.com/apeisa/Discussions/blob/master/Discussions.module#L280. That code is 10+ years old and a bit verbose, but that's exactly why it's (in my opinion) a good example. No abstraction layers, no potentially confusing shortcuts, etc. ?
  21. This is why I always prefer the inline mode for CKEditor: very little is done until needed, which speeds things up nicely, yet setting up a new RTE field (when it is needed) takes maybe a few hundred milliseconds (assuming scripts and/or styles need to be loaded, otherwise it's nearly instantaneous). No matter how you do it, adding elements to DOM tends to slow things down. The more you add, slower things get. That is why Ajax loading is great for things that are needed rarely, while things that are needed most of the time can and should be loaded right away ?
  22. Article looks great, but their licensing model is indeed problematic. Folks at Bolt likely got a custom license (or perhaps paid OEM license) to use it, but on what terms is hard to say — I couldn't find specifics about their licensing terms. Only thing they do say is that it's available for use "in Bolt itself", which is a bit vague. It's up to Ryan whether he finds this interesting enough to contact Imperavi and query about license ? Either way, I wouldn't count CKEditor 5 out of the race quite yet. To me personally it looks UI/UX wise like a solid upgrade over CKEditor 4. I do remember that it seemed potentially "too different", and there were some relatively basic features (which I can't for the life of me remember anymore) from v4 that the devs originally said would be very difficult or nearly impossible to implement in v5, but that was a long time ago so perhaps things have changed. First of all, CKEditor 4 being EOL'd in 2023 is a huge reason to move on. There's no guarantee of updates after the EOL date, which includes potential security updates. ProcessWire is relatively safe since most of the time CKEditor is used by trusted users, but there are cases where that isn't necessarily true. And even if it was, there could still be vulnerabilities that third parties can abuse. In my opinion it's painfully obvious that we must drop CKEditor 4 support from the core at some point in the future. If some prefer to keep using EOL'd software (which I would personally recommend against), there's always the possibility of stripping it from the core and converting into a separate, possibly community-supported module. For me personally CKEditor 5 seems like a logical next step, but admittedly I've not used it enough to know if it's really going to be feasible, let alone how much work it will require. It's a good idea to check out what else there is, but CKEditor has quite a few things going for it as well: plenty of features, solid UI/UX, longevity of the project, active community, being open source with no costs or limiting licensing rules, etc. As for ease of use, I absolutely agree that this is vital. And in this regard CKEditor 5 feels like a big step up — if anything it feels less confusing and more streamlined than earlier versions. I would not expect my/our clients to have any trouble with it. Give it a try and see for yourself, and do keep in mind that CKEditor 5 is configurable: features you don't need can be disabled ? Just my two cents. 100%.
  23. No worries, this is always an interesting topic to discuss, as off-topic as it may be. My answer will be a bit lengthy, so I'll wrap it in a spoiler tag (feels overkill to split this into new topic) ?
  24. This module has been superseded by SearchEngineFileIndexer and there will be no further development for it. --- This module is an optional — and experimental — add-on for SearchEngine. It adds support for indexing PDF file contents. While SearchEngine is technically able to index file fields and contained Pagefile(s), it will natively only store the name and description of each file (and hopefully soon custom field values as well). This module hooks into Pagefile indexing and, if said Pagefile looks like a valid PDF document, attempts to extract human-readable text from the file itself. Getting started is straightforward: install and configure SearchEngine, install SearchEngine PDF Indexer, and choose which PDF parser library you'd like to use. The rest should happen automagically behind the scenes. GitHub: https://github.com/teppokoivula/SearchEnginePdfIndexer Composer: composer require teppokoivula/search-engine-pdf-indexer --- Now, as you may or may not know, PDF files are notoriously difficult to process programmatically. For this reason a) we're going to rely on third party libraries to handle parsing them, and b) things can still go wrong, so please consider this module an early beta release. It did work in my early tests, but there's little guarantee that it will work in real life use cases, and as such I'd recommend backing up your site before installing/enabling this module ? Also: while this module can be installed via the admin or by cloning/downloading module from the GitHub repository, please note that you need to run composer install in the module's directory — or preferably install the whole module via Composer. This is mainly because I really don't like bundling dependencies with the module, especially when there's a bunch of them. (... although if you dislike Composer or for whatever reason can't use it, feel free to load either smalot/pdfparser or spatie/pdf-to-text manually. Just make sure that they're available by the time the module's class file is constructed.) -- If you get a chance to use this module, please let me know how it went ?
  25. Just to be clear: CKEditor 5 is licensed under GPL, unless I'm mistaken. LGPL would likely be less of an issue (if not a non-issue), since it's relatively permissive (no strong copyleft, dynamic linking with proprietary code allowed, etc.) Anywho — very interesting to hear that there's a (likely) roadmap to 5 in the future ?
×
×
  • Create New...