Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 12/14/2018 in all areas

  1. Last week's version 3.0.121 was the first release candidate for our next master version. Several issue reports were covered this week for minor things, and they are all included in this week's dev branch version 3.0.122. Please consider this version the RC2 (release candidate 2) for our next master. There's nothing major to report, but if you'd like to see the list of changes relative to last week's version, please see the dev branch commit log at: https://github.com/processwire/processwire/commits/dev If you have a chance, please upgrade to version 3.0.122 and let us know if you run into any issues. Thus far things are going smoothly and it seems like we are very close to the next master version, perhaps as soon as next week. Since I don't have much more to report than the above, we'll skip doing a blog post this week. But after last week's post, a couple of people asked me about ProMailer (as mentioned, which we use for the weekly email distribution), so I'll be sure to write more on that soon. Attached is a screenshot from the message editor screen that reveals several aspects of the message sending part at least. Thanks for reading and I hope that you all have a great weekend!
    11 points
  2. Hello Everyone! I'm new here, just signed up. I've discovered PW few days ago (what a shame...) and I'm angry for myself that I lost several years of my life... I'm a homegrown webdeveloper since 2005, started from pure HTML, then e107, Textpattern and from 2008 I work(ed) only with WordPress. I've made over a hundred of sites. Most of them are simple blogs but my main site is quite large (with over a 10k entries and over 100k of media). It's outdated a little bit so I was planning to modify and refresh it lately but then... Gutenberg happened. Gutenberg as an editor is unintuitive, buggy, produces massive problems and it's incompatibile with most of the things I'm using (it seems to be the same story for hundreds of websites built on WP). And though the whole WP community is frustrated and angry, it's been forced with WP 5.0 as the beginning of rebuilding WP as a platform into... hmm... next Wix? I was trying to discuss - my comments were deleted and my account has been blocked (as many others). After 8 years of developing WP... Well... I've frozen the site for updates and started looking elswhere. I have few advanced demands so tried Drupal, then played a little with Craft, Codeigniter and Laravel (I'm not a programmer per se). And after few recommendations I've finally found You. Guys... I'm so thrilled and emotional. I can't stop reading and following tutorials on localhost. PW is THE TOOL I was searching my whole life! I'm going to study everything very carefully and next year I'm going to rebuild slowly (there's no rush) my main site with PW. Back to Gutenberg: I understand where it aims to be and what it tries to accomplish BUT this is wrong on so many levels. As far as I can see, a barebone PW installation is far more flexible and useful then WP with 30 plugins. And obviously you know it perfectly. So I'm begging you: no Gutenberg here... ? Cheers to Ryan and Everyone! Greetings from Poland!
    8 points
  3. Not sure where I originally saw it while lurking around the forums, but someone, somewhere at some time was asking about styling Uikit checkboxes as toggle-style switches, much like the ones at the bottom of this post asking me if I want to be notified of replies. So here is my humble offering, rough and ready, which can be thrown in at the bottom of your Uikit css as a starting point. Everything is based on ems and rems, so you can increase size as you desire by altering the single instance of font-size. It only targets single instances of labels within a specific field to a) try to limit unintended consequences and b) because in those cases it often seems more user-friendly to have an on/off binary switch rather than a checkbox. It's still totally a checkbox, just styled differently. .uk-form-controls-text label:only-of-type input.uk-checkbox { font-size:.8rem; margin-top:0; position:relative; -webkit-appearance:none; outline:none; width:4em; height:2.4em; border:2px solid #D6D6D6; border-radius: 3em; box-shadow:inset 5em 0 0 0 #DDD; flex-shrink: 0; } .uk-form-controls-text label:only-of-type input.uk-checkbox:after { content:""; position:absolute; top:.25em; left:.25em; background:#FFF; width:1.6em; height:1.6em; border-radius:50%; transition:all 250ms ease 20ms; box-shadow:.05em .25em .5em rgba(0,0,0,0.2); } .uk-form-controls-text label:only-of-type input.uk-checkbox:checked { background-color: transparent; box-shadow:inset 5em 0 0 0 #4ed164; border-color:#67bba5; } .uk-form-controls-text label:only-of-type input.uk-checkbox:checked:after { left:1.85em; box-shadow:0 0 1em rgba(0,0,0,0.2); } label:only-of-type input.uk-checkbox:checked + span { color:#008a00; transition:all 250ms ease 20ms; } .InputfieldCheckbox .InputfieldContent label:only-of-type {display:flex;} label:only-of-type input.uk-checkbox + span { color:#c3c3c3; display:flex; align-items:center; line-height:1.1; } /* Below is only necessary if you want the optional "tick" after items when selected */ label:only-of-type input.uk-checkbox + span:after { flex-shrink:0; margin-left:.5em;width:2em; opacity:0; content:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 250 250'%3E%3Ccircle cx='125' cy='125' r='125' fill='%23231F20' opacity='.1'/%3E%3Cpath fill='%230B8B44' d='M95.823 139.432l-32.492-32.56-31.872 31.883-.008-.008 63.72 63.732L218.549 79.116 187.494 47.52z'/%3E%3C/svg%3E"); } label:only-of-type input.uk-checkbox:checked + span:after { opacity:1; transition: opacity 250ms ease 150ms; }
    4 points
  4. Or just put that in the settings: { "files.associations": { "*.module": "php" } }
    2 points
  5. It's working for me using the code from your first post. ProcessGoodNews.zip If this module you're working on is going to be freely shared with community when finished then maybe it would be good to put your code into a public GitHub repo now so people can see the code and help you with problems that come up as you are developing it.
    2 points
  6. @bernhard @LostKobrakai Just adding my two cents here ... I think if we're talking about writing site-specific modules or code, both options are equally valid and it comes down to preference. I try to write my site-specific functionality in general classes (not extending the Module class) and wire them up in my templates; in this case, it's just less work to connect the namespace through composer than to set up a module and add the namespace manually through the classloader. But really, for code that won't be used anywhere else it doesn't really matter. For reusable code or shareable modules I guess it depends on how closely it integrates with ProcessWire; i.e. my Textformatter module is built as a Processwire module, since it can't be used outside of Processwire anyway. But I'm also working on a collection of utility classes for my personal workflows (based on my markup generation tutorials), and most of those could be used in another context, so in this case I'm building it as a normal composer package, not as a ProcessWire module. One usecase for the Composer autoloader for me is this module: It's not available on any public repository or the module directory, but I can still manually clone it into my project from my private repo and just connect the namespace through Composer. In this case it would definitely be more work to write a wrapper module around it, so for that it's a useful technique. Thanks @horst, no idea why that never crossed my mind ? It's much better indeed, I've edited the tutorial accordingly! I don't think that will work in this specific setup though, since the custom installer mentioned in that blogpost just returns "site/modules/..." as the install path, which isn't correct if your composer.json lives one directory above. Though it would be trivial to fork it and just add the public/ part there ...
    2 points
  7. Minor, but useful update just committed. I noticed that the Console panel didn't have access to custom properties/methods added via hooks in other modules if they were added in ready() vs init(). For example, in the MarkupSEO module when trying to do this, I got null returned. d($page->seo); Anyway, this now works as expected and returns the "seo" property object. Hopefully you guys will find it useful also. If you grab the latest fork of the MarkupSEO module (https://github.com/adrianbj/MarkupSEO/tree/various-fixes-enhancements) you'll also be able to make that call in the Console panel when editing a page in the backend as well as the frontend page view.
    2 points
  8. It looks like Safari has a problem with the ui-helper-clearfix class. If you remove it the layout looks ok.
    2 points
  9. For composer itself: interoperability and a far bigger ecosystem. For wrapping packages into pw modules: Please don't wrap packages for the sake of wrapping them. It's useful if you provide additional features like configuration through the modules or deeper integration in processwire classes, but that's work and needs to be maintained on top of the package by itself. The only backdraw a plain composer package has on top of a pw module without additional features, is that it can't be installed via the backend, but you need to use the composer cli (and that's more a restriction of composer than of pw). The same is actually also true for the few pw modules which install composer packages. Another problem of wrapping packages is that you cannot get updates without the wrapping module being updated. There is also lot's of tooling like checking for security issues around composer. For anyone not just doing php as a hobby I don't see a reason not to use composer just like nobody uses javascript without npm anymore for any serious work.
    2 points
  10. @MoritzLost regarding earliest include of the autoloader, I think the site config.php is the right place. It is parsed / executed before modules, but it get not overwritten with core updates. ?
    2 points
  11. 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
  12. AdminOnSteroids has a nice feature to make pages stick to the top of the page tree. Is there an easy way to do the opposite—make a page stick to the bottom of the page tree? What I’d like to use it for: Usually I have a test page in my PW setup. This is handy because the main content of a page is often created using a Repeater Matrix field. If I add a new type to this field, I can test it on the test page (which usually uses the basic page template). In the page tree, I usually position this test page as the last page before the 404 page. 404 page, the admin section and trash are always at the bottom of the fist level of the page tree. I’d like to see my test page work the same: It should be positioned before the 404 page. And when I add a new page directly under home (with the first level of the page tree being manually sortable), I’d like the new page to be inserted just before my test page instead of just before the 404 page.
    1 point
  13. Hi @bernhard! Gutenberg in Wordpress is a dual misconception: Wordpress is known as a blog platform. Yes, you can extend it massively and use it for many different projects but in the end it's mostly about operating with text. It's usually enriched with images and embeds but it's still an article, news, etc. So many authors for so many years just copied and pasted their texts, added few media and with 2-3 clicks published it. Now, doing this simple task with Gutenberg is insanely uneffective: instead one simple menu in editor there are several (hidden) menus everywhere (in every block). And EVERYTHING is a block now - a title, a paragraph, an image, a quote and so on (imagine the amount of additional code it generates!). You have to do absurdly much more things to get the same result and you have to spend much more time to do the simplest task. So maybe Gutenberg is for designers rather? If it's true and if this was the idea (to simplify building content) - there are so many so much better WP site builders and themes (to do so) FOR YEARS! Anybody who wants a one-page site or portfolio just picks up a theme and few plugins and voila. The core blogging mechanism stays safe and ready when necessary. I can understand that Matt, Automattic and the dev-deciders want to turn with WP elsewhere and change the character/purpose of the platform. Their choice (though the style they're doing that is embarrassing). But cutting out all those (millions?) of websites using WP for TEXT PUBLISHING and trying to convince the whole world that Gutenberg is better tool to write an article than TinyMCE or CKEditor is as funny as idiotic. From practical point of view, Gutenberg is incompatible with so many plugins and themes (used stably for years!) that it broke hundreds (thousands?) of websites. Blank sites, errors, bugs everywhere AND in many cases people have no idea where is a problem and what to fix. At my site (mentioned above) I have 50 plugins. Half of them doesn't work or generates errors with Gutenberg. Just take a look at the reviews of Gutenberg (and their dates!) to catch the disaster happening there. I know perfectly from my own experience how such a "click click drag-and-drop magic" approach can be tempting. Probably even using PW at some point (it's still ahead of me!). But it's the whole different way and phillosophy of creating (fast) content. There are all those Wix, Weebly, Spacesqare and Mobirise builders for that. WordPress as it was thought in the beginning shoudn't go that way (that 30% of web share will fall quickly).
    1 point
  14. I think it's a very specific need. Perhaps you could dig into AdminOnSteroids code (if it helps) and make your own hook to achieve this.
    1 point
  15. If you are developing modules I'd recommend changing .module to .module.php so every ide from every user will recognize it ?
    1 point
  16. Hi Guys Working now for several years with Sublime Text and lately I had made the decision to try out vscode and I must say that it is really cool. Feels really fast like Sumblime Text. I have a question about the code syntax highlighting. How can I say to vscode that it should treat *.module files as *.php files so that syntax highlighting of php is used for Modules? Edit: Nevermind - https://stackoverflow.com/questions/29973619/how-to-make-vs-code-to-treat-other-file-extensions-as-certain-language Kind Regards Orkun
    1 point
  17. I've just stripped out the ":after" declarations nesting them inside their respective selectors ?
    1 point
  18. .uk-form-controls-text label:only-of-type input.uk-checkbox { font-size: .8rem; margin-top: 0; position: relative; -webkit-appearance: none; outline: none; width: 4em; height: 2.4em; border: 2px solid #D6D6D6; border-radius: 3em; box-shadow: inset 5em 0 0 0 #DDD; flex-shrink: 0; &:after { content: ""; position: absolute; top: .25em; left: .25em; background: #FFF; width: 1.6em; height: 1.6em; border-radius: 50%; transition: all 250ms ease 20ms; box-shadow: .05em .25em .5em rgba(0, 0, 0, 0.2); } } .uk-form-controls-text label:only-of-type input.uk-checkbox:checked { background-color: transparent; box-shadow: inset 5em 0 0 0 #4ed164; border-color: #67bba5; &:after { left: 1.85em; box-shadow: 0 0 1em rgba(0, 0, 0, 0.2); } } label:only-of-type input.uk-checkbox:checked+span { color: #008a00; transition: all 250ms ease 20ms; } .InputfieldCheckbox .InputfieldContent label:only-of-type { display: flex; } label:only-of-type input.uk-checkbox+span { color: #c3c3c3; display: flex; align-items: center; line-height: 1.1; }
    1 point
  19. Sorry flydev, not at the moment. I am an old-school, banging-rocks-together, CSS kinda dude, so am not experienced with compilers in general, yet. I get why they are very useful, I just haven't *needed* to use them in the past. It is something I plan to work towards with processwire after many years of static sites.. Using variables are starting to make great sense. It's still very much a work in progress and is not very fancy or tricky, so it should be able to slot in somewhere without much hassle.
    1 point
  20. Inspired by this i whipped up something. class element { protected $element = null; protected $attributes = []; function __construct( string $element ) { $this->element = $element; } public function attribute(string $key, ?string $value = null, ?bool $replace = false) { if ( empty($value) ) return empty( $attributes[$key] ) ? null : $attributes[$key]; if ($replace or empty($attributes[$key])) { $this->attributes[$key] = $value; } else { $this->attributes[$key] .= $value; } return $this; } public function attributes(array $items, ?bool $replace = false) { foreach ($items as $key => $value) { self::attribute($key, $value, $replace); } return $this; } public function class(?string $value = null, ?bool $replace = false) { return self::attribute('class', $value, $replace); } public function id (?string $value = null, ?bool $replace = false) { return self::attribute('id', $value, $replace); } public function content( $content ) { $content = $this->start().$content.$this->end(); return $content; } public function start() { $attribute_string = self::generate($this->attributes, true); $element = $this->element; $content = "<{$element}{$attribute_string}>"; return $content; } public function end() { $element = $this->element; $content = "</{$element}>"; return $content; } public function closing() { $attribute_string = self::generate($this->attributes, true); $element = $this->element; $content = "<{$element}{$attribute_string} />"; return $content; } protected function generate( array $attributes, bool $leading_space = false ): string { $attr_string = ''; foreach ($attributes as $attr => $val) { if (is_bool($val)) { if ($val) { $attr_string .= " $attr"; } } else { $attr_string .= ' ' . $attr . '="' . $val . '"'; } } if (!$leading_space) { $attr_string = ltrim($attr_string, ' '); } return $attr_string; } } function element( string $element ) { return new element( $element ); } I haven't tested it much but should be usable. // example usage -- not tested! $navelement = element('li')->class('navitem'); $navitems = pages('/')->and(pages('/')->children()) echo element('ul')->content( $navitems->each( $navelement->content('{title}') ); // or echo element('ul')->start(); foreach($navitems as $item) { echo $navelement->content($item->title); } echo element('ul')->end();
    1 point
  21. Didn't realise I wouldn't be able to edit the original post with inevitable tweaks and changes. Whoops, sorry about that. Below is an extended version dealing with a few more common admin backend use cases. .uk-form-controls-text label:only-of-type input.uk-checkbox, .Inputfield input[type=checkbox].uk-checkbox { font-size:.8rem; margin-top:0; position:relative; -webkit-appearance:none; outline:none; width:4em; height:2.4em; border:2px solid #D6D6D6; border-radius:3em; box-shadow:inset 5em 0 0 0 #DDD; flex-shrink:0; } p.template-checkboxes input[type=checkbox].uk-checkbox { font-size:.6rem; } .uk-form-controls-text label:only-of-type input.uk-checkbox:after, .Inputfield input[type=checkbox].uk-checkbox:after { content:""; position:absolute; top:.25em; left:.25em; background:#FFF; width:1.6em; height:1.6em; border-radius:50%; transition:all 250ms ease 20ms; box-shadow:.05em .25em .5em rgba(0,0,0,0.2); } .uk-form-controls-text label:only-of-type input.uk-checkbox:checked, .Inputfield input[type=checkbox].uk-checkbox:checked { background-color: transparent; box-shadow:inset 5em 0 0 0 #4ed164; border-color:#67bba5; } .uk-form-controls-text label:only-of-type input.uk-checkbox:checked:after, .Inputfield input[type=checkbox].uk-checkbox:checked:after { left:1.85em; box-shadow:0 0 1em rgba(0,0,0,0.2); } label:only-of-type input.uk-checkbox:checked + span, .Inputfield input[type=checkbox].uk-checkbox:checked + span { color:#008a00; transition:all 250ms ease 20ms; } .InputfieldCheckbox .InputfieldContent label:only-of-type, .InputfieldCheckboxes table label, .uk-form-controls .InputfieldCheckboxes ul li label { display: flex; } label:only-of-type input.uk-checkbox + span, .Inputfield input[type=checkbox].uk-checkbox + span { color: #c3c3c3; display: flex; width: 100%; max-width: 22em; align-items: center; justify-content: space-between; line-height: 1.1; } label:only-of-type input.uk-checkbox + span:after { flex-shrink:0; margin-left:.5em;width:2em; opacity:0; content:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 250 250'%3E%3Ccircle cx='125' cy='125' r='125' fill='%23231F20' opacity='.1'/%3E%3Cpath fill='%230B8B44' d='M95.823 139.432l-32.492-32.56-31.872 31.883-.008-.008 63.72 63.732L218.549 79.116 187.494 47.52z'/%3E%3C/svg%3E"); } label:only-of-type input.uk-checkbox:checked + span:after { opacity:1; transition: opacity 250ms ease 150ms; }
    1 point
  22. This is the way I found that works: 1. Create a new folder in your site Modules folder named Injector ( site/modules/Injector ). 2. Copy / paste the following code into a file named Injector.module.php and put it in your module folder. <?php namespace ProcessWire; class Injector extends Process { public static function getModuleinfo() { return [ 'title' => 'Injector', 'summary' => 'Add content before </head> and before </body>', 'href' => '', 'author' => '', 'version' => '1.0.0', 'singular' => true, 'autoload' => true, ]; } public function init() { // add a hook after each page is rendered and modify the output $this->addHookAfter('Page::render', $this, 'after_render'); } public function after_render($event) { /** @var Page $page */ $page = $event->object; // ignore templates $ignore = array( 'admin' ); if( !in_array( $page->template, $ignore ) ){ $replace =array( '<!--[+head.include+]-->' => ( defined( 'HEAD_INCLUDE' ) ? HEAD_INCLUDE : '' ), '<!--[+body.include+]-->' => ( defined( 'BODY_INCLUDE' ) ? BODY_INCLUDE : '' ) ); $event->return = str_replace( array_keys( $replace ), array_values( $replace ),$event->return ); } } } 4. In your admin, refresh Modules and then install Injector. 5. In your template before the </head> tag, add <!--[+head.include+]-->, also optional add the <!--[+body.include+]--> before the </body> tag. 6. In your script(s) define HEAD_INCLUDE and BODY_INCLUDE ( optional ), ex: $head_include ='<link rel="canonical" href="http://example.com/tags/" />'; define( 'HEAD_INCLUDE', $head_include ); Do the same thing for BODY_INCLUDE if needed. Hope this helps.
    1 point
  23. lol so easy @adrian I missed this feature ? edit-ot: really.. what a crazzy job with tracy...
    1 point
  24. Or change it in the database - via the link to Adminer in the RequestInfo panel in Tracy is a nice shortcut, but however you get there is fine.
    1 point
  25. In admin.php file : /** * Hook : * Add FieldtypeDecimal to compatible fieldtypes of * a FieldtypeFloat when a superuser need to change the type * of a float field. * * https://modules.processwire.com/modules/fieldtype-decimal/ * https://processwire.com/talk/topic/7542-development-fieldtypefloat-fieldtypedecimal/ * */ $wire->addHookAfter('FieldtypeFloat::getCompatibleFieldtypes', function($event) { if(!$this->modules->isInstalled('FieldtypeDecimal') || !$this->user->isSuperuser()) return; $return = $event->return; $return->set('FieldtypeDecimal', $this->modules->get('FieldtypeDecimal')); $event->return = $return; });
    1 point
  26. Though $input seems to be defined, or the echo before attaching the hook would show a NullPage too.
    1 point
  27. $jobID = $wire->input->get->job; More infos : @BitPoet I think he is outside template
    1 point
  28. Any change if you remove the ampersand from your use() statement?
    1 point
  29. @LostKobrakai Thanks for the clarifications! As for the PHP read access, I'm more worried about remote code execution through undiscovered vulnerabilities in external packages (or an attacker gaining write access to a package that gets included through the dependency chain, like we've seen with the event-stream debacle recently). If a PHP file with such a vulnerability lives inside the webroot (especially if it's in a "standard" path like /vendor/vulnerable-package/...), this could give an attacker access to the entire system. Granted, direct access can be blocked in the .htaccess or something like that, but for me it's just one less thing to worry about. Though I'm admittedly a bit paranoid ? ProcessWire's classloader is certainly a good option as well, I just use the composer autoloader because I need to set up Composer anyway for most projects, I guess it comes down to preference. For a shared module or site profile I'd definitely go with the ProcessWire classloader!
    1 point
  30. Just a note here to say that repeater support is now fixed. A big thanks to @PWaddict for help testing these changes.
    1 point
  31. Just to clarify the bit about "putting stuff outside the webroot" for security reasons: This is certainly a nice precaution, but processwire is not using it because there are way to many shared hosters, where it's simply not possible to go outside the webroot. I'd also say that if your webserver is not behaving correctly you've got bigger problems to deal with, so usually just adjusting your .htaccess file should be perfectly fine as well. Especially as your php process still needs to be able to read things even if they're not within the webroot to be able to execute them. There's not really a need for composer for that part as processwire has it's own psr-4 compatible classloader: https://processwire.com/api/ref/class-loader/
    1 point
  32. Hi, I think that you don't need to do that because $page->comments->count return number of comments for page. Some options to sort pages by comments: // example: page template "blog-item" // $pages->find($selector)... // from top by number of comments $selector = 'template=blog-item, sort=-comments.count' // by recent comment $selector = 'template=blog-item, sort=-comments.created' // by upvotes $selector = 'template=blog-item, sort=-comments.upvotes' Or options by downvotes or stars. Also, there are and additions, eg. "AND comments.count > 10" etc... Regards. EDIT: read again your question, and if you have page array (results), than you can try to filter results with this: $my_results->sort("-comments.count");
    1 point
  33. If anybody of you like me totally missed the markdown preview of vscode just click the preview icon on the top right:
    1 point
  34. Can you compare my settings to yours, because in my case it works well. I have my JS custom file located in the folder "ckeditor". Path to the JS-file entered in the input: mystyles:/site/templates/ckeditor/mystyles.js and in the mystyles.js I have fe UIKit styles like these: CKEDITOR.stylesSet.add( 'mystyles', [ { name: 'Inline Code', element: 'code' }, { name: 'Inline Quotation', element: 'q' }, { name: 'Bild links', element: 'img', attributes: { 'class': 'align_left' } }, { name: 'Bild rechts', element: 'img', attributes: { 'class': 'align_right' } }, { name: 'Bild zentriert', element: 'img', attributes: { 'class': 'align_center' } }, { name: 'Small', element: 'small' }, { name: 'Text durchstreichen', element: 'del' }, { name: 'Inserted Text', element: 'ins' }, { name: 'Cited Work', element: 'cite' }, { name: 'Highlight', element: 'mark' }, { name: 'Einfügen', element: 'ins' }, { name: 'Sample', element: 'samp' }, /* Uikit headlines */ { name: 'unterstrichen', element: 'h3', attributes: { 'class': 'uk-heading-divider' } }, { name: 'Linie in der Mitte', element: 'h', attributes: { 'class': 'uk-heading-line' } }, { name: 'Kugel am Anfang', element: 'h', attributes: { 'class': 'uk-heading-bullet' } }, /* Uikit paragraphs */ { name: 'Kleine Schrift', element: 'p', attributes: { 'class': 'uk-text-small' } }, { name: 'Große Schrift', element: 'p', attributes: { 'class': 'uk-text-large' } }, { name: 'Nur Kleinbuchstaben', element: 'p', attributes: { 'class': 'uk-text-lowercase' } }, { name: 'Nur Großbuchstaben', element: 'p', attributes: { 'class': 'uk-text-uppercase' } }, { name: 'Erster Buchstabe groß', element: 'p', attributes: { 'class': 'uk-text-capitalize' } }, { name: 'Farbe: ged&auml;mpft', element: 'p', attributes: { 'class': 'uk-text-muted' } }, { name: 'Farbe: Prim&auml;r', element: 'p', attributes: { 'class': 'uk-text-primary' } }, { name: 'Farbe: Erfolg', element: 'p', attributes: { 'class': 'uk-text-success' } }, { name: 'Farbe: Warnung', element: 'p', attributes: { 'class': 'uk-text-warning' } }, { name: 'Farbe: Gefahr', element: 'p', attributes: { 'class': 'uk-text-danger' } }, /* ul classes */ { name: 'Liste mit Kugel', element: 'ul', attributes: { 'class': 'uk-list uk-list-bullet'}}, { name: 'Liste mit Linie', element: 'ul', attributes: { 'class': 'uk-list uk-list-divide'}} ] ); Here is a screen shot of the custom styles dropdown: So in my case I didnt find it difficult to add styles
    1 point
  35. Just in case you guys haven't come across it, I have been using https://www.gitkraken.com/ but maybe I should give Tower a go one of these days.
    1 point
  36. I use Atlassians' Sourcetree if people wanted an alternative. https://www.sourcetreeapp.com/
    1 point
  37. would be awesome if core natively supported dependent selects in repeaters!
    1 point
  38. Thanks for your solution @Macrura. I found that the reason why dynamic function is not working. This is because the class of the select field are amended by the repeater so the jquery is not able to select the DOM correctly. What we should do is to fix it by targeting the correct DOM by changing the selector. I can get it to work with already saved repeater page but not the newly added one. I think a listener is needed to attach the on change event to newly added repeater item when we press Add New. EDIT: The newly added repeater item surprisingly fires the js again. It is working fine now. A small bug is that the old repeater items will fire more than once if there are more than one newly added item. Below is the amended JS file for InputfieldPage in quick EDIT: The bug is fixed. I have submited a pull request. Hope we could see this feature in the core soon!
    1 point
  39. Why do you want to do this ? Inline css lowers the security and breaks the consistency of the website. In CKEditor you should not go any further as allowing html tags but keep the css inside your templates folder. Anyway: Admin => Setup => Fields => Your field => Input scroll down to Format Tags and add div to it: div;p;h2;h 3;h4;h5;h6;pre;address scroll down to Extra Allowed Content and add wildcards for the <a> and <div> tag: a[*]{*}(*) div[*]{*}(*) Now your <a> and <div> tags won't be stripped off anymore. The CKEditor forced <p> tags are still wrapped around your html tags, this is how you can get rid of them: (body field example) Open config-body.js in your Editor (site\modules\InputfieldCKEditor\config-body.js) and make it look like this, to prevent the forced <p> tags: CKEDITOR.editorConfig = function( config ) { // Define changes to default configuration here. For example: // config.uiColor = '#AADC6E'; config.enterMode = 2; config.shiftenterMode = 1; }; Now you have your html tags free from wrapped <p> tags.
    1 point
×
×
  • Create New...