Leaderboard
Popular Content
Showing content with the highest reputation on 03/21/2015 in all areas
-
Everybody who has import scripts running as a cronjob, there's this effect that the cronjob is run als guest user. So imported pages via API are created and modified by "guest". This is not nice and can lead to confusion. "What?! How can a guest create this page?" To avoid this and set the current user via API you can do this at the beginning after bootstrapping PW: include_once("./index.php"); /** * Overwrite static user for imports. All created pages will now * have created and modified user set to "importer" PW user. * Otherwise API created pages will have the created user "guest" * ------------------------------------------------------------------------------------- */ $importerUser = wire("users")->get("importer"); if($importerUser->id) wire()->setFuel("user", $importerUser, $lock = true); Only thing is you have to create a new superuser with the name you wish to use for such scripts and replace the name in the script. Now if you run this script no matter from where or with what current user you'll have "importer" as the created and modified user. ----- Note: There's a new way to set system vars like $user via wire(name, value), but this doesn't seem to work in this case in my tests. Cause the user will get overwritten again when creating a page by the current user calling the script. I'm not sure it's a bug or what, so it might be possible in future to use the shorter version of wire()->setFuel(name, value).3 points
-
3 points
-
This module does provide two different added functionalities to FormBuilder. 1. The module does allow users to set default "From" email addresses for emails send to administrators. There's a global address, which is set in the modules settings, and a additional field in the settings for "Send an email to administrator(s)", where one can set a form specific emailaddress to override the global one. Both of those are overridden if you chose to use the "Email from field" setting and the returned value is not blank. 2. The module does add an additional syntax for the textfield where administrator emails are set. If you have a pagefield in your form, where one can choose from the potential users, that should be emailed about your form submission, you don't need to write extensive conditional lines like this: personInCharge=SomeUser?someuser@example.com personInCharge=AnotherUser?anotheruser@example.com You can simply add a email field to the template of those users and use the email provided there. !personInCharge?email The syntax says get the user(s) from the field "personInCharge" and send email(s) to the addresses provided by the "email" field of the selected page. https://github.com/LostKobrakai/FormBuilderEmailExtentions Thanks to madeprojects.com for letting me share this. They'll pay the time I spend to build it.2 points
-
I just had to do a site-wide replacement on a word this morning, so this may be of use to others in a similar situation (in my case a product name had to have a capital letter in the middle instead of lowercase). Stick at the top of your homepage template and be careful with this - always take a database backup before playing with anything that's potentially destructive. function searchReplace($page) { foreach ($page->children('include=all') as $child) { // Skip admin page if ($child->id != 2) { foreach ($child->template->fields as $field) { $child->{$field} = str_replace('search_word', 'replacement_word', $child->{$field}); } foreach ($child->children as $grandchild) { searchReplace($grandchild); } $child->setOutputFormatting(false); $child->save(); } } } searchReplace($pages->get('/'); exit; It essentially iterates every page under the homepage, goes through every field and replaces the search term with the replacement. It is case sensitive too. Comment out the code when you are done and see the changes live on your site. This might be a nice one for a quick module that only targets things like text, textarea and image/file descriptions as that's pretty much the only fieldtypes that are relevant I think. Settings could be added to skip certain pages (and therefore their children) entirely, but I don't have time for building a module at the moment.2 points
-
2 points
-
If you are using the great PagePathHistory module in core, this one might be helpful: Page Path History Manager https://github.com/boundaryfunctions/PagePathHistoryManager General This modules allows you to easily manage past page URLs tracked with the PagePathHistory module. It extends the settings tab on the page edit form in the backend and allows you to: view past URLs of the current page and parent pages, delete past URLs, and create new fallback URLs. How to use Use the form in the settings tab on the page edit form of every page in admin to view and manipulate past URLs. See Screenshots to get a better idea of what you can do. Installation Install the module PagePathHistory from within the Processwire admin. PagePathHistory is included in core but not installed by default. Grab the module from its Github repository. Install this module from within the Processwire admin or copy the file content to/site/modules/PagePathHistoryManager. In Admin, click Modules → Check for new modules to refresh module directory. Afterwards install the newly registered module PagePathHistoryManager. You can now manage past URLs from within the settings tab when editing any page. Screenshots Notes This module doesn't install or require PagePathHistory because I'm currently working with a fork of it that is language sensitive. I'll try to publish this one here as well, but I'm not done with final testing. Links You can grab this Module from Github: Source Releases Download latest release I would be glad if some of you could give this module a quick test drive and comment with some feedback here.1 point
-
This is a very simple way to display some instructions to the admin users. Before starting, you need to write some docs; they can be a hidden branch of your page tree, using basic-page, or a different template of your choosing. You should make each subject it's own page under the docs so you can output each one under an accordion trigger. Required Module: Admin Custom Pages 1.) Follow all instructions to install the module; Also add the ACP_scripts_and_styles field to the admin template. 2.) Make a new page under admin, called Docs or whatever; assign the process as described in the module instructions. 3.) Make a template in your themes directory to generate the output of the docs page. 4.) Select that template from the page select in the admin custom page you created. 5.) also make a folder to keep your admin custom pages scripts and styles; 6.) create a css file to use for the display output and some basic styles (like ol, ul li etc..) 7.) Add the custom css file to your ACP_scripts_and_styles field. You can use any output you want, but i'm using a nested accordion, which is provided here: http://tympanus.net/codrops/2013/03/29/nested-accordion/ this is the content of the admin custom page: <?php $docs = $pages->get(4259); ?> <div id="docs"> <ul id="cbp-ntaccordion" class="cbp-ntaccordion"> <?php foreach($docs->children as $doc) { ?> <li> <h3 class="cbp-nttrigger"><?php echo $doc->title ?></h3> <div class="cbp-ntcontent"> <?php echo $doc->body;?> </div> </li> <?php } ?> </ul> </div> <script src="<?php echo $config->urls->templates ?>_admin_custom/js/jquery.cbpNTAccordion.min.js"></script> <script> $( function() { $( '#cbp-ntaccordion' ).cbpNTAccordion(); } ); </script> you'll also want to add the provided css, js and fonts that come with the Nested Accordion; in the css file you'll need to point the fonts to the actual font directory, for example: /site/templates/_admin_custom/fonts/icomoon_arrows/icomoon.eot it should come out looking something like this: *if you are using Reno theme, you can customize the icon, like for example fa-book, which is used in this example: -- Thanks & Credits to Diogo for originally creating the ACP module, and for Nico for getting it to work with the new admin theme system...1 point
-
Gave my first client training yesterday on using ProcessWire. I've built approx 7 sites so far in PW but this was the first scenario where I was handing off to a client and training them in. It was interesting to see where the client had issues and where they had praise. Their site had previously been running on a different CMS so they were familiar with the general workings but also had a lot of expectations on how the CMS would work. Positives Overall the feedback was extremely positive. Here's just a couple I recall They also loved the simplicity of the Add New button when I had mapped it to creating various pages etc Negatives In truth there was no 'negative' feedback as such. A few misunderstandings about the UI as follows 1. There were some issues dragging images onto the image drop zone. It just wasn't clear where client should release the image. I think this area could be cleaned up a bit? 2. When browsing the tree, the client would sometimes repeatedly click a page title instead of the 'edit' link to the right of the page title. 3. When they clicked 'View' or the Home icon on the top menu (Reno Theme) the site would load in the same browser window and sometimes they would loose changes. Personally, I've always thought these 'View' links should open a new tab and have found them annoying. 4. Found the new image crop UI confusing. I've gotten used to it but i'm not new to image management. Possibly the only time training came to a dead stop and we had to rewind a bit. That's it really. Will write a proper blog post about this soon with more detail.1 point
-
Get it from GitHub Setup Just put the module in you modules directory and install it via admin. Intro This module might come in handy if you like to keep your templates clean and free of unreadable and unmaintainable string concatenations and even free of any logic. It also comes with some handy features besides just embedding JS, CSS and image assets, see below. Yikes! <link href="<?php echo $config->urls->templates . 'styles/foo.css'; ?>"> <link href="<?php echo $config->urls->templates . 'styles/bar.css'; ?>"> <script src="<?php echo $config->urls->templates . 'scripts/foo.js'; ?>"></script> <script src="<?php echo $config->urls->templates . 'scripts/bar.js'; ?>"></script> <img src="<?php echo $config->urls->templates . 'images/sky-scraper.jpg'; ?>" alt="Some huge building"> <img src="<?php echo $config->urls->templates . 'images/owzim.jpg'; ?>" alt="Handsome!"> Way cleaner <?php echo $asset->css('foo'); ?> <?php echo $asset->js('foo'); ?> <?php echo $asset->img('sky-scraper.jpg', 'Some huge building'); ?> or with short syntax <?= $asset->css('bar') ?> <?= $asset->js('bar') ?> <?= $asset->img('owzim.jpg', 'Handsome!') ?> And prettier if you're using Twig {{ asset.css('foo') }} {{ asset.css('bar') }} {{ asset.js('foo') }} {{ asset.js('bar') }} {{ asset.img('sky-scraper.jpg', 'Some huge building') }} {{ asset.img('owzim.jpg', 'Handsome!') }} Usage JS example Let's use the js method an its configuration as an example, and assume we have the following files located in /site/templates/scripts - index.js - index.min.js - main.js $config->blick = array( 'jsPath' => $config->paths->templates . 'scripts', 'jsUrl' => $config->urls->templates . 'scripts', 'jsMarkup' => '<script src="{url}"></script>', 'jsDefault' => 'markup', 'jsVersioning' => true, 'jsVersioningFormat' => '?v={version}', 'jsMin' => true, 'jsMinFormat' => "{file}.min.{ext}", ); $asset = $modules->get('Blick'); $asset->js('index')->url; // returns /site/templates/scripts/index.min.js?v=1426170460935 // 'min' and version parameter added, which was fetched from the file modified date $asset->js('main')->url; // returns /site/templates/scripts/main.js?v=1426170460935 // without 'min', because there is no main.min.js $asset->js('main'); // returns <script src="/site/templates/scripts/main.js"></script> // because 'jsDefault' is set to 'markup' // you can also access it explicitly via $asset->js('main')->markup $asset->js('http://code.jquery.com/jquery-2.1.3.js'); // returns <script src="http://code.jquery.com/jquery-2.1.3.js"></script> // nothing is modified here, because it's a remote url You can use the file name with or without extension. Adding a version parameter only takes place, if jsVersioning is set to true, it's a local file and it exists. Modifying the file name to include min only takes place, if jsMin is set to true, it's a local file and it exists. The same applies for the $asset->css('file') method: $config->blick = array( 'cssPath' => $config->paths->templates . 'styles', 'cssUrl' => $config->urls->templates . 'styles', // and so on ... ); IMG example the img method lets you include images, crop and resize them, without them having to be a page image. $config->blick = array( 'imgPath' => $config->paths->templates . 'images', 'imgUrl' => $config->urls->templates . 'images', 'imgMarkup' => '<img {attrs} src="{url}" alt="{0}">', 'imgDefault' => 'markup', 'imgVariationSubDir' => 'variations', ); $asset = $modules->get('Blick'); $asset->img('sky-scraper.jpg')->url; // returns /site/templates/images/sky-scraper.jpg $asset->img('sky-scraper.jpg', 'Some huge building'); // returns <img src="/site/templates/images/sky-scraper.jpg" alt="Some huge building"> // any arguments following the filename are passed as an array // in this case the alt value is the 0th argument, so {0} get's replaced // you can set as many arguments as you want in 'imgMarkup' $asset->img('sky-scraper.jpg')->size(100, 100)->url; // returns /site/templates/images/variations/sky-scraper.100x100.jpg // the resized image is put into a subdir 'variations' as configured in 'imgVariationSubDir' // if 'imgVariationSubDir' is left empty, the variation will be put in the same directory $asset->img('sky-scraper.jpg', 'Some huge building')->attr('title', 'Some huge building'); // returns <img title="Some huge building" src="/site/templates/images/sky-scraper.jpg" alt="Some huge building"> // the resized image is put into a subdir 'variations' as configured in 'imgVariationSubDir' // if 'imgVariationSubDir' is left empty, the variation will be put in the same directory You can also setup predefined variation settings in imgVariations $config->blick = array( 'imgVariations' => array( 'header' => array( 'width' => 960, 'height' => 360, 'options' => array( 'suffix' => 'header', ), ), 'person' => array( // and so on ... ), ), ); And call it like so: $asset->img('sky-scraper.jpg')->variant('header')->url; // returns /site/templates/images/variations/sky-scraper.960x360-header.jpg $asset->img('sky-scraper.jpg')->variant('header', 50)->url; // returns /site/templates/images/variations/sky-scraper.480x180-header.jpg Attributes example Since version 0.4.0 you don't need to create arbitrary variable placeholders, if you want to use attributes only. Now you can use the {attrs} placeholder and set the attributes via $asset->attr('name', 'value'). The name argument can also be multiple names, split by a pipe |. $config->blick = array( // ... 'imgMarkup' => '<img {attrs} src="{url}">', // ... ); $asset->img('sky-scraper.jpg')->attr('alt|title', 'Some huge building'); // returns <img alt="Some huge building" title="Some huge building" src="/site/templates/images/sky-scraper.jpg" > Using files that are not in the configured directory If you want to include files, that are neither in the configured directory nor in one of its sub directores, just use an absolute path (actually, relative to your /site directory. $asset->js($config->urls->SomeModule . 'scripts/file-in-root'); Autoload the module If you don't want to include the module manually via $assets = $modules->get('Blick'); you can set it to be autoloaded under a custom name: $config->blick['autoloadAs'] = 'fiddle'; Now it becomes automatically available in your templates under the name fiddle $fiddle->css('foo'); $fiddle->js('foo'); $fiddle->img('baz.png', 'qux'); Please note, that, if you're using the TemplateTwigReplace.module you will have to add your chosen autoload name to the Auto-import fuel list on the module's config page. See config-example.php for all configurable settings. Change Log 0.5.0 add optional scale argument to variant-method: $asset->img('foo.jpg')->variant('header', 50) 0.4.0 add possibility to get/set and render attributes (see section Attributes example) 0.3.0 add $asset->variant('name') alias for $asset->getVariation('name') 0.2.0 fixes and internal refactorings 0.1.0 initial version1 point
-
There's another method to be able to overwrite created user directly when creating a page. There's a new template setting to allow overwriting the $page->createdUser that you can enable to allow this via API. Then you can do this: $p = new Page(); $p->template = "basic-page"; $p->set("createdUser", wire("users")->get("importer")); $p->title = "Imported page"; $p->save();1 point
-
I forked the original module and use this fork for a project in development already. In my opinion it would be much more useful if merged into core, so I opened a pull request for it. You can assess the patch on Github, or you can test it using this temporary standalone module version (not to be used in conjunction with the core PagePathHistory module but as an alternative to it). The Page Path History manager module might be helpful in evaluating it. As always, I'd be grateful for any feedback.1 point
-
Thanks a lot for your comments. Looking at the code of Process::___installPage() showed that there currently is no possibility to set the page status using the descriptive way to set up a page. Thanks anyway, knowing about this will come in handy soon enough, really saves some repetitious copy-paste work. I already though about this myself but shirked from the duty of implementing it for the first release. But you're absolutely right, sooner or later this will be needed, so thanks for pointing it out. I've already added an issue for this feature and will implement it during the next days. There's one other thing that has been corrected in the current development version of the module and this is proper handling of URLs with non name-format characters (all characters but -_.a-zA-Z0-9/~), i.e. to redirect content from a legacy website. Due to the way Processwire currently handles these URLs, you will have to edit youR .htaccess file to enable this functionality. I added a short description of what has to be done to the module's README and issued a pull request on core to make the need for manual modifications obsolete in the future – let's see how this turns out.1 point
-
In backend it works cause there's no outputformatting. Doing in a template you see the error cause front end template context has output formatting enabled. Not sure if pagetable causes issues with clone but can't remember if Ryan said something. So the solution is right there explained in the error if you read it! Try a $pages->setOutputFormatting(false) before your code.1 point
-
You won't be redirected just like that. You know that Ryan wouldn't do something like that to us, remember, you're still in full control Now you have to use the available methods to take people to the correct url. My favourite is implementing a simple language switch, since I personally hate to be redirected to my browser's language without being asked. You would use $page->localUrl($language) for this. Check how to do it here https://processwire.com/api/multi-language-support/multi-language-urls/ I usually do something as simple as this: foreach($languages as $lang) { $active = $user->language===$lang ? 'class="active"':''; echo "<li {$active}><a href='{$page->localUrl($lang)}'>{$lang->title}</a></li>"; } -- For serving the language based on the browser language, you don't even need the language urls —and since I've never done it, I may be giving you a wrong info— Just detect the browser language http://www.paulund.co.uk/auto-detect-browser-language-in-php and switch the user language accordingly with: $user->language = $language; Of course, if you prefer, set up the URLs and make the redirect instead.1 point
-
Not sure about elastic search, but this module (http://modules.processwire.com/modules/indexer/) allows you to index content inside doc and pdf files. Does that help at all?1 point
-
Hey Pete - nice one! I know your code is meant as a quick snippet to get the job done, so no offense intended, but the concerns I have with this is: On a site with a LOT of pages, that could be very slow. I don't like the fact that it re-saves every page, regardless of whether there is a change or not, which will affect the modified date and modified user. I have actually already made a start on a feature rich search and replace module which I will get around to finishing up sometime soon. It provides the ability for searching and then showing the search term in context for each match. You can then choose which matches get replaced, or replace all. Stay tuned!1 point
-
Just adding this for completeness in relation to my post above...I went ahead and finished the Menu Builder module.1 point
-
This is a nice and much needed thread, however it would be great if each idea, complaint, feature or UI request referenced a Github Issue or another thread within the forum. To me, that would ensure that these important concerns were/are being addressed.1 point
-
Update: Menu Builder Version 0.0.2 is now available. I'll update the original post later + post a new video. Main Changes: Beta status Menus stored as pages (note: just the menu, not the items!) Menu items stored as JSON in a field in the menu pages (empty values not stored) Add menu items from ProcessWire pages using page fields (option to choose between PageAutocomplete and AsmSelect [default]) or a Selector (e.g. template=basic-page, limit-20). For page fields, you can specify a selector to return only those specified pages for selection in the page field (i.e. asm and autocomplete) For page fields, now you can also add css classes and IDs as you add the items Menu settings for nestedSortable - e.g. maxLevels (limit nesting levels) Advanced features (e.g. add pages via selector, menu settings) currently permissible to superadmins only (may change to be permission-based) Delete single or all menu items without deleting the menu itself Lock down menus for editing Highly configurable MarkupMenuBuilder - e.g. can pass menu id, title, name or array to render(); Passing an array means you can conditionally manipulate it before rendering, e.g. make certain menu branches visible only to certain users [untested and the code is up to you!] More... Note: Some nestedSortable features not yet implemented/working (some are not really necessary actually). The module creates 3 fields (menu_items, menu_pages, menu_settings) and 1 template (menus). Menu pages are stored as children under the modules parent page (admin/setup/menu-builder/) - so not accessible in the frontend Issues: Drag and drop (ordering menu items) is some times finicky...something in the js I think or just my mouse.1 point
-
Great, thanks. I used explode to get the individual words from the search query and then a foreach to build the selector. $selector = ''; if($input->get->general_search) { $value = $sanitizer->selectorValue($input->get->general_search); $terms = explode(" ", $value); foreach($terms as $term) { $selector .= "title|author|source|keywords|bibliography_type%=$term, "; } $input->whitelist('general_search', $value); }1 point
-
Hi all, http://axisanimation.com http://axis-vfx.com http://flauntproductions.com I've added these to the directory but you might like to check some of the more interesting details written up in a blog post here - http://newnow.co/blog/the-4k-website/ They use: Modified multisite module to mix shared and site-specific content in one instance Modified thumbnail inputfield for cropping Custom inputfield to retrieve video details from Vimeo API Form builder module They are responsive from mobile to 4K, built on Zurb Foundation, and use the new picture element in conjunction with Processwire to serve images at the most appropriate size, and double size for higher pixel density displays. Wouldn't have been possible without the great forum content and documentation so thanks to everyone in the community! Crawford. New Now Ltd. http://newnow.co1 point
-
As a speaker of English as a second language, I really notice this quirky error. I notice it a lot in this community, in the blogs and forum entries, but also on official pages (the latest: The PW Directory, front and centre). "its" means the thing belongs to the thing. "it's" means "it is". The simplest test would be: assertTrue( "it is" == meaning_of( $phrase ) ); IOW, if you can write "it is" right there, it's OK to write "it's". Otherwise, always always write "its". Sorta grumpy today.1 point
-
Hey everybody, Many of us know about isit.pw, the web site that checks if you are running PW. I thought I should find out how it knows whether a web site is ProcessWire-powered. Turns out, it sends a "GET /?it=/trash/ HTTP/1.0" request, and if the response is 200, then PW it is. Next thing I did was to go to admin templates and change the default behavior such that ProcessWire would through back a 404 instead of offering to log in. Now, isit.pw does not like me for "not running" ProcessWire. However, I liked the method isit.pw uses. It can be handy if you want to run a quick check like this: http://<...>/<some_page_name/?it=/ If you get the Home page, it means you've hit a ProcessWire-powered web site. Have a good Friday and a nice week-end1 point
-
I've posted here and created an issue on Github but not received a reply to either. If my question is lacking some information, please let me know.1 point
-
Almost. There's also an additional check to see if the returned page contains certain traces of ProcessWire. Simply checking the return code wouldn't be enough here For the record, isit.pw includes roughly a dozen methods for checking if a site is running ProcessWire. In many (most) cases it can still identify your site, even if that one check fails. I should probably mention that isit.pw (which is my project) is both a functional tool (as Antti explained earlier) and an experiment; "can you properly identify a site running ProcessWire or not?" I'm also planning to add an info section later, including details on hiding your ProcessWire-ness from humans and services like isit.pw equally1 point
-
> We use a user interface here for exactly what a user interface is meant for. Agree - however... > I would consider myself very lazy and remiss in my responsibilities if I expected people to use text files (YAML or otherwise) as the primarily method of configuratio I don't think anyone has proposed or suggested that? We're proposing a supplement/alternative, not a replacement. At least I would never suggest that, and I don't think that's what rajo was trying to imply. Ryan, do you have any thoughts on what I mentioned a couple of times earlier - changing the API internally to use a command pattern for changes to the data model? If every change to the data-model had to be submitted to a command processor in the form of an object, and those objects could be serialized, and assuming the command processor was hookable, that would make it trivial to implement all kinds of synchronization / change management / logging / recording modules. The problem with manipulating schema directly, is you can't only tell whether something changed, not how it changed or why - you are already working around this fact by introducing things like change-tracking internally in the objects, which need to know what changes were made. For example, when a field gets renamed, there are methods to capture that change and work around it's side-effects. When dealing with schema, I find it safer to have a centralized facility through which detailed records of change pass through - rather than manipulating individual aspects of the schema independently here and there. Template changes and Field changes, for example, are closely related because they are components of the same schema model - yet these changes are completely unrelated at the API level. A command facility could provide a central API point where all schema-related changes would be exposed, even future (and even third-party) changes would pass through it, so for example a synchronization module could work with future/third-party extensions to the data-model...1 point
-
When the cache is fully populated, you could do this. You could literally take everything in the /site/assets/ProCache/ dir, move it to the root on another web server and it would function statically. You would also need to have your other static assets copied over too, which I think would be limited to these dirs: /site/assets/files/* /site/assets/templates/styles/* /site/assets/templates/scripts/*1 point