Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 05/10/2019 in all areas

  1. In this week’s post we’ll shift focus a bit and take a look at the latest version of FormBuilder (v38) just released today. It ends up being a fairly major release with a lot of new additions, optimizations and updates— https://processwire.com/blog/posts/formbuilder-v38-released/
    7 points
  2. Media Manager version 012 (released 10/05/2019) Happy to announce the latest release of Media Manager. Changelog ProcessWire 3.x support only. New GUI to match AdminThemeUiKit Upload Anywhere (drag and drop to upload in Media Manager Library and Media Manager Inputfields). Custom fields/columns - add any field to any of the Media Manager templates and access them as a property of a MediaManager object. Edit a single media including its custom fields I would like to thank all the beta testers! Documentation Documentation is now complete! Please report any missing links or anything that is not clear. Upgrading Grab the latest version of JqueryFileUpload (version 008) from here. Upgrade to that version (note: it is also namespaced) Grab the latest version of Media Manager using resend download links form here. Simply overwrite existing files but delete the files MediaManagerTabs.php and pocketgrid.css in the old files. Hit module refresh. You might need to clear compiled files several times. For most beta testers, upgrading has gone smoothly. However, two people have reported an error about class ProcessMediaManager not found in line 20 of MediaManagerUtilities. I have not been able to resolve this issue. I suspect FileCompiler is trying to be clever or some module loading order change? Please let me know how it goes. Beta testers, please upgrade as well. A few things have changed including a fix for the bug reported in the previous post. Screenshots Please refer to the documentation for more photos. Thanks!
    3 points
  3. Please no. ? I've been working with JsViews on a project and as the project became considerably large it became a nightmare to maintain. It's not necessarily JsViews fault though, it does a splendid job at what it does. But attaching event listeners to things based on their ID somewhere in the DOM and then reacting to it isn't really maintainable in a larger scale. In my opinion VueJS (https://vuejs.org) would be a great addition to the ProcessWire backend as they also somewhat follow the same philosophy and are a joy to work with.
    3 points
  4. ImageMagick does use this too, but do produce correct results when it is setup to work in 16 bit colordepth mode. And thats the main difference: IMagick can do this and GD only supports 8 bit colordepth mode. When working in 8 bit colordepth mode like the GD, the workaround with gammacorrection applies good results for the middark to white parts, but the very dark parts get masacred. A very good explanation with examples can be found here: http://www.ericbrasseur.org/gamma.html ( One of my personal favorite quotes on Eric Brasseur site is down in Solutions/Conclusions, regarding Adobe Photoshop: ) It is a possible workaround to get overall better results with resizing/downsizing then it would be without it. But not for very dark parts! Let Ryan answer this: https://github.com/processwire/processwire-issues/issues/465#issuecomment-363045136 ?
    3 points
  5. I fixed this for you ? tbh though, people were using Modernizr for years, and still use polyfills and whatnot, that bloats the HTML tag with countless pseudo classes, just so the tools know if their polyfill function should do anything this way or another. And with tools like Angular, Vue or React, you have inline crap all over the place... ng-this, ng-that, CSS written in JS(X) etc.
    3 points
  6. Never really thought about that detail but in terms of naming... Clone = I'd expect the same created/modified dates Copy = I wouldn't be shocked if those dates would be different An option in the module settings to change the behaviour could be nice - at least in your case. I can't really remember a situation in which I used those date. I almost always rely on additional date fields.
    2 points
  7. The status flags are bitwise so if you use a flag value directly to find published pages it would need to be like this: projects_awards.owner.status<2048 But for PageFinder selectors you can use a string for status: projects_awards.owner.status!=unpublished You would also want to exclude unpublished repeater pages because otherwise you can get unfilled "ready" repeater pages in your result. So your selector would be: template=repeater_projects_awards, projects_awards.owner.status!=unpublished, status!=unpublished, include=all
    2 points
  8. @pout Why just not use user IDs? Also, you can use the Pagenames class that was introduced in 3.0.111 like $page->name = $pages->names()->uniquePageName('user-' . $user->id, $users_parent); https://processwire.com/blog/posts/pw-3.0.111/
    2 points
  9. This module (github) does with site/assets/files what Ryan's DatabaseBackups module does with the database: Backup site/assets Download ZIP archive Upload ZIP archive Restore site/assets Motivation: This module can be the missing part for projects with content backup responsibility on the client's side: The client will be able to download DB and assets/files snapshots through the backend without filesystem access, thus backing up all content themselves. Release state alpha – do not use in production environments. Credits for the nice UI go to @ryan – I reused most of it and some other code from the DatabaseBackups module.
    2 points
  10. I've been working with ProcessWire for a while now, and I've noticed that using Composer to manage dependencies and autoload external libraries isn't as prevalent in ProcessWire development as in other areas of PHP programming. I started out by using the default setup recommend in this blogpost. However, one major problem I have with this approach is that all external dependencies live in the webroot (the directory the server points to), which is unfavourable from a security standpoint and, in my opinion, just feels a bit messy. In this tutorial, I want to go through a quick setup of Composer and ProcessWire that keeps the dependencies, all custom-written code and other source material outside of the webroot, and makes full usage of the Composer autoloader. This setup is pretty basic, so this tutorial is probably more useful to beginners (this is why I'll also include some general information on Composer), but hopefully everyone can take something away from this for their personal workflow. Site structure after setup This is what the directory structure can look like after the setup: . ├── composer.json ├── composer.lock ├── node_modules │ └── ... ├── public │ ├── index.php │ ├── site │ ├── wire │ └── ... ├── packacke-lock.json ├── package.json ├── sass │ ├── main.scss │ ├── _variables.scss │ └── ... ├── src │ ├── ContentBag.php │ └── ... └── vendor ├── autoload.php ├── composer ├── league ├── symfony └── ... As mentioned, the main point of this setup is to keep all external libraries, all other custom source code and resources out of the webroot. That includes Composer's vendor folder, your node_modules and JavaScript source folder if you are compiling JavaScript with webpack or something similar and including external scripts via NPM, or your CSS preprocessor files if you are using SASS or LESS. In this setup, the public directory acts as the webroot (the directory that is used as the entry point by the server, DocumentRoot in the Apache configuration). So all other files and directories in the mysite folder aren't accessible over the web, even if something goes wrong. One caveat of this setup is that it's not possible to install ProcessWire modules through Composer using the PW Module Installer (see Blogpost above), but that's just a minor inconvenience in my experience. Installation You'll need to have composer installed on your system for this. Installation guides can be found on getcomposer.org. First, open up your shell and navigate to the mysite folder. $ cd /path/to/mysite/ Now, we'll initialize a new Composer project: $ composer init The CLI will ask some questions about your projects. Some hints if you are unsure how to answer the prompts: Package names are in the format <vendor>/<project>, where vendor is your developer handle. I use my Github account, so I'll put moritzlost/mysite (all lowercase). Project type is project if you are creating a website. Author should be in the format Name <email>. Minimum Stability: I prefer stable, this way you only get stable versions of dependencies. License will be proprietary unless you plan on sharing your code under a FOSS license. Answer no to the interactive dependencies prompts. This creates the composer.json file, which will be used to keep track of your dependencies. For now, you only need to run the composer install command to initialize the vendor directory and the autoloader: $ composer install Now it's time to download and install ProcessWire into the public directory: $ git clone https://github.com/processwire/processwire public If you don't use git, you can also download ProcessWire manually. I like to clean up the directory after that: $ cd public $ rm -r .git .gitattributes .gitignore CONTRIBUTING.md LICENSE.TXT README.md Now, setup your development server to point to the /path/to/mysite/public/ directory (mind the public/ at the end!) and install ProcessWire normally. Including & using the autoloader With ProcessWire installed, we need to include the composer autoloader. If you check ProcessWire's index.php file, you'll see that it tries to include the autoloader if present. However, this assumes the vendor folder is inside the webroot, so it won't work in our case. One good place to include the autoloader is using a site hook file. We need the autoloader as early as possible, so we'll use init.php: EDIT: As @horst pointed out, it's much better to put this code inside the config.php file instead, as the autoloader will be included much earlier: // public/site/config.php <?php namespace Processwire; require '../../vendor/autoload.php'; The following also doesn't apply when including the autoloader in the config-file. This has one caveat: Since this file is executed by ProcessWire after all modules had their init methods called, the autoloader will not be available in those. I haven't come across a case where I needed it this early so far; however, if you really need to include the autoloader earlier than that, you could just edit the lines in the index.php file linked above to include the correct autoloader path. In this case, make sure not to overwrite this when you update the core! Now we can finally include external libraries and use them in our code without hassle! I'll give you an example. For one project, I needed to parse URLs and check some properties of the path, host et c. I could use parse_url, however that has a couple of downsides (specifically, it doesn't throw exceptions, but just fails silently). Since I didn't want to write a huge error-prone regex myself, I looked for a package that would help me out. I decided to use this URI parser, since it's included in the PHP League directory, which generally stands for high quality. First, install the dependency (from the project root, the folder your composer.json file lives in): $ composer require league/uri-parser This will download the package into your vendor directory and refresh the autoloader. Now you can just use the package in your own code, and composer will autoload the required class files: // public/site/templates/basic-page.php <?php namespace Processwire; use \League\Uri\Parser; // ... if ($url = $page->get('url')) { $parser = new Parser(); $parsed_url = $parser->parse($url); // do stuff with $parsed_url ... } Wiring up custom classes and code Another topic that I find really useful but often gets overlooked in Composer tutorials is the ability to wire up your own namespace to a folder. So if you want to write some object-oriented code outside of your template files, this gives you an easy way to autoload those using Composer as well. If you look at the tree above, you'll see there's a src/ directory inside the project root, and a ContentBag.php file inside. I want to connect classes in this directory with a custom namespace to be able to have them autoloaded when I use them in my templates. To do this, you need to edit your composer.json file: { "name": "moritzlost/mysite", "type": "project", "license": "proprietary", "authors": [ { "name": "Moritz L'Hoest", "email": "info@herebedragons.world" } ], "minimum-stability": "stable", "require": {}, "autoload": { "psr-4": { "MoritzLost\\MySite\\": "src/" } } } Most of this stuff was added during initialization, for now take note of the autoload information. The syntax is a bit tricky, since you have to escape the namespace seperator (backslash) with another backslash (see the documentation for more information). Also note the PSR-4 key, since that's the standard I use to namespace my classes. The line "MoritzLost\\MySite\\": "src/" tells Composer to look for classes under the namespace \MoritzLost\MySite\ in the src/ directory in my project root. After adding the autoload information, you have to tell composer to refresh the autoloader information: $ composer dump-autoload Now I'm ready to use my classes in my templates. So, if I have this file: // src/ContentBag.php <?php namespace MoritzLost\MySite; class ContentBag { // class stuff } I can now use the ContentBag class freely in my templates without having to include those files manually: // public/site/templates/home.php <?php namespace Processwire; use MoritzLost\MySite\ContentBag; $contentbag = new ContentBag(); // do stuff with contentbag ... Awesome! By the way, in PSR-4, sub-namespaces correspond to folders, so I can put the class MoritzLost\MySite\Stuff\SomeStuff in src/Stuff/SomeStuff.php and it will get autoloaded as well. If you have a lot of classes, you can group them this way. Conclusion With this setup, you are following secure practices and have much flexibility over what you want to include in your project. For example, you can just as well initialize a JavaScript project by typing npm init in the project root. You can also start tracking the source code of your project inside your src/ directory independently of the ProcessWire installation. All in all, you have good seperation of concerns between ProcessWire, external dependencies, your templates and your OOP-code, as well as another level of security should your Server or CGI-handler ever go AWOL. You can also build upon this approach. For example, it's good practice to keep credentials for your database outside the webroot. So you could modify the public/site/config.php file to include a config or .env file in your project root and read the database credentials from there. Anyway, that's the setup I came up with. I'm sure it's not perfect yet; also this tutorial is probably missing some information or isn't detailed enough in some areas depending on your level of experience. Feel free to ask for clarification, and to point out the things I got wrong. I like to learn as well ? Thanks for making it all the way to the bottom. Cheers!
    1 point
  11. The current behavior is that the created and modified dates are brought across to the new page, but I wonder if this is expected / desired behavior. For my current use, I'd prefer they weren't but before submitting an issue I'd like to know what others think. Thanks!
    1 point
  12. Moderator note: this is not a module support thread, so I'm moving it to the General Support area of the forum instead. Please keep in mind that the Modules/Plugins area is only intended for module-specific support threads. Thanks!
    1 point
  13. This works: $this->addHookAfter('Pages::cloned', function(HookEvent $event) { $p = $event->arguments(1); $p->created = time(); $p->save(array('quiet' => true)); }); This doesn't handle "modified", but for my needs I don't need that because publishing the newly cloned page will adjust that automatically then. But, if you do, you could add this to the hook: $sql = "UPDATE `pages` SET `modified` = NOW() WHERE `id` = '".$p->id."';"; $this->wire('db')->query($sql);
    1 point
  14. Thanks for your thoughts @wbmnfktr - it's actually weird to me that the core module is called "Clone" but the page list action button is called "Copy". I kind of agree with clone having the same dates because a clone should be identical, but I also don't think that in reality anyone actually wants a clone in the end - usually it's just a quick way to start a new page from existing content and modifying it to your needs after that. An option for changing the behavior might be a decent approach to the problem. Anyone else have any thoughts? I think in reality I'll probably end up hooking into ___clone or ___cloned and adjust "created" via SQL (or the quite save option) because I don't honestly see that Ryan will want to change the current behavior.
    1 point
  15. @pout You can hook to Pages::added. It will fire only once when the user is created. wire()->addHookAfter('Pages::added', function($event) { $page = $event->arguments(0); if($page->template == "user"){ $user_id = $event->arguments(0)->id; } }); From this hook, you can create user's page wire()->addHookAfter('Pages::saved', function($event) { $page = $event->arguments(0); if($page->template == "user"){ $user_id = $event->arguments(0)->id; $savedUser = $page; $userpage = wire('pages')->find("parent=/parentpage, name=page-for-user-".$user_id); if ( count($userpage) == 0 ) { $parent = wire('pages')->get('/parentpage'); $page = new Page(); $page->template = 'Lektionen'; $page->name = $pages->names()->uniquePageName('page-for-user-' . $user_id, $parent); $page->parent = $parent; $page->title = $savedUser->name; $page->save(); } } });
    1 point
  16. Are you sure all those IDs were necessary? A lot can be done without IDs all over the markup, for example: https://www.jsviews.com/#samples/form-els/visible-binding BTW, VueJS would be next thing I would pick if JsViews was not around but as JsViews is still being maintained I am not planning to switch to anything just yet. Also, those who seem to have experience with VueJS have issues with it too, eg.: https://vuejsdevelopers.com/2017/09/17/vue-js-avoid-dom-templates/ Looks like nothing is perfect ?
    1 point
  17. This is amazing. PW is so so so good. Much appreciated, @Robin S and the others ?
    1 point
  18. I guess you could do a CSS solution: https://www.google.at/search?q=css+truncate+multiline+text&oq=css+truncate&aqs=chrome.1.69i57j0l5.4338j0j4&sourceid=chrome&ie=UTF-8 Or you could also create custom labels via a hook: // /site/ready.php $wire->addHookAfter('Pages::saveReady(template=yourtemplate)', function(HookEvent $event) { $page = $event->arguments(0); $page->yourcustomlabel = $this->sanitizer->truncate($page->yourtextarea, 150); });
    1 point
  19. I agree that this is a challenge. I also find the Mystique approach very interesting! Did you see my approach of migrations? From the docs: Migrations are shipped with the module in /site/modules/YourModule/RockMigrations/XXX.php // 0.0.5.php <?php namespace ProcessWire; /** * Änderungen für neues Feld "Kundenstatus" */ $upgrade = function(RockMigrations $rm) { $rm->createField('ernum', 'text', [ "label" => "ER-Nummer", ]); $rm->addFieldToTemplate('ernum', 'rockprojecteffort', 'cost_gross'); }; $downgrade = function(RockMigrations $rm) { $rm->deleteField('ernum'); }; I can then just do: git pull $rm = $modules->get('RockMigrations'); $rm->setModule('YourModule'); $rm->up('0.0.5'); It's not at all complete yet, but it works well on several production projects and simplified my workflow a lot! Here an example of a more complex migration (that is IMHO still self expanatory and easy to create and manage): <?php namespace ProcessWire; /** * tweaks */ $upgrade = function(RockMigrations $rm) { $rm->setFieldData('invoiceto', ["labelFieldFormat" => "{rockcontact_parent}, {title}, E-Mail = {rockcontact_email}"], 'rockproject'); $rm->installModule('Prozesse'); $rm->installModule('ProcessProzesse'); $rm->installModule('Rechnungsfreigaben'); $rm->installModule('ProcessRechnungsfreigaben'); $rm->addPermissionsToRoles( ['prozesse','prozesse-rechnungsfreigaben'], ['office-management', 'senior'] ); $rm->createField('iscurrent', 'checkbox', [ 'label' => 'Ist der aktuellste von mehreren Einträgen', 'collapsed' => Inputfield::collapsedNo, ]); $rm->addFieldToTemplate('iscurrent', 'invoiceconfirmation'); foreach($this->pages->find('template=invoiceconfirmation') as $p) $p->save(); }; $downgrade = function(RockMigrations $rm) { $rm->deleteField('iscurrent'); $rm->uninstallModule('ProcessRechnungsfreigaben'); $rm->uninstallModule('Rechnungsfreigaben'); $rm->uninstallModule('ProcessProzesse'); $rm->uninstallModule('Prozesse'); $rm->setFieldData('invoiceto', ["labelFieldFormat" => "{rockcontact_parent}, {title}"], 'rockproject'); }; You see that it makes task that are usually tedious via the API very easy. The first line (setFieldData for invoiceto) sets new field settings in template context, for example. IMHO the way to go are migrations. The mystique approach looks very interesting indeed, but it will not work in all scenarios (eg when you need to manage/edit/install/uninstall modules or templates or roles and permissions. @LostKobrakai had a reason for developing his module and it took me quite long to understand that ? I just didn't like the implementation a lot due to the reasons mentioned in the docs of RockMigrations. Said that I have to admit that RockMigrations is also still a very early stage implementation of would would be necessary in my opinion. I think PW would strongly need a solid API to handle all those migration stuff properly and easily. Something that makes it easy to migrate between different module versions, upgrade modules, downgrade modules, revert changes, check for compatibility before installation and so on. Something that maybe even automatically syncs the module versions with the migration versions (so that your code is always in sync with your DB, otherwise it would be possible that your code requests a field that does not exist in the DB yet). If that worked all we would have to do would be a "git pull" and pw would take care of the rest. My module is kind of a quick and dirty implementation of that dream, but it works quite well ?
    1 point
  20. Hi @kongondo, we've tested your new MM 012, great work! In grid view, there is a small bug in rendering thumbnails: If the calculated width is not a whole number, the style of the elements div.mm_page_thumb is written as "width: 263,5px" for example. Because browsers expect decimal numbers in CSS with a dot, they fail in case of the comma, so the width is undefined and the thumbnail is not shown (see screenshot). This error probably only occurs in german environments, where the decimal point is the comma by default. I've changed line 524 in MediaManagerRenderer.php, what fixed the problem: $wrapperWidth = str_replace(',', '.', $media->thumbWidth) . 'px'; Alternatively, rounding the thumb width will have the same effect, because the decimal part isn't really important on rendering. Greetings, Thomas.
    1 point
  21. Regarding compression and quality | webpQuality | lossy | lossless and how different the two rendering engines work, I want to show a little example, comparing two image motives with equal dimensions. I have created two master source images in the dimensions 3000 x 2000 px. The first one is a 24bit color jpeg, filled with noise in Photoshop. The second one is a checkerboard with 100x100 squares, only black and white, but also saved as 24bit color jpeg. I don't want to scare or confuse anybody. Look at the following tables with the file sizes for the different qualities, rendering engines and output formats. (Just let it sink, ...) Really interesting are the results of the IM files in 100% quality, compared to their jpegs and compared between both motives. ? EDIT: And here two more real world motives, but also with interesting IM 100 quality results:
    1 point
  22. News Update - 3 May 2019 - Part Two Class Padloper - Public API We have re-written the Padloper Class (Padloper.module) to server as proxy class for use as a public API for everything you need to do with Padloper (except rendering; we don't do that :-), see previous post). Think of ProcessWire $pages variable. This is something similar in that it allows you to interact with (retrieval and manipulation) with Padloper at a higher level. Rather than multiple methods from multiple classes such as $modules->get("PadCart")->someMethod() or $modules->get("PadCheckout)->anotherMethod(), you will only need to interact with one class, Padloper. This will hopefully streamline your development process. Most (maybe all) of the current modules will be "converted" to Padloper core classes (.php) and/or absorbed in other classes. This means less modules will be installed. With one class (proxy class but also with native methods) you won't need to know (but good if you did :-)), the names of the fields that Padloper will ship with. Your code could be as simple as this: // get the class $padloper = $modules->get("Padloper"); // find a limited number of products $products = $padloper->findProducts(); // find products matching a criteria $selector = "brand=toshiba,price>200"; $products = $padloper->findProducts($selector); $selector = "tags|categories~=Vane,type*=Jac,description~=Some text,images.count>3"; $products = $padloper->findProducts($selector); $selector = "inventory<=10,variant_option=size|colour,variant_option_value=red|black"; $products = $padloper->findProducts($selector); // find related products $related = $padloper->findRelatedProducts($product); // get current cart $cart = $padloper->getCart(); // add item to current cart $padloper->addCart($item); // import products $padloper->importProducts($imports);// array/json/csv // get an order $order = $padloper->getOrder($id); // export orders $padloper->exportOrders($selectedOrders); // etc for customers, discounts, downloads, categories, tags, brands, variants, reports, inventory, types, etc Note the short 'field names' in the selectors. For instance, there are no fields known as brand or tags or categories in Padloper (they have other names and/or are subfields) but Padloper will convert them into something ProcessWire will be happy with. Currently, we don't support Or:groups, sub-selector selectors and similar using the 'short-field-names-selectors' . For such, you would need to pass the the full names and subfields of the Padloper fields you want to query to findProducts(), etc. The Padloper Class is also useful for debugging your shop, producing reports using the API, etc.. We'll talk about this and more in future posts.
    1 point
  23. News Update - 3 May 2019 - Part One The little speckled fella has been very busy on the trail. Despite being the smallest of its kind, she has lofty dreams. We've been working on the API and the Products GUI. In the next post, I'll tell you more about the API. Products Features and GUI Though there are a few issues still pending (aren't there always? sigh), I am relatively pleased with the results. Of course, during beta testing we'll received and incorporate feedback as best as we can. Only UI-Kit theme will be officially supported. Multilingual fields if site is multilingual Ajax powered inputs for fast and convenient editing Four types of products Physical product requiring shipping Physical product not requiring shipping (for collection) Digital product Service/Event (etc) products - e.g. Swimming lessons, Consultancy services, Hotel booking, etc Product Classification (ajax powered) by: Type: e.g. Belt, trousers, etc Brand: Puma, Sanyo, whatever (editors can type in or import brand names + planning to support logos) Categories (aka Collections): Multiple categories, e.g. Men, Girls, Hospitality Tags: Multiple tags can be entered, e.g. sale, amazing, etc Product Variants (consists of an Option (e.g. Colour) and an Option Value (e.g. Red) Add zero or n variants as you wish Live preview as you build variants Each created product variant can be enabled/disabled. Devs can then decide to either show that variant as unavailable or not show them at all. That's up to you :-). Apart from classifications, shipping class, inventory policy, weight and dimensions units, title and description (and this latter one may change), almost all product properties will vary by variant if variants are used Product properties include: Images Colour (more on this below) Downloads (centralised and reusable) Price and Compare Price (aka former price) Inventory policy (whether to track or not) Charge taxes SKU (stock keeping unit) Inventory (quantity) Allow back orders (aka overselling) - @note: this can be set per variant. This is useful if one variant can be restocked faster than others Weight Length Width Height Weight Unit (mg, g, kg, oz, lb, t) Dimensions Unit (mm, cm, m, in, ft ) Shipping Class - can be used for product-based shipping if needed (e.g. bulky goods, light, fragile, small items, perishable, etc) Images (more on this below) Downloads (more on this below) Images Multiple images can be added to both a product and its variants (in case its has some). Images add to the product itself can be used with all variants Images added to a variant are tracked/tagged as belonging to only that variant In some cases, it may not make much sense to add different images for similar variants. For instance, a small red hat and a large red hat could probably share the same images. Although we do not currently support specifying an already uploaded image as belonging to a group of variants, this may change in the future Colour Similar to images, can be set at both product and its variants level Colour saved in RGBA format Downloads Also similar to images, can be populated for both both product and/or its variants Multiple files can be added to a product A file designated for 'whole' product will be available to download irrespective which variant of the product was purchased Conversely, a file or files saved for a variant will only be available to the buyer if they buy that variant of the product The above is useful if you want buyers to be able to download different files of the same product. For instance, recently someone needed to sell two versions of a font as part of one product. This is a solution for such cases. TODO List Lots! e.g. default settings for some properties, e.g. weight unit, shop currency, etc. For the frontend, we are creating a rich language-aware API that you can use to build your shop however you want. There will be no rendering of markup (but see first post in this thread about a separate fully functional frontend shop). In the next post, we talk a bit about the API. Before that, here are some screenshots and a video demo (if you can spare some 20 minutes away from watching, er..., cat videos? ?) Screenshots Video Demo Thanks ?
    1 point
  24. @horst, it's perfect for me. I already had WebP since your code from late 2018 and use my own ImageSizer, which relies on LibVips. The Vips engine is very fast - about 5 times faster than ImageMagick. I hope WebP will make it into the core soon - many thanks for your hard work!
    1 point
  25. @Tom. Many thanks for your feedback! And, uhm, - GD does not use the compressed jpeg for webp creation, but currently IMagick does. But this is not intended and I locally have a version that uses the uncompressed src variation for webp creation. I will finalize this and commit an update to the test branch later this evening. So the intended usage is that you can define independend quality settings for jpeg and webp, and both final variations will be created from the uncompressed variation bitimage. ["quality" => 80; "webpQuality" => 90] If you simply want to test out GD-Lib when IMagick is installed with higher priority, you can pass the param "forceEngine" with the options array to the size method: $options = [ 'forceEngine' => 'ImageSizerEngineGD', // ImageSizerEngineGD | ImageSizerEngineIMagick 'forceNew' => true, 'webpAdd' => true, 'webpQuality' => 90, 'quality' => 80, 'sharpening' => 'none' ];
    1 point
  26. @lokomotivan @Sergio I have now experimented with many options to solve this problem. However, there is only one way, which covers both behaviors. If you don't want segments to be counted, just enable the option as the behavior is current. But if segments are to be counted as well, the segments MUST be defined in the template configuration. For dynamic segments with RegEx. For this I have inserted a passage in the readme with the link to the PW help. There is currently no other option. The problem is that the Page Hit Counter hooked into the PageNotFound process (But I also tried PageRender, etc.). If URL segments are allowed but not defined, a 404 is never triggered from Processwire. This means that the Page Hit Counter cannot be called. For the tracking of segments, so simply define the segments. ? I also released an update with version 1.2.5, which improves the behavior when tracking 404 errors. All infos and download as always in the first post.
    1 point
  27. I started changing over my default site profile that I use as a base for new projects to use the functions API and region() function. Then I realised that neither of these will suit me because the functions can't be interpolated in strings the way variables can. I much prefer string interpolation over concatenation - I find it more concise and easier to read. The main attraction to me was the IDE code completion. Pasting the following at the top of each template file does the trick and isn't much hassle. namespace ProcessWire; /** * ProcessWire API variables * * @var $page Page * @var $pages Pages * @var $modules Modules * @var $user User * @var $users Users * @var $permissions Permissions * @var $roles Roles * @var $input WireInput * @var $sanitizer Sanitizer * @var $session Session * @var $log WireLog * @var $cache WireCache * @var $datetime WireDateTime * @var $files WireFileTools * @var $mail WireMail * @var $config Config * @var $database WireDatabasePDO * @var $fields Fields * @var $templates Templates * @var $languages Languages * @var $wire ProcessWire * @var $procache \ProCache **/ A similar thing can be done for region variables to avoid IDE 'undefined variable' notices. /** * Template region variables * * @var $headline * @var $content * etc **/ I've set these up as a file template in PhpStorm so they appear automatically for each new PHP file created in the project.
    1 point
  28. From time to time, when I'm on a website, I'm checking the source, because I'm curious. But may be since two years, I got the feeling, that the more and more websites are stuffed with interesting crap. Today I found these body styles. It's from Squarespace. There were times, when a webpage was stuffed with table constructions and local styles. Now this madness appears again.
    0 points
  29. I think it will required a complete rewrite, based on some JS "framework" magic... Sure. While adding UIkit 3 to the mix was possible, it just added another layer of complexity. The current admin is a patchwork, although a good one, but there is room for improvement as always I think. Ryan likes proven tech, so I wish he took a closer look at JsViews by Boris Moore: https://www.jsviews.com/#samples/editable/submit 6+ years of constant development without breaking changes and reinventing the wheel, in this sense similar to ProcessWire's path, so I started using it too. It took me a while to stumble upon it by accident.
    0 points
×
×
  • Create New...