Leaderboard
Popular Content
Showing content with the highest reputation on 06/03/2015 in all areas
-
Hi @holmescreek and welcome to the forums. What you need to do is define a separate role - perhaps called "deletor" and give it edit and delete permissions. Now remove the delete permission from the main editor role. Now for the pages that you want the delete option to appear on, give their template edit permission for the deletor role. Something like this:2 points
-
Some sites need widgets, as they have been called in some systems; a widget can be almost anything, like: tag cloud mini calendar menu quote rotator free text social sharing search contact info map This is a simple way to create widgets that can be shown in multiple "areas" of a page, as well as on specific pages. In this particular method you would need to setup each widget type you want and then determine how best to accept any necessary user input like content, pages select (like for a menu) or settings. This example uses include files for each widget type, and the name of the include file would match the name of the widget type, which is also a page field. In this example, I'm also using ListerPro to provide a widget management page. Fields The main fields used on this widget example are : title widget_location (page select - options in this case are footer and sidebar) widget_type (page select, you would configure your widget types as selectable options) pages_select (would be used for multiple pages and might apply to a menu widget) body - used for plain widgets selector (selector inputfield, used for telling the system where to show the widget) text_structured - for this i'm using a YAML field, but it could just as easily be a table; would depend on what you want to store; YAML would allow this single field to be used for varying requirements based on the widget type, but would be harder to validate and prone to user error; icon - a page select for an optional icon which is being used in the template, and would be shown as part of the widget. Files for each widget type you want to allow users to select from, you would need to create an include file with the markup for that widget, and then add that widget to the list of available widgets. here is an example for a site with several widget types: Selector & Output wherever you want to include the widgets (footer, sidebar etc.) you would run a $pages->find and then foreach through the widgets (in this case finding all footer widgets). In this case the (incredibly amazing new) selector field would be specifying what pages to show the widget on. We assume that most widgets won't have a selector specified, and will default to show the widget. if a selector is specified, we can check to see if this page fits the selector by using the $page->is($selector) syntax. <?php $widgets = $pages->find("template=widget, widget_location=footer, sort=sort"); foreach($widgets as $widget) { // check if the selector field is in use and if so, see if this page is supposed to display it: if( $widget->selector) { if( !$page->is("$widget->selector") ) continue; } $widgetType = $widget->widget_type->name; $include = file_exists("./inc/widget-{$widgetType}-foot.inc") ? "./inc/widget-{$widgetType}-foot.inc" : './inc/widget-footer.inc'; include($include); } ?> this example also has a fallback file in case the widget type is not specified, sort of a default. the widget's .inc file will be unique to your design and how you have it setup.1 point
-
For pages that you want to automatically direct to the first child, I would make them use a template that has this in it's code: <?php if($page->numChildren) $session->redirect($page->child()->url); If you add a new child page, and they aren't sorted by date added (descending) then the newly added page isn't likely to be the first child. If no default sort is selected, then it'll add it as the last child. So if you wanted to redirect to last page (rather than the first) then you'd want to do this: <?php if($page->numChildren) $session->redirect($page->child("sort=-sort")->url); By the way "sort" is just a name representing the order that pages have been dragged/dropped to. That's the default value if a page doesn't have another field selected as it's default sort field. The minus sign "-" in front of it represents descending sort. Without the minus sign, it would be ascending. Since you want to select the last page, that's why it's "-sort" rather than "sort". Or if you wanted to make it select the most recent page added by date: <?php if($page->numChildren) $session->redirect($page->child("sort=-created")->url); The above is also descending since most recent added would be the highest date.1 point
-
Today I can finally share a project with you, that started about two years ago. Together with a colleague (the daughter of the client) I did the concept and design and a click-dummy for a course of my studies. Half a year later after finishing my studies we then did some clean-up and I programmed it in ProcessWire. And now nearly a year later all the content—texts, photos and a lots of tech. information—is ready, too, so it can soft-launch on monday. http://korona-licht.de/ The client is a small local company selling mostly LED lighting. They've a handful of quite flexible systems to build on, which can be adapted to a lot of use cases, as well as the ability to custom build things if needed. While they're not a very big company their portfolio has lot's of great national and even some international projects to offer. It was a really nice experience working with them and I'm really happy that even things like well written texts have finally found it's way into the website. Others may have just published it halfway through the project.1 point
-
Hi Currently the invoicing mode skips the payment options all together - so you would actually need two different "checkout" pages, other with setInvoiceMode true and other without (using normal payment modules). Then in your cart page you would have the choose between payment and invoice checkout. I am planning to make invoice (and other "postpay" methods) work just like all others, but I have no ETA for that yet.1 point
-
Ok I tried this: go to Users/roles and make a note what was set there for the fields with a permission, set those same permissions in the new field settings for each field delete the permission entries from Users/Permissions and finally uninstall the old module1 point
-
I've been having multiple issues with my Grid Server databases over the last few days. After about 6 years I'm now considering moving away from Mediatemple (also considering it's now owned by GoDaddy) .1 point
-
It took me some time to find how to use Selector Inputfield, so I think this post just might help someone else. As it should be obvious from the word Inputfield (was not for me ) it is not a fieldtype. That means you should create a field with fieldtype "Page" and then select "Selector" inputfield on the "Input" tab. But it can't be done without some customization. You need to go to the Inputfield Page module config in Modules and add it to the allowed inputfield list. After that all works as expected. Thank you, Macrura! Without you topic I wouldn't even know this awesome inputfield existed in the first place.1 point
-
Just for the record, this is also discussed here: https://github.com/ryancramerdesign/ProcessWire/issues/263. In that issue Ryan explains why it works like it does. Generally speaking I'd suggest avoiding changing templates of existing pages, and explaining to clients that this is a) a special case, and b) potentially dangerous. Changing template could result in loss of data (though ProcessWire does attempt to warn you before anything irreversible can happen), and it might also cause unexpected side-effects on the site, if something somewhere assumes that a specific page exists and is of certain type, etc.1 point
-
But then you're not creating a new page. You're changing an existing. (Soma is quicker)1 point
-
But that's not creating a new page, but changing an already created page. As I remember it was always like this.1 point
-
1 point
-
Thank to everybody for your support! At the end Nico suggestion's worked like a charm and luckily I have no security limitations on the server. I report here the code I finally use and I hope this could be useful to someone else // fetch the json displayed on the service page $dataJson = file_get_contents('http://www.serviceurl.com/service-pages/?parent=1145'); // transform it into a php array $items = json_decode($dataJson, true); foreach ($items['matches'] as $item) { // start the looping. "matches" is the name of the results array generated by the webservice echo $item['title']; echo $item['body']; echo 'http://www.myurl.com/site/assets/files/' . $item['id'].'/'.$item['myimage']['basename']; // url image } If you need to pass an image, the last line rebuild the url and Insted of www.myurl.com and [myimage] field you have to write your own and than you can use in an img tag.1 point
-
Not sure why this hasn't been mentioned, so I am wondering if I am missing something relevant, but why not use the $template->noSettings option? Do you need to hide on a page basis, rather than per template? Anyway, if it suits your needs, turn on advanced mode in your config.php file and then you will have a Disable Settings Tab? option on the Template's System Tab. Hope that might help.1 point
-
One for https://processwire-recipes.com/ Output a Pagearray as: beer, rum, wine & whisky (note the '&' and don't get drunk) $count = count($pagearray); foreach ($pagearray as $key => $p) { $divider = ($key + 1 === $count) ? ($count === 1 ? '' : ' & ') : ($key === 0 ? '' : ', '); $out .= $divider . "<a href='$p->url' class=''>$p->title</a>"; } echo $out;1 point
-
Just to add to the confusion. - You can make the title field not required in template context. - You can set a template to not include global fields (advanced settings) So you could remove title for that template but still have title global.1 point
-
This turns out more complex than it seems, but it is usually something not used that often or ever at all. Even with my experience took some time to get all pages, unpublished , published, hidden, not in trash and not under admin. This is with superuser logged in as I think as editor or guest user you won't get pages from trash anyway. But something like this is needed currently Unless I'm missing something. $pa = $pages->find("has_parent!=2,id!=2|7,status<".Page::statusTrash.",include=all"); foreach ($pa as $p) { echo "<li>$p->path</li>"; } Note that as soon as you got a few hundred or thousand pages you will get a problem Edit: id = 2 // is the /processwire/ admin parent id = 7 // is the trash include=all // to get all pages unpublished and hidden1 point
-
Based on what I'm understanding from your last message, I think you should skip keeping the separate table. It just sounds like extra, unnecessary work, unless there's something more to this project that I don't yet understand. Instead, I think you should have your cron job execute a script that bootstraps ProcessWire and takes care of all the adding, updating and deleting of records consistent with the web service you are reading from. This is something that I think ProcessWire is particularly good at, because it's been designed for this from the beginning (it's something I have to do with a lot of my client work). Whether XML or JSON doesn't matter much, as PHP includes the ability to read from either type quite easily. Though like the other guys here, I generally prefer JSON just because it's less verbose and less fuss. If JSON, you'll pull the feed and use PHP's json_decode() to convert it to an array. If XML, you'll use PHP's SimpleXML to convert it to an array. Once you've got the array of raw data, you'll iterate through it and add, update, or delete pages in ProcessWire to make it consistent with the data you are pulling from the web service. Live, working example I think that the best way to demonstrate it is with a live, working example. This one uses the existing modules.processwire.com/export-json/ feed. You might also want to see the feed in human-readable mode to get a better look at the format. Below is a shell script that bootstraps ProcessWire, reads from that feed and maintains a mini "modules directory" site, on your own site. I made this feed so that it can be tested and used on a brand new installation using the basic profile (included with PW). If left how it is, it'll create a mini modules directory site below the '/about/what/' page and use the template 'basic-page' for any pages it adds. But you can run this on any ProcessWire installation by just editing the script and changing the parent from '/about/what/' to something else, and changing the template from 'basic-page' to something else, if necessary. This script assumes that the template used has 3 fields: title, body, and summary. The 'basic-page' template in PW's default profile already has these. If you adapt this for your own use, you'd probably want to change it to use more specific fields consistent with what you need to store on your pages. In this example, I'm just building a 'body' field with some combined data in it, but that's just to minimize the amount of setup necessary for you or others to test this… The purpose is that this is something you can easily run in the default profile without adding any new templates, fields, pages, etc. 1. Paste the following script into the file import-json.php (or download the attachment below). For testing purposes, just put it in the same directory where you have ProcessWire installed. (If you place it elsewhere, update the include("./index.php"); line at the top to load ProcessWire's index.php file). 2. Edit the import-json.php file and update the first line: "#!/usr/bin/php", to point to where you have PHP installed (if not /usr/bin/php). Save. 3. Make the file executable as a shell script: chmod +x ./import-json.php 4. Run the file at the command line by typing "./import-json.php" and hit enter. It should create about 95 or so pages under /about/what/. Take a look at them. Run it again, and you'll find it reports no changes. Try making some changes to the text on 1 or 2 of the pages it added and run it again, it should update them. Try deleting some of it's pages, and it should add them back. Try adding some pages below /about/what/ on your own, run it again, and it should delete them. import-json.php #!/usr/bin/php <?php // replace the path in the shabang line above with the path to your PHP // bootstrap ProcessWire. Update the path in the include if this script is not in the same dir include("./index.php"); // if you want to run this as a PW page/template instead, remove everything above (except the PHP tag) // save our start time, so we can find which pages should be removed $started = time(); // keep track of how many changes we've made so we can report at the end $numChanged = 0; $numAdded = 0; $numTrashed = 0; // URL to our web service data $url = 'http://modules.processwire.com/export-json/?apikey=pw223&limit=100'; // get the data and decode it to an array $data = json_decode(file_get_contents($url), true); // if we couldn't load the data, then abort if(!$data || $data['status'] != 'success') throw new WireException("Can't load data from $url"); // the parent page of our items: /about/what/ is a page from the basic profile // update this to be whatever parent you want it to populate... $parent = wire('pages')->get('/about/what/'); if(!$parent->id) throw new WireException("Parent page does not exist"); // iterate each item in the feed and create or update pages with the data foreach($data['items'] as $item) { // see if we already have this item $page = $parent->child("name=$item[name]"); // if we don't have this item already then create it if(!$page->id) { $page = new Page(); $page->parent = $parent; $page->template = 'basic-page'; // template new pages should use $page->name = $item['name']; echo "\nAdding new page: $item[name]"; $numAdded++; } // now populate our page fields from data in the feed $page->of(false); // ensure output formatting is off $page->title = $item['title']; $page->summary = $item['summary']; // To keep it simple, we'll just populate our $page->body field with some combined // data from the feed. Outside of this example context, you'd probably want to // populate separate fields that you'd created on the page's template. $body = "<h2>$item[summary]</h2>"; $body .= "<p>Version: $item[module_version]</p>"; foreach($item['categories'] as $category) $body .= "<p>Category: $category[title]</p>"; $body .= "<p><a href='$item[download_url]'>Download</a> / <a href='$item[url]'>More Details</a></p>"; $page->body = $body; // print what changed $changes = $page->getChanges(); if(count($changes)) { $numChanged++; foreach($changes as $change) echo "\nUpdated '$change' on page: $page->name"; } // save the page $page->save(); } // now find pages that were not updated above, which indicates they // weren't in the feed and should probably be trashed $expired = $parent->children("modified<$started"); foreach($expired as $page) { echo "\nTrashing expired page: $page->name"; $page->trash(); // move to trash $numTrashed++; } echo "\n\n$numAdded page(s) were added"; echo "\n$numChanged page(s) were changed"; echo "\n$numTrashed page(s) were trashed\n"; import-json.php.txt Running the script as a cron job: You can instruct your cron job to run the script and it should be ready to go. You may want to move it to a non web accessible location for more permanent use. You'll also want to update your bootstrap "include()" line at the top to have the full path to your ProcessWire index.php file, as your cron job probably isn't executing it from the web root dir like you were manually. Running the script as a template file: You can run this script as a template file on a page by removing the include() line and everything above it with this line: <pre><?php Place it in your /site/templates/ directory, add the template from PW admin, and create a page that uses it, then view it.1 point