Leaderboard
Popular Content
Showing content with the highest reputation on 03/17/2015 in all areas
-
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 version6 points
-
As I did a lot of performance optimization stuff for a client's website recently I thought I'll share some of my findings: - optimizing for "time to first byte": Apart from fixing performance issues with your php code there is an easy way to "get things started":Chunk your Output! Doing an ob_flush (or {% flush %} if you're using twig) here and there is an easy way to split your page into chunks that are instantly (and in parallel) served to the client instead of rendering the whole page at once. This is especially handy if you're using the next technique: - Inlining "above the fold" content I must admit that I'm not a big fan of inlining things. In my opinion it's against anything I've learned about keeping things "dry, clean and separated". That's why i refused to do it until now. But if you're using grunt/gulp (and especially criticalcss) you're not doubling anything and the inlining is just another task in your gruntfile. There is a pretty easy step by step guide by Jeremy Keith at https://adactio.com where he explains why inlining css on the first visit will gain your site a massive (perceived) performance boost on the first load (this is especially handy on mobile devices). I'll post a recipe to processwire-recipes.com how to achieve this with processwire in the next days - Avoid loading Webfonts directly but do it asynchronous as "Progressive Enhancement" (+ Store them in localstorage to load them super fast afterwards) to avoid blank pages: http://bdadam.com/blog/loading-webfonts-with-high-performance.html Just implementing these 3 (pretty easy) things made the pagespeed score climb up by 15 points and lowered the perceived loading time by at least 2 seconds below the "critical hurdle" of 1-2 seconds.6 points
-
Getting the different values is easy for the pagefields, as you know all the possible values (the pages). $formats = $pages->find("template=format"); foreach($formats as $format){ $num = $pages->count("template=video, format={$format->id}"); // Count all videos where format is $format if($num) echo $num; } For the other informations I'd suggest going the same way. E.g. for clip length: Add pages to your tree for the different clip length options (5-10, 10-15, …; you don't need the exact values for the count). Add a pagefield to the video's template: "clip_length_option" Use a hook to update this field on page save (example) dependent on the field that holds the real length of a clip. Use mysql to update existing video entries with the new field data (i think that's the fastest way as you're already using mysql). Hope this helps.3 points
-
@bbeer: additionally, if you're using the latest version of Version Control for Text Fields, there's an option in the module settings to *not* remove it's database tables when the module is uninstalled. The purpose of this is to make transition to Version Control easier: it should be able to import old data from Version Control for Text Fields during installation. I've only done limited amount of tests with this feature, though, so I can't 100% guarantee that it will work. It has worked for me so far, but making backup copies of the module's tables might make sense if you're going to try it.3 points
-
I would place one global jquery.min.js at a central place and name it specific to that uploaded files: /unity.jquery.min.js Then I would delete all uploaded jquery.min.js or still would them leave unused. And in the html file I would correct the url to point to the global one: $htmlfilename = 'index.html'; // this need to hold the relative or better the absolute *filesystem path* (not url) to the unity html file $search = './jquery.min.js'; // this is how the jquery.min.js is embedded originally in the html file $replace = '/unity.jquery.min.js'; // this is the absolute URL to the global js file // a very rude method would be to just read the file content, replace the url and write it back into the file in just one line: file_put_contents($htmlfilename, str_replace($search, $replace, file_get_contents($htmlfilename))); . . But instead to do it in one line, you can use this steps one by one and optionally with validation: // fetch the file content $content = file_get_contents($htmlfilename); // optional validation if it has the whole content if (false === $content || strlen($content) != filesize($htmlfilename)) { // uups, we have had a read error ... } // replace the url of jquery.min.js $content2 = str_replace($search, $replace, $content); // optional validation if it exactly one time has changed the url in the content if (strlen($content2) != (strlen($content) - strlen($search) + strlen($replace))) { // uups, an error occured ... } // write it back into the html file $result = file_put_contents($htmlfilename, $content2, LOCK_EX); // optionally check if all data could be written into the file if (false === $result || strlen($content2) != $result) { // uups, we have had a write failure ... } . The validation for str_replace can also be done with an optional fourth parameter: // replace the url of jquery.min.js $replacementCounter = 0; $content = str_replace($search, $replace, $content, $replacementCounter); // optional validation if it exactly one time has changed the url in the content if (1 != $replacementCounter) { // uups, an error occured ... }3 points
-
Just a thought — you could also keep those numbers in dedicated fields in a page and update them every time a video is created or deleted. edit: the famous Eiffel Tower looks unrecognisable in that clip2 points
-
2 points
-
Yipieh! Looks like a task for an importer script! The XML has <DocumentID>123456</DocumentID> what seems to be the boat-article-ids. So, you can go with it manually via importer script, or first have a look for getting a PHP conversion lib that converts xml to csv and then maybe use the CSV module for importing. But it is also very easy done manually with an importer script, (bootstrapping PW, running via cron or via PWs lazyCron). If you need any further explanation, please ask here. EDIT: @Adrian beats me a few seconds2 points
-
Good to know! I think it might be worth you creating a converter that can be run via a cron job. Sorry I don't have time for a detailed example, so this might not be much use, but you can use one of the PHP xml to array (or maybe json) functions and then use the PW API to convert that into pages. It won't be terribly difficult, but not exactly trivial. There are several bits of code that might help you if you decide to tackle this - some from the Wordpress Migrator (xml to json) and Migrator (json to PW pages). If you're willing to have a go, I am sure we can help you get through any roadblocks that come up.2 points
-
Just to make this clear, you want a way to be able to continuously import from that source and not a one-time thing?2 points
-
It is possible to swap the template file on runtime so that a page can have multiple template files. Maybe this is sufficient for you. This is possible with the Module FieldtypeSelectFile. You have to check the checkbox "Change Page Template" in the module settings and select the file to render in a page.2 points
-
I'll try it, but it won't be as efficient as your mysql statement. // This is optional if you know the templates $t = new TemplatesArray(); foreach($templates as $template{ if($template->hasField("myfield")) $t->add($template) } $ps = $pages->find("template=$t"); $list = new PageArray(); foreach($ps as $p){ $list->import($p->get("myfield")); } $list = $list->unique(); $list->explode("name"); Edit: getting the templates could be more efficient like this, but I'm not sure about this. $myfield = $fields->get("myfield"); $fgs = $myfield->getFieldgroups(); $t = new TemplatesArray(); foreach($fgs as $fg){ $t->import($fg->getTemplates()); }2 points
-
You will absolutely love ProcessWire and this feeling you got? You will get that a lot . Just unlearn the illogical of other systems and take the most simple route. The thing with ProcessWire is: don't make it harder than is has to be. Good luck with your project.2 points
-
This is getting cooler and cooler A few more comments / suggestions. In ASM Select mode, everything seems to be working fine, but I am getting this notice: Warning: Invalid argument supplied for foreach() in //site/modules/FieldtypeSelectExtOption/FieldtypeSelectExtOption.module on line 312 You should probable change your DB queries to use PDO and prepared statements. Here is a note from Ryan (https://processwire.com/talk/topic/3768-processwire-dev-branch/?p=36787) - at some point procedural mysqli functions will no longer be supported - I am not sure when, but better to be ahead of things (I know there lots of modules out there that need updating). The $page->myfield->row['land'] approach seems to work just fine. It's a shame it won't work as $page->myfield->land, but I as you mentioned, I guess the issue is $page->myfield->data, which would be a common requirement. I haven't time to investigate right now to see if I can find a workaround, but I don't think it really matters - what you have is easy to use and an awesome way to access data from all sorts of DB tables - brilliant!2 points
-
https://processwire.com/talk/topic/8525-cant-import-polymer-elements/2 points
-
Exactly that happens if a client goes to your central media manager and deletes an image. It's a natural flaw of RTE's that they store filenames which break if one deletes the file. A RTE is not an image manager. It's a texteditor. That's why you always need some extra place where images are stored. In either way: You need to communicate to your editors where images are stored, so they can manage them (and not only upload till extinction). If these images are in the page, they are editing, or in some central hub shouldn't matter to them to much. That's where I personally think it's easier to tell them the images are stored right next to the RTE they want to use it in, instead of some other place, which is quite unrelated to the actual page. It's really the same problem, only the images are displayed in different places. You can read Ryan view about that and how ProcessWire handles deleted and updated images here: /blog/posts/quality-assurance-for-images-in-rich-text-fields/2 points
-
You can delete any module manually - just use something like PHPMyAdmin and browse/search the "modules" database table and remove the row for the module. Then remove the module folder from the server and you should be good. In the case of this module, there are also some additional db tables to remove, prefixed with "version_control", but be careful to remove the ones for the version of version control that you want to remove. Also, note that Version Control supersedes Version Control for Textfields. The latter is only still around for older versions of PW.2 points
-
ElasticSearch does a lot, but the part that is most interesting to me is that it does an amazing job of fulltext search. It's also crazy fast. It can be a bit scary at first so hopefully this module will make it more accessible. I threw together this module pretty quickly, it's more of a proof of concept than anything else at this point. I tried it out on a site with 400 bilingual pages and the search results are much improved over the normal search you would get doing like queries or fulltext queries in mysql. Github page: https://github.com/jdart/ElasticSearchProcessWire I'd love to hear some feedback on how it works for you. It's very new so expect bugs, in particular the mechanism that turns pages into data to be indexed by ES might have some surprises.1 point
-
Hi guys, after a long pause on this project, I relaunched few days ago the new version of lymeta.com a website offering free high resolution photos, royalty free under creative commons zero license. Anyone can submit a photo and participate. I made a very simple design, flat and responsive, hope you like it. Cheers.1 point
-
Is it needed for the Backend Editmode? What's about to simply have one template with some fieldsets, each fieldset contains a few fields (those you mentioned in your subtemplates) and the visibility of the fieldsets are bound through checkboxes and the onlyShowIf settings for templates? | Select granule Subtemplates: | | | | [ ] use Basic-Car | [ ] use Diesel-Engine | [ ] use Turbo-Engine | [ ] use Four-Wheel-Drive | | | | Select granule Subtemplates: | | | | [x] use Basic-Car | [ ] use Diesel-Engine | [ ] use Turbo-Engine | [ ] use Four-Wheel-Drive | | | |--- Basic car -------------------------------------------------------------------------------| | | | BC_textfield_1 BC_ceckbox_1 ... | | | |---------------------------------------------------------------------------------------------| | Select granule Subtemplates: | | | | [x] use Basic-Car | [ ] use Diesel-Engine | [ ] use Turbo-Engine | [x] use Four-Wheel-Drive | | | |--- Basic car -------------------------------------------------------------------------------| | | | BC_textfield_1 BC_ceckbox_1 ... | | | |---------------------------------------------------------------------------------------------| |--- Four-Wheel-Drive ------------------------------------------------------------------------| | | | FWD_textfield_1 FWD_ceckbox_1 .... | | | |---------------------------------------------------------------------------------------------| - Pseudocode is like: only show Fieldset_BasicCar if Checkbox_BC is checked1 point
-
Another +1 for Cycle2. Easy to implement and customise.1 point
-
At OP, take my experience i came to PW with the experience of Wordpress, Zend , Yii Framework , ASP.NET MVC and the biggest advice you will get from me is almost the same as above "Just unlearn the illogical (Only Wordpress is illogical) pattern of other systems and take the most simple route." and also Template,Hooks and Module and wireData are the only thing you should really focus on to understand PW.1 point
-
It's not really a big security risk to allow access to html files, as that are static files. It's just that by now it wasn't a intended behavior to be able to access html files, therefore the rule. Also in the templates folders are maybe docs and such things in html format, which should probably be hidden. But if you use markdown this security is gone as well. Writing a custom .htaccess rule to allow access in the bower_components folder would probably be the best / most flexible bet.1 point
-
If these layouts are predefined, then you could go and use FieldtypeOption to simply build a selectbox for the backend where the editor can choose. In the template file it would be matter of a simple if / else structure. You could even use includes or wireIncludeFile or wireRenderFile, to import the different layouts, so they're available to other templates as well (if you need that or simply for more structured code). If the html stays the same you could easily use file fields to let the editor upload css / js files. These would be dynamically added to the site. It's better to use files instead of textfield (which would also work from a backend point of view) because it's better to include files instead of inline codes. If you need the html to also change you've two options. Either use again the file field for a php file and include that file, or use a textfield with the new Inputfield ACE Extended, but for the second option I'd suggest using a templating language, as it's easier and more secure than handling real php code.1 point
-
I am not sure I understand why they can't be referenced to your site root - is it just a matter of keeping things all together? <link rel="import" href="/bower_components/paper-input/paper-input.html" /> Actually looking into this more, I see that import is not supported in Firefox and apparently there are no plans to support it: http://caniuse.com/#feat=imports I guess the platform.js polyfill is making it functional across all browsers - is that what you guys are using?1 point
-
1 point
-
@Marty - maybe this could help: http://ckeditor.com/forums/Support/Solved-I-cant-embed-tweet-with-the-new-version-4.1.1 also this plugin might be cool: http://ckeditor.com/addon/mediaembed doh! adrian is 1 step ahead1 point
-
# Block access to any PHP or markup files in /site/templates/ RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/templates($|/|/.*\.(php|html?|tpl|inc))$ [OR] You can't link directly to php, html, tpl, or inc files in the templates directory, or its subfolders. You'll need to place them somewhere else!1 point
-
1 point
-
Your problem is actually in the html, not in the php code. Forms are send in plaintext by default, so to upload files you need to add this to the form tag. <form … method="post" enctype="multipart/form-data">…</form>1 point
-
hi heldercervantes, welchome to the forum. regarding the listing part of your question: there is a commercial module that does your request very well: https://processwire.com/talk/store/category/9-listerpro/ regarding your 2nd part of the question: don't know exactly what you mean by "profile page". but overall it sounds a bit like you are thinking in a way like you would do it with another CMS... organizing your admin-interface in tabs and lists and so on. processwire is quite different on this part! you have everything organized in your pagetree. everything has its place there and if not really needed nowhere else! for example if you had a blog setup. in drumlapress you would have a tab "blog" anywhere in your admin and manage your blog-entries there. then you would have to setup a menu-item listing all your blog-entries. in processwire you would create a page "blog" in your tree, holding all of the blog-entries as children. home '- blog '- post1 '- post2 so if you or your client wanted to create a blog-entry you would just have to click on "blog" and then "new". in my experience this is much easier to understand for the clients than setting up articles and then linking them in the menu. of course in PW you would have to exclude all blog-posts from getting listed in the menu - but thats very easy by using a selector like "template!=blogitem" hope that helps a little i hope it is not offtopic but structuring your content is the key to success in PW1 point
-
This thoughts have come up every now and then here in the forums. But after some time of getting used to this most people do like the fact that files are just where they are needed: stored in the page which it belongs to. It's actually more powerful and structured than having just a single bowl of files. There are also no plans to change the way images are stored. To make this more concrete: An RTE field cannot store any images. Most cms's hide that fact, by including their media managers directly into it, but this decouples the images completely from the page structure. If you're worried about your clients being confused by this, you should be able to hide the images field for them, as the latest dev version added the ability to upload images directly from the RTE images modal. The flexibility comes if you think about multiple imagefields. E.g. one for the big heroimage (single), one for the RTE images (mutiple) and maybe one for generating a optional gallery (mutiple). Each field for it's own concern and seperated by the page they are used on. If you compare that to a media manager where all those files are bunched together, I would rather take the processwire approach. Another example: Think of a list of pages representing different clients of the website's owner. All of them have a logo and semantically the logo belongs to the client, that's why it's on a page with all those other informations like names, address and stuff. If you would link the image from a media center you would need to maintain the images seperate to the clients: Go to page, change the name; go to media manager, change the logo (if it's that easily replaceable). In ProcessWire you can change both in one place and other pages using the image will update as they most likely will be field dependent (if used via the api, they are for sure) and not dependent on a specific imagefile (don't know if the RTE's do update automatically).1 point
-
There are some brilliant minds on Reddit. I've only ever read two things on there and this was the second. http://www.reddit.com/r/discworld/comments/2ysv26/sir_terry_has_gone_for_the_long_walk_across_the/cpcmru1 Amazing tribute.1 point
-
pushed Version 1.0.6 on github dev-branch. Works now with the API Adrian recommended: for single values //selected value (int) $page->myfield->value // selected label $page->myfield->label // associative array with column => value of depending datatable row $page->myfield->row muliple values can be called with WireArray API examples: $page->myfield->last()->row['land'] $page->myfield->first()->row['id'] $page->myfield->eq(3)->value To prevent conflicts with datatable column names like 'data' I decided to access the values via $page->myfield->row['data'] instead of $page->myfield->data. 'data' is an reserved property of the WireData object. Please check out and comment. Thanks1 point
-
By art-directed to you mean per-page or overall custom css/js/html? To begin with the whole frontend is custom in processwire. The cms doesn't enforce any markup, while a few module happily do generate markup if you wish, so you've the full control. If you need to be able to change presentation from the backend, build it that way. It really depends on what exactly you need.1 point
-
Hey, just noticed right now that this is a swiss powered discussion Have a nice weekend! Cheers1 point
-
Hmmm... I wonder if it's the inline function. Try this code instead for each module: <?php class CustomLogout extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'Custom Logout', 'summary' => 'Redirects to a custom login page after logout', 'singular' => true, 'autoload' => true ); } public function init() { $this->addHookAfter('Session::logout', $this, 'hookAfterLogout'); } public function hookAfterLogout($event) { $this->session->redirect($this->pages->get('/login/')->url); } } <?php class SiteHider extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'SiteHider', 'summary' => 'Hide Sites in CSS per User Roles', 'singular' => true, 'autoload' => true ); } public function init() { $this->addHookBefore("ProcessPageList::execute", $this, 'hookBeforePageListExecute'); } public function hookBeforePageListExecute($event) { if (!$this->user->name === 'selina') $this->config-styles->add($this->config->urls->templates . "css/sitehide.css"); } } Also, be careful with where you put the semi-colons (. In SiteHider, you had put it just after the if, which is a problem.1 point
-
Here is something I hacked together quickly for automatically adding new child pages to the pagetable field. This is only if you are using the page as the parent. It also handles deletion of items if they are trashed externally. I also disabled the internal check for orphans - because they have been automatically added already, there is no need for the "Children were found that may be added to this table. Check the box next to any you would like to add." option. I seems to be working great here, but please test carefully!! Add this to your admin.php file: wire()->addHookBefore('InputfieldPageTable::render', function($event) { $pp = wire('pages')->get(wire('input')->get->id); $ptf = $event->object; //remove pages from pagetable field if they were externally trashed foreach($pp->{$ptf->name} as $item) { if($item->is(Page::statusTrash)) $pp->{$ptf->name}->remove($item); } //add pages to pagetable field if they were created externally foreach($pp->children as $child) { if(!$ptf->has($child->id)) { $pp->{$ptf->name}->add($child); $pp->of(false); $pp->save($ptf->name); } } //reset orphans property so that we don't get a message asking to add new pages that are now already automatically added $ptf->setOrphans(new pageArray()); });1 point
-
this tutorial shows an application of the field: https://processwire.com/talk/topic/8635-simple-example-for-widget-management/?p=83418 whereby the user is able to select what pages a widget shows on, using a selector, or series of selectors.. so in this scenario, a widget can end up showing under some very complex/flexible circumstances, such as: - all child pages of a particular page - selected pages almost anything you can think of in terms of selecting a page with the selector api1 point
-
There are usually 2 menu types on most sites. Let me generalise here a bit. You've got the top navigation which tends to be global. It's on every page and usually accompanies the company logo. Then you've got the side navigation which is contextual or based on the section the user is currently within. I'm assuming you're asking how you your client can pick which links / pages are used on the top navigation? Create a field called top_navigation or something meaningful to you and your clients Set it to Type=Page type (Basics Tab) Make it Multiple Pages (Details Tab) Assign it PageListMultipleSelect+ win the Input field type (Input tab) Finally, associate this naviagtion field with a template. You can just assign it to the homepage or you could create a new page called Site Settings or Navigation. Just tell your client this is the place to manage their top menu. Here's a screengrab of how it should look.1 point
-
It makes a lot of sense for the menu to reflect the page tree - your site map makes sense, pages are easy to locate in the back end because they follow the identical structure to the front end and so on. I think there is an inherent danger if a client pushes and pulls their menu around too much - you can get a lot of broken links and illogical cross linking after a while. So a system where they have to work logically can be a life saver.1 point
-
Hi @Sephiroth, Welcome to PW and the forums. I am sure Joss is writing a long post right now to answer your questions ...(edit: he just did) About this: Can you confirm if you are really talking about the Blog (Site) Profile rather than the Blog Module? if the latter, what errors did you get? The Blog Module works fine for me even in 2.5.9. PHP Unit Testing: There was something in the works but I don't know the current status - https://processwire.com/talk/topic/2609-tests-for-processwire-core/ Menu Management: There is nothing out-of-the-box that the client themselves can (should?) use. A while back I did a proof-of-concept Menu Builder but never got it finished. However, there are other ways to achieve this. One way is to set up (yes, you guessed it), a 'page' field that you can attach to some template where a client can select pages that he/she wants to appear in a menu. A second similar option is to set up a 'checkbox field' that you attach to the template of pages that can potentially appear in a menu. Every time the client edits such pages they can tick the checkbox to enable (or disable depending on how you code it in your template file) that page to appear (or not appear) in a menu. Custom Post: Don't use WP so I don't know what this is. Maybe explain a bit more? Edit: OK, just read this: Given Joss' explanation above about pages, I think that answers your question. Really, in PW everything is custom. PW doesn't care what you call them . You will probably get a better explanation...1 point
-
Okay, I will address the Pages issue - I am somewhat famous for it! To start: https://processwire.com/talk/topic/2296-confused-by-pages/ And once you have that out of your system, here is the real info. Basically, a page in Processwire is just a container for content - nothing more. So, it could be a: Web Page News Bullitin Block of info Some strange widget An option for a dropdown selector A gallery item A review Something that gets stuffed into something else! A parent of some other group of pages, A child of something Basically, it is just an item that is created using the criteria of a template. It does not need to have a template file associated with it - if you are using it as a simple option in a drop down, what would be the point? Fields from a particular page can be called into another template or page or anything else, either singularly or rendered as a group. The contents of a page need a template file to be displayed on the site as they are, but not if they are being displayed by something else. Confused? The bottom line is don't think of a page as a "page" that you would get in Wordpress - just think of it as a container for data that can be used for anything at all. This is why Processwire is a TRUE content management system - because all the elements are simply tools to help you manage content, they do not force you to make your content any particular shape.1 point
-
Hi Marek, I am running 2.5.4 on this profile without any issues, what kind of issues are you having? Cheers1 point
-
Usually when I need to truncate something it's because it needs to be a summary that fits appropriately in a defined area and consistently with other items of the same type. As a result, having HTML in the truncated text is no good, so I'll include a strip_tags() as part of the truncation process, then wrap it in my own <p> or what not. Most of my sites have a shared truncateText() function somewhere in there that works kind of like this. Maybe there should be one in PW's core, not sure. function truncateText($text, $maxlength = 200) { // truncate to max length $text = substr(strip_tags($text), 0, $maxlength); // check if we've truncated to a spot that needs further truncation if(strlen(rtrim($text, ' .!?,;')) == $maxlength) { // truncate to last word $text = substr($text, 0, strrpos($text, ' ')); } return trim($text); } $summary = truncateText($page->body); echo " <a href='$page->url'>$page->title</a> <p class='summary'>$summary</p> ";1 point
-
just an idea for site specific css: when you use the BodyClass module, you can control the css as needed. Also there's no need for multiple css files. Then you can set all styles in the same file using specificity.1 point
-
Assuming I understand the need correctly, what I usually do add this to the <head> section of the main markup include: <head> <!-- all your typical <head> stuff --> <?php $file = "styles/$page->template.css"; if(is_file($config->paths->templates . $file)) { echo "<link rel='stylesheet' type='text/css' href='{$config->urls->templates}$file' />"; } $file = "scripts/$page->template.js"; if(is_file($config->paths->templates . $file)) { echo "<script src='{$config->urls->templates}$file'></script>"; } ?> </head> Using this method, if you have a template named 'product', then it could have dedicated CSS and JS files in /site/templates/styles/product.css and /site/templates/scripts/product.js, when you need it. The nice thing about this is that it's just a system rather than hard coded file. If you determine you need something unique for the CSS (or JS) on pages using some template, the you can just create the CSS (or JS) file and have it start working automatically. You can take this further too. For instance, you could use the same technique with page IDs to assign custom CSS/JS files to specific pages.1 point
-
My way of handle it was to create a textarea field and insert the code there directly. In the head.inc I had something like this: <?php if($page->additional_css != '') { echo '<style type="text/css">'.$page->additional_css.'</style>'; } ?> So no extra files were needed.1 point
-
Joss actually emailed me a similar question and I'll duplicate my reply here since it seems relevant: Performance as it relates to database is really not an issue that one needs to consider much (or at all) when it comes to creating their fields. Most field data in ProcessWire is loaded on-demand. It loads data selectively and only when it needs it. This enables it to be highly memory efficient with large quantities of pages in memory at once. When you have a $page, behind the scenes, none of the page data is actually loaded until you access it. For instance, if you access $page->body, then it goes and retrieves it at that moment (if it hasn't already retrieved it before). MySQL is extremely fast with simple primary key, non-joined selects, and we take advantage of that. What I'm trying to get across is that quantity of fields does not translate to an increase in joins or other factors that would slow the system down. Where ProcessWire does join data automatically is at page load time is when you check the "autojoin" box on a Field's "advanced" tab. Some fields you know will always be needed with every $page instance, and that's what autojoin is for. Typically, I make my "title" field autojoin, as it is already by default. I've hidden that autojoin option under the Advanced tab simply because most people never need to consider it. The original intentions behind autojoin have become less applicable than I originally thought [with regards to performance], so it's not something that comes up that often. ProcessWire also uses joins when it performs queries for $pages->find("selector"), and related DB-querying selector functions. It joins all the tables for fields that you query. So if you perform a find for "date>2012-12-19, body*=holidays" then it's going to join the field_date and field_body tables when a value matches. Though it doesn't do this for the purpose of loading the data, only for matching the data. Technically this type of query could be potentially faster if all those fields were in one table. But that doesn't translate to results that matter for us, and doesn't affect the way that you should use ProcessWire. The benefits of our one-table-per-field architecture far outweigh any drawbacks. I put a lot of time into finding the right architecture and balance here when coding ProcessWire 2. Incidentally, ProcessWire 1 did use the one-table approach (all the field data was stored with the page rather than in separate tables) and it was far less efficient with memory, and about the same in terms of performance. It's better to re-use something like "body" (when possible) rather than create "article_maintext" or other template-coupled variations like that. The reasons for that are for your own benefit. It is less to keep track of, and tends to foster better consistency. It also results in more reusable code and broadens the potential of where the data can be used. Take the example of an on-site search engine, like you see in the upper right corner of processwire.com. If we know that the main text field(s) of most templates has some consistency in their field names (like title and body), then we can write code that doesn't need to know whether something is an article, a press release or a product. We can find all pages that match "holidays" in the text just by doing this: $pages->find("title|body*=holidays"); But if created a separate textarea field for every template, then any code that queries those fields needs to know a lot more about them: $pages->find("title|article_maintext|pr_maintext|product_maintext*=holidays"); While that still works, it doesn't scale nearly as well. This also translates to the code you use to output the results. If you want to show a snippet of the matching text with the search results, you are going to have a lot more fields to consider than just "body". Now if each of your templates genuinely needs very different settings for each of their main text fields, then of course it's fine to create them as you need them. But in the real world, I think you draw more benefit by planning for reusability when possible. The benefits are for you (the developer), as it doesn't matter much to ProcessWire. Reuse fields where it's obvious that the name of the field makes sense in the context of multiple templates. If template "employee" needs a date_of_birth field and template "press_release" needs a date_publish field then just create one field called date and use it on both templates. On the other hand, if you need multiple date fields on the same template (like date_unpublish) then more specific field names start to make sense. In that case, I would usually use my date field for publish date, and create a separate date_unpublish field for my unpublished date field. Though some may prefer to actually have separate date_publish and date_unpublish fields because they are obviously related by name. Ultimately, use what works best for you, but always keep an eye out for obvious reusability potential with fields. I think that most people naturally arrive at the right balance for their needs after some experimentation. What is a best practice for one need might not necessarily be for another. So these are mostly general purpose guidelines and people should find what makes the most sense in their context. For the majority of cases, I think avoiding tightly coupled template and field names is a better strategy. TL;DR: It doesn't matter to ProcessWire what you do. Aim to reuse fields when you can and when it makes sense, for your benefit.1 point
-
Below, I'll write how you can move your site from Drupal to ProcessWire. It's quite simple. In Drupal you will need: - Views Module, - Views Data Export Module, - Views UI Module (integrated with Views), - Chaos tools Module - required by Views. Install these modules and switch them on. In ProcessWire you need only: - CSV Page Import Process (Import Pages from CSV). Install this module. When you are ready, you have to create a new View (select: "Create a page") in Drupal with all fields which you want to export. Then, add "Data export" subpage and make sure, that format is CSV file. It's a good idea, to use Pager when you have lot of nodes (pages). You have to setup an url to download your CSV files. When you are ready - download your data. Next step: In ProcessWire, you have to prepare a template with your fields. When that's finished, you can import your data from CSV files using "CSV Page Import". That's all. If you have any questions, write them below. I can also write complete scenario for my website (if there will be anyone interested in that).1 point