Leaderboard
Popular Content
Showing content with the highest reputation on 06/07/2019 in all areas
-
I remember to had this same issue with PhpStorm. Open templates with Notepad, unwanted char (��) will appear or use SublimeText 3 with encoding UTF-8 without BOM.3 points
-
3 points
-
Hey thank you so much for your answers. First at all I'm happy that it doesn't seem impossible what I'm trying to do. I will check out, if I can solve my problem with your advices and will write back here with more details when I have solved it. Have a nice weekend!2 points
-
Ah, @ryan has added support for PNG8 to the Imagick engine, what wasn't before. He also asked me why this wasn't added and I was unsure if I simply forgot to add it. But now when I see this, I think I had tested it and removed it from the Imagick supported filetypes / subtypes, so that this images always were rendered by GD! until before the last Update. https://github.com/processwire/processwire/pull/141#issuecomment-495983196 So it seems it should be rolled back again, at least for PNG8. EDIT: I couldn't remember as it is (how many?) years ago as the Image Engine System was introduced. And yep, it would have been better to add some comments. ;-)2 points
-
Ok, it could also be my local MAMP server setup. Because I have recently installed Imagick with Pecl and use this instead the build-in Imagick of MAMP. But switching didn't change anything and I think I have experienced this issue on our webhoster as well. Let's wait if someone else experienced this. ?2 points
-
Hi @AndZyk I can confirm this. If I upload a PNG saved by Photoshop then all is good but if I upload a PNG optimized with ImageOptim then transparency is removed and some sort of inverted version of the image is generated. It does look like it is a ProcessWire 3.0.132 issue indeed. It would be great to fix it ASAP as it is a real pita....2 points
-
@flydev thanks. i reopend all files with Sublimetext 3.. found nothing. Then i begun to open all files with VSC.. and there i finally found �������� behind the <html> tag. I have no clue how they ended up there nor what funky encoding they are, but deleting them finally solved my problem.2 points
-
Hello, since the upgrade to PW 3.0.132, I have noticed some artefacts in the generated images: Before the upgrade: I have the ImageSizerEngineIMagick installed and use PHP 7.2.14 with Imagick 3.4.4. I think this issue is specific to Imagick. If I uninstall ImageSizerEngineIMagick I don't have artefacts. Has anyone else noticed such issue or is it maybe just my local installation? Regards, Andreas2 points
-
Hi @Salah-eddine Etangi, Welcome to the forum. Can you show us any error you saw when you access the backend (admin space)? Gideon2 points
-
2 points
-
I have had this module sitting in a 95% complete state for a while now and have finally made the push to get it out there. Thanks to @teppo for his Hanna Code Helper module which I referred to and borrowed from during development. http://modules.processwire.com/modules/hanna-code-dialog/ https://github.com/Toutouwai/HannaCodeDialog HannaCodeDialog Provides a number of enhancements for working with Hanna Code tags in CKEditor. The main enhancement is that Hanna tags in a CKEditor field may be double-clicked to edit their attributes using core ProcessWire inputfields in a modal dialog. Requires the Hanna Code module and >= ProcessWire v3.0.0. Installation Install the HannaCodeDialog module using any of the normal methods. For any CKEditor field where you want the "Insert Hanna tag" dropdown menu to appear in the CKEditor toolbar, visit the field settings and add "HannaDropdown" to the "CKEditor Toolbar" settings field. Module configuration Visit the module configuration screen to set any of the following: Exclude prefix: Hanna tags named with this prefix will not appear in the CKEditor toolbar dropdown menu for Hanna tag insertion. Exclude Hanna tags: Hanna tags selected here will not appear in the CKEditor toolbar dropdown menu for Hanna tag insertion. Background colour of tag widgets: you can customise the background colour used for Hanna tags in CKEditor if you like. Dialog width: in pixels Dialog height: in pixels Features Insert tag from toolbar dropdown menu Place the cursor in the CKEditor window where you want to insert your Hanna tag, then select the tag from the "Insert Hanna tag" dropdown. Advanced: if you want to control which tags appear in the dropdown on particular pages or templates you can hook HannaCodeDialog::getDropdownTags. See the forum support thread for examples . Edit tag attributes in modal dialog Insert a tag using the dropdown or double-click an existing tag in the CKEditor window to edit the tag attributes in a modal dialog. Tags are widgets Hanna tags that have been inserted in a CKEditor window are "widgets" - they have a background colour for easy identification, are protected from accidental editing, and can be moved within the text by drag-and-drop. Options for tag attributes may be defined You can define options for a tag attribute so that editors must choose an option rather than type text. This is useful for when only certain strings are valid for an attribute and also has the benefit of avoiding typos. Add a new attribute for the Hanna tag, named the same as the existing attribute you want to add options for, followed by "__options". The options themselves are defined as a string, using a pipe character as a delimiter between options. Example for an existing attribute named "vegetables": vegetables__options=Spinach|Pumpkin|Celery|Tomato|Brussels Sprout|Potato You can define a default for an attribute as normal. Use a pipe delimiter if defining multiple options as the default, for example: vegetables=Tomato|Potato Dynamic options Besides defining static options as above, you can use one Hanna tag to dynamically generate options for another. For instance, you could create a Hanna tag that generates options based on images that have been uploaded to the page, or the titles of children of the page. Your Hanna tag that generates the options should echo a string of options delimited by pipe characters (i.e. the same format as a static options string). You will probably want to name the Hanna tag that generates the options so that it starts with an underscore (or whatever prefix you have configured as the "exclude" prefix in the module config), to avoid it appearing as an insertable tag in the HannaCodeDialog dropdown menu. Example for an existing attribute named "image": image__options=[[_images_on_page]] And the code for the _images_on_page tag: <?php $image_names = array(); $image_fields = $page->fields->find('type=FieldtypeImage')->explode('name'); foreach($image_fields as $image_field) { $image_names = array_unique( array_merge($image_names, $page->$image_field->explode('name') ) ); } echo implode('|', $image_names); Choice of inputfield for attribute You can choose the inputfield that is used for an attribute in the dialog. For text attributes the supported inputfields are text (this is the default inputfield for text attributes so it isn't necessary to specify it if you want it) and textarea. Note: any manual line breaks inside a textarea are removed because these will break the CKEditor tag widget. Inputfields that support the selection of a single option are select (this is the default inputfield for attributes with options so it isn't necessary to specify it if you want it) and radios. Inputfields that support the selection of multiple options are selectmultiple, asmselect and checkboxes. You can also specify a checkbox inputfield - this is not for attributes with defined options but will limit an attribute to an integer value of 1 or 0. The names of the inputfield types are case-insensitive. Example for an existing attribute named "vegetables": vegetables__type=asmselect Descriptions and notes for inputfields You can add a description or notes to an attribute and these will be displayed in the dialog. Example for an existing attribute named "vegetables": vegetables__description=Please select vegetables for your soup. vegetables__notes=Pumpkin and celery is a delicious combination. Notes When creating or editing a Hanna tag you can view a basic cheatsheet outlining the HannaCodeDialog features relating to attributes below the "Attributes" config inputfield. Advanced Define or manipulate options in a hook You can hook HannaCodeDialog::prepareOptions to define or manipulate options for a Hanna tag attribute. Your Hanna tag must include a someattribute__options attribute in order for the hook to fire. The prepareOptions method receives the following arguments that can be used in your hook: options_string Any existing string of options you have set for the attribute attribute_name The name of the attribute the options are for tag_name The name of the Hanna tag page The page being edited If you hook after HannaCodeDialog::prepareOptions then your hook should set $event->return to an array of option values, or an associative array in the form of $value => $label. Build entire dialog form in a hook You can hook after HannaCodeDialog::buildForm to add inputfields to the dialog form. You can define options for the inputfields when you add them. Using a hook like this can be useful if you prefer to configure inputfield type/options/descriptions/notes in your IDE rather than as extra attributes in the Hanna tag settings. It's also useful if you want to use inputfield settings such as showIf. When you add the inputfields you must set both the name and the id of the inputfield to match the attribute name. You only need to set an inputfield value in the hook if you want to force the value - otherwise the current values from the tag are automatically applied. To use this hook you only have to define the essential attributes (the "fields" for the tag) in the Hanna Code settings and then all the other inputfield settings can be set in the hook. Example buildForm() hook The Hanna Code attributes defined for tag "meal" (a default value is defined for "vegetables"): vegetables=Carrot meat cooking_style comments The hook code in /site/ready.php: $wire->addHookAfter('HannaCodeDialog::buildForm', function(HookEvent $event) { // The Hanna tag that is being opened in the dialog $tag_name = $event->arguments(0); // Other arguments if you need them /* @var Page $edited_page */ $edited_page = $event->arguments(1); // The page open in Page Edit $current_attributes = $event->arguments(2); // The current attribute values $default_attributes = $event->arguments(3); // The default attribute values // The form rendered in the dialog /* @var InputfieldForm $form */ $form = $event->return; if($tag_name === 'meal') { $modules = $event->wire('modules'); /* @var InputfieldCheckboxes $f */ $f = $modules->InputfieldCheckboxes; $f->name = 'vegetables'; // Set name to match attribute $f->id = 'vegetables'; // Set id to match attribute $f->label = 'Vegetables'; $f->description = 'Please select some vegetables.'; $f->notes = "If you don't eat your vegetables you can't have any pudding."; $f->addOptions(['Carrot', 'Cabbage', 'Celery'], false); $form->add($f); /* @var InputfieldRadios $f */ $f = $modules->InputfieldRadios; $f->name = 'meat'; $f->id = 'meat'; $f->label = 'Meat'; $f->addOptions(['Pork', 'Beef', 'Chicken', 'Lamb'], false); $form->add($f); /* @var InputfieldSelect $f */ $f = $modules->InputfieldSelect; $f->name = 'cooking_style'; $f->id = 'cooking_style'; $f->label = 'How would you like it cooked?'; $f->addOptions(['Fried', 'Boiled', 'Baked'], false); $form->add($f); /* @var InputfieldText $f */ $f = $modules->InputfieldText; $f->name = 'comments'; $f->id = 'comments'; $f->label = 'Comments for the chef'; $f->showIf = 'cooking_style=Fried'; $form->add($f); } }); Troubleshooting HannaCodeDialog includes and automatically loads the third-party CKEditor plugins Line Utilities and Widget. If you have added these plugins to your CKEditor field already for some purpose and experience problems with HannaCodeDialog try deactivating those plugins from the CKEditor field settings.1 point
-
We recently rebuilt the Architekturführer Köln (architectural guide Cologne) as a mobile-first JavaScript web app, powered by VueJS in the frontend and ProcessWire in the backend. Concept, design and implementation by schwarzdesign! The Architekturführer Köln is a guidebook and now a web application about architectural highlights in Cologne, Germany. It contains detailled information about around 100 objects (architectural landmarks) in Cologne. The web app offers multiple ways to search through all available objects, including: An interactive live map A list of object near the user's location Filtering based on architect, district and category Favourites saved by the user The frontend is written entirely in JavaScript, with the data coming from a ProcessWire-powered API-first backend. Frontend The app is built with the Vue framework and compiled with Webpack 4. As a learning exercise and for greater customizability we opted to not use Vue CLI, and instead wrote our own Webpack config with individually defined dependencies. The site is a SPA (Single Page Application), which means all internal links are intercepted by the Vue app and the corresponding routes (pages) are generated by the framework directly in the browser, using data retrieved from the API. It's also a PWA (Progressive Web App), the main feature of which is that you can install it to your home screen on your phone and launch it from there like a regular app. It also includes a service worker which catches requests to the API and returns cached responses when the network is not available. The Architekturführer is supposed to be taken with you on a walk through the city, and will keep working even if you are completely offline. Notable mentions from the tech stack: Vue Vue Router for the SPA functionality VueX for state management and storage / caching of the data returned through the API Leaflet (with Mapbox tiles) for the interactive maps Webpack 4 for compilation of the app into a single distributable Babel for transpilation of ES6+ SASS & PostCSS with Autoprefixer as a convenience for SASS in SFCs Google Workbox to generate the service worker instead of writing lots of boilerplate code Bootstrap 4 is barely used here, but we still included it's reboot and grid system Backend The ProcessWire backend is API-only, there are no server-side rendered templates, which means the only PHP template is the one used for the API. For this API, we used a single content type (template) with a couple of pre-defined endpoints (url segments); most importantly we built entdpoints to get a list of all objects (either including the full data, or only the data necessary to show teaser tiles), as well as individual objects and taxonomies. The API template which acts as a controller contains all the necessary switches and selectors to serve the correct response in <100 lines of code. Since we wanted some flexibility regarding the format in which different fields were transmitted over the api, we wrote a function to extract arbitrary page fields from ProcessWire pages and return them as serializable standard objects. There's also a function that takes a Pageimage object, creates multiple variants in different sizes and returns an object containing their base path and an array of variants (identified by their basename and width). We use that one to generate responsive images in the frontend. Check out the code for both functions in this gist. We used native ProcessWire data wherever possible, so as to not duplicate that work in the frontend app. For example: Page names from the backend translate to URLs in the frontend in the form of route parameters for the Vue Router Page IDs from ProcessWire are included in the API responses, we use those to identify objects across the app, for example to store the user's favourites, and as render keys for object lists Taxonomies have their own API endpoints, and objects contain their taxonomies only as IDs (in the same way ProcessWire uses Page References) Finally, the raw JSON data is cached using the cache API and this handy trick by @LostKobrakai to store raw JSON strings over the cache API. Screenshots1 point
-
Hi all users of the croppable image 3 fieldtype. I'm currently working on the module, or better I'm reworking the module to support webp copys like the core image field does. Unfortunately this will break backwards compatibility! ? My questions are, how should we handle this? Until now the crop variation has this sort of names: basename.ext becomes basename.-suffix.ext But with the new version, it looks like regular image variation files with a -suffix: basename.ext becomes basename.100x200-suffix.ext My current thoughts are along that lines: I create a new named module: CroppableImage4, that supports the same API as the CAI3 version plus an alternative method like getCrop4("suffix"), and I add some checking, when the CAI3 is installed / active, it only hooks the plus method, not the regular one. What do you think? Any suggestions, ideas, wishes? And how can we savely update from CAI3 to CAI4, for example with existing websites containing tons of images ❓ PS: Besides that, the new module now supports individual $options as array or selector strings. It generates 0x48 thumbs and webp copies by auto generation and by manually creating a crop. It removes all variations on every changes: changing a single image, changing or removing settings. It has input fields in modules config for webpAdd and webpQuality, so you can handle it different from the $config->imageSizerSettings, and you now can add individual options with every API call, like with the core image field: $pageimage->getCrop("suffix", $options)->url, or $pageimage->getCrop("suffix", $options)->webp->url. And some more minor tweaks.1 point
-
I do not need it ? but my client does so I had to find a way not to upload the "same" image twice, once for the client and once for the site. The client also needs those PNGs to be as small as possible, so that is where crushing them comes into play. Anyway, if you could revert the change, that would be great for the time being. Maybe a note in the source code about the issue could help to decide when to add it again to the supported filetypes is feasible. (A few years from now on, maybe?)1 point
-
Hohoho, a 3000 x 3000 PNG, for what do you need this? You generate a 1000 x 1000 variation? If you use photoshop jpeg quality 12 you also has lossless master images. My favor would be to have LZW-Tiffs as master, = Lossless compression and a format that cannot wrongly used for web output. ?1 point
-
? I know the theory, however, saving space can be important on some servers. Also, in this particular case form a 3000x3000 PNG8 a 1000x1000 JPG is generated, and I do not think anyone can tell what the source was just by looking at it.1 point
-
Yep, and I / we don't like version hunting for all the format issues in Imagick or GD. ?1 point
-
I see! Yes, those PNGs are indeed PNG8 in my case. Tracy on MAMP Pro reports :IMAGICK SETTINGS Version: 6.9.6 Whereas in production: IMAGICK SETTINGS Version: 6.7.8 It seems like it is a bug in older verions of Imagick which are still quite common, I guess.1 point
-
Hmmm, upon further inspections, I'm no longer so sure that it is a ProcessWire issue because the clone of the site in question in my local dev environment (MAMP Pro) can generate proper PNGs, while the one in production cannot. But still, it started happening after some ProcessWire upgrades.1 point
-
Thank you for confirming. In my case the original file was exported with Sketch unoptimized, but in a UHD resolution.1 point
-
I ran into issues with a slow server using this method, where wireHttp would already resolve a result while RestApi was still running. So with help from my co-worker @harmvandeven we came up with a more stable version, with some more redundancy: <?php /* api.php, a simple PW template to fill the gap between the RestApi and ProCache modules v2 @author: @eelkenet, with help from @harmvandeven & @ryan 1. Create a template called 'api' and set it up using the following settings: - Allow URL segments - Allow guests to view the page - Set the Content-Type to application/json - Make sure to NOT Prepend or Append any files 2. Add a page using this template and allow ProCache to run its magic */ $timeout = 600; $maxAttempts = 10; // Pre-check for unwanted symbols if (strpos($input->urlSegmentStr(), '.') !== false) { throw new Wire404Exception(); } // Build request URL $endpoint = $modules->get("RestApi")->endpoint; $url = $input->scheme() . "://" . $config->httpHost . "/" . $endpoint ."/" . $input->urlSegmentStr(); $http = new WireHttp(); // Set a high timeout, to deal with a slow server $http->setTimeout($timeout); // Get the HTTP status of the page, to make sure it exists in the first place $status = $http->status($url); // If the page exists, or possibly redirects to valid content if ($status >= 200 && $status < 400) { $result = false; $attempt = 0; // If the result isn't a string, something went wrong while(gettype($result) !== "string" && $attempt++ < $maxAttempts) { $result = $http->get($url); if ($attempt > 1) wire()->log->message("Loading content at $url, attempt $attempt: " . gettype($result)); } // Double check if the data is a string.. if (gettype($result) === "string"){ // .. And check if it can be decoded, if so: return the data and thus cache it if (json_decode($result) !== NULL) return $result; // If it cannot be decoded: throw exception (don't cache it) throw new WireException("Found the data at $url, but it could not be decoded. Please check your API output!"); } // Throw exception if data could not be loaded in time (don't cache it) throw new WireException("Found the data at $url, but could not load it in time, after $attempt attempts. Result has type: " . gettype($result)); } // Throw generic exception if the requested page was not found or there was another error throw new WireException("Failed to load the content at: $url, with HTTP status: " . $status);1 point
-
Maybe OT: I have been thinking of using Dart or TypeScript to write my JS for me ?. Vanilla JS can be a pain at times. Using Dart or TypeScript, I can write in familiar OOP style (yes, I know about ES6, but that's another story) and have them transpile the code into JS. For small projects it's probably not worth the hassle, but the strongly typed nature of Dart or TypeScript alone is compelling reason enough to steer away from vanilla JS if I can. OK, I'll now crawl back under my rock...?1 point
-
Hi @franciccio-ITALIANO, Try this great module. http://modules.processwire.com/modules/markup-sitemap/ Gideon P.S. Oops. 1 minute late....1 point
-
I tested your setup in a VM but with a Linux distribution instead of a Windows and as a result , ProcessWire run smoothly on it, even the default search feature. I will install a Windows server today just to see if there is an extension which could mess the setup. Stay tuned..1 point
-
Hey, Launched a site today with a form that sends attachments and it turned out that our production server doesn't have mime_content_type() ? https://github.com/chriswthomson/WireMailMailgun/pull/17 I've added a private method getMimeType() which checks first for mime_content_type(), then finfo_open(), then falls back to inferring based on file extension if neither exist. This is based on https://www.php.net/manual/en/function.mime-content-type.php#87856 and https://gist.github.com/Erutan409/8e774dfb2b343fe78b14#file-mimetype-php Also, a WireException is now thrown if an attachment has been added using WireMail::attachment() but curl_file_create() doesn't exist. Cheers, Chris1 point