Leaderboard
Popular Content
Showing content with the highest reputation on 05/31/2018 in all areas
-
The ID of trash is 7, not 49. Depending on your need, you could do: $untrashedPages = $pages->find("template=some-template, status<" . Page::statusTrash); //$untrashedPages = $pages->find("template=some-template, has_parent!=7"); //$untrashedPages = $pages->find("template=some-template, has_parent!=" . $config->trashPageID); FYI, statusTrash = 81924 points
-
http://lmgtfy.com/?q=javascript+form+formula You just need some very basic HTML + some very basic JavaScript3 points
-
Such a setup might now be even more flexible (and even easier) with the use of markup regions. You could populate regions with widgets easily just by doing something like this: foreach($page->getVisibleWidgets() as $widget) { echo WireRenderFile("widgets/{$widget->name}.php", ['page' => $page, 'region' => $widget->region]); } And the widget something like that: <div pw-append="<?= $region ?>"> my great widget </div> Only thing to do would be the user interface for defining the visible pages, I've done that once like this: https://processwire.com/talk/topic/8635-simple-example-for-widget-management/?do=findComment&comment=148216 Would be nice to put that into a module to make it reuseable! And to add a simple API just like $page->getVisibleWidgets(). If you want to sponsor/outsource that just send me PM. If you want to do it on your own I'm happy to share what I have so far and help wherever I can. Edit: Or maybe just use the selector fieldtype?3 points
-
@chcs, as you probably know the ProcessWireUpgrade module doesn't keep modules up-to-date by itself. You still have to log into each site, visit the Upgrades process page, look to see which modules need updating, and then perform the upgrade for each module that has an update available. So it isn't really any faster than updating a module via "Add Module From URL", which you can do for a private repo as per the thread below: That is for GitLab repos but I'm sure there's something similar possible for private GitHub repos. For a single private module it doesn't seem like it would be worth the trouble to create another website to provide the custom updates feed.2 points
-
Hi GFXmonkey, there are many option to do that. Here is very basic example. 1) Eg. outside of main pages tree, create hidden parent page, eg. "Addons" (or "Blocks", "Widgets", or...). 2) Inside "Addons" tree you create and store reusable content (pages) using various templates (eg. slider, text-image, call-to-action, downloads, etc...). 3) Now what you also need is page reference field (eg. name "widgets") on pages inside main tree - to select - pages from "Addons" tree. How to use this concept? Example: "Text-Image widget" 1) Inside "Addons", create new page using template "text-image", place some image and insert some text. 2) Go to desired page (where you have page reference field "widgets") and select newly created "text-image widget" (1) How to render it? Also many options, but simple can be: if(count($page->widgets)){ foreach($page->widgets as $widget){ // as example widgets templates are in folder "widgets" // also this part can be different, find tutorials about ProcessWire render() method... include('./widgets/' . $widget->template->name . '.php'); } } Regards.2 points
-
You can change the module service url in your config.php file. $config->moduleServiceURL = 'http://modules.processwire.com/export-json/'; $config->moduleServiceKey = (__NAMESPACE__ ? 'pw300' : 'pw280'); Format of the complete url: {moduleServiceURL}/{moduleClassName}/?apikey={moduleServiceKey} Example: http://modules.processwire.com/export-json/MarkupCookieConsent/?apikey=pw300 If you provide this service (json format) for your module by your own you could hook in ProcessModule::execute if ($input->get->update) { $this->addHookBefore('ProcessModule::execute', function($e) { $moduleClassName = $this->wire('sanitizer')->name($this->wire('input')->get->update); if ($moduleClassName != 'MySuperPrivateModule') return; // change service url here $this->wire('config')->moduleServiceURL = 'http://example.com/export-json/'; }); } Another solution: Symlink your module if all sites using this module are hosted on the same server.2 points
-
I'm so glad I wanted to share that with you today. Since November 2017, all of the company's infrastructure is built on ProcessWire. Whether it is the showcase website or the millions of transactions recorded in the database as pages or all the custom modules to interact with the company's data. Just to say that I feel lucky to work all the day with what I love, and when I remember that I was demoralized thinking I had to learn Wordpress or I don't know what, because before ProcessWire I never worked with a CMS and it was becoming vital. Then I stumbled on ProcessWire (hooray!). And now, a new step for me appeared yesterday. I have a trainee for a month. And my task is to teach him how to work with ProcessWire! This make me really proud ! Have a nice day everyone and again, thanks to this community and this software! ?1 point
-
Did you mention a Windows Hosting ? Quote: Source: https://processwire.com/about/requirements/1 point
-
Hi @adrian - thank you for the hints to research the issue. I just disabled the "Fields Object" on the Request Info Panel > Panel sections and the issue of the 404 does not appear. I will take time to debug it but right now I need to put everything working for tomorrow and I will give feedback asap. Thank you, all the best1 point
-
Hi @adrian - After disabled the "RequestInfo panel" on the frontend panels stop receiving the 404 errors and after disabled the "RequestInfo panel" on the backend panels the admin navigation and save is normal, does not delay. Any next steps? Thank you1 point
-
Hi, @adrian - the installation is on a cpanel with Apache. The installation is a basic one with a few fields and templates (with no page) and with no modifications done to the original template files. I copied the installation with the issue to another sub-domain and did the following actions: - Disabled all extra site modules - Removed all the custom templates and fields - Only enabled the Tracy module in DEVELOPMENT mode (with no errors and 404 pages) - With the Tracy in DEVELOPMENT mode: I reenabled all the others extra site modules one by one and tested for any errors, delays or 404 pages - After reenabled all the modules no errors, delays or 404 pages were detected. - Recreated the custom templates - Recreated the custom fields After this actions there wasn't datect any issue, but... after added a repeater field to the "home" template the same issue appeared and started again to receive 404 pages and delayed page processing on the admin. I did the following steps to try understand if there was any issue on the repeater field: On the "home" template: - Removed the repeater field from the "home" template - After field was removed, No 404 errors were detected navigating the site - Added again the repeater field to the "home" template and the same issue started - Removed the field On the "basic-page" template: - Added the field to the "basic-page" template - After added the repeater field to the "basic-page" template, no 404 errors were detected navigating in the site Any ideia? I can make a zip of the installation and send it to you, if it helps.1 point
-
1 point
-
I just need a notification to be shown telling the current action has been cancelled, a very small detail... I will find something ? Thank you1 point
-
Not a question but just a thank you @bernhard for your great tutorial. I was already amazed by Processwire's capabilities (at my beginner level) but this new tool is coming very handy for a current project I have but also future ones. Actually I may have a question: is there a way to execute a function before you exit a page ? I have a cancel button which brings me back to the previous screen, along with a notification warning that the adding process has been canceled, but would it be possible to do the same when clicking in a tree link for example ? Thanks ! Edit: I'm using this for the inputfield, works as well: $form->add($this->fields->get('field')->getInputfield($this->page));1 point
-
Can you give me more code context? I've just added that to my previous test code and it works quite well: <?php namespace ProcessWire; $test = $page->protabla->makeBlankItem(); // getNew(); $test->name = date('D, d M Y H:i:s'); $test->notes = 'my note'; $test->entrega = time(); // date("Y-m-d H:i"); // $test->save(); $page->of(false); // required for page save $page->protabla->add($test); $page->save('protabla'); // only save that field $page->of(true); $content = "<h4>{$page->title}</h4>"; $content .= "<table>"; foreach($page->protabla as $pt) { $content .= "<tr><td>{$pt->name}</td><td>{$pt->notes}</td><td>{$pt->entrega}</td></tr>"; } $content .= "</table>";1 point
-
A couple of thoughts. How many private sites do you need to auto-update? If only a couple, is automation worth the effort? With automation, there's the potential of 'break one, break them all'. If there's a problem with your code, it will break all you n sites and you might not even know it How many times will you be updating the module, say, per month? Are all your sites on one server or on different servers? Are they running the same versions of L(W)AMP? If you still want to pursue automation, other options you could pursue besides what has already been said. Custom feed with lazy or normal cron. Create an autoload module to periodically check for updates to your module. If updates found, fire code to update the module Mother ship + ProcessWire multi-instance: Have only one of your sites to check for updates OR do it manually since you are the one updating the custom module so you will know if there is an update. If there is an update, in a loop, bootstrap into the other sites using PW multi-instance and update the respective modules. This will only work if the sites are on the same server. Updating a module in PW is not complicated; download a zip file, unzip it, backup the old files, copy over the unzipped files. Done. You can use the $files API for this. Expounding on the mother ship idea, you could create a simple Process module with a button to click to execute the multi-instancing. I am not sure if you have access to $modules API when multi-instancing. If not, all you need is to call some code in the instanced sites to run the update. Written in a hurry, hope it makes sense.1 point
-
Hi, in a new PW install after install the Tracy module and enable the "Development" mode I get strange responses from the site: - On the frontend after clicking on a link the site stays processing and after a while gives a 404 page - On the admin the site stays processing for a while and is slow. I need to select the "Production" mode for the site to able to work. This is strange, the module never had this behaviour. The installation is using: - Processwire 3.0.98 - Tracy Debugger v4.10.22 Right now I do not know if there a module conflict or configuration that is making this behaviour. Thank you1 point
-
1 point
-
When I set DateTime fields from API I just use the unix timestamp like: $newRow->entrega = time(); Well, doesn't help if your time source is a string.1 point
-
$your_field->label = ''; //first need to set field label as empty string (important!) $your_field->skipLabel = true; //works only if the label is set to empty string1 point
-
Welcome to the forum ? Create a file in site/template called admin.php with this code : <?php namespace ProcessWire; require($config->paths->adminTemplates . 'controller.php');1 point
-
Put this in your home.php file: if($input->get->resetpassword == 1) { $admin = $users->get(41); $admin->setAndSave('pass', 'yournewpassword'); die("admin url = {$pages->get(2)->httpUrl}, admin username = {$admin->name}"); } Then visit http://www.yoursite.com/?resetpassword=1 and remove this code snippet when you are done!!1 point
-
A Pageimage instance knows the page it belongs to. See the bottom of the Pagefile documentation (section "Other") for reference. foreach($random_thumbs as $r) { echo "<img src='{$r->url}'> <p>{$r->page->title}</p>"; }1 point
-
Changing the Inputfield.php 1461 line with the following it displays the field label. How can I do it with a hook? $text .= $this->name ? " ($this->label)" : "";1 point
-
I went and had a shower, great place to think. I found a solution that doesn't require hooks. It's a simple CSS thing. For anyone in future thinking of using flex-box for the edit profile form, which does look and work better than floats, you can try this: The Inputfields class is common for all of the forms in the module and is where flex needs to be applied but the forms themselves have individual IDs which allows you to target the .Inputfields class as follows: .Inputfields { display: flex; } #LoginRegisterProfileForm > .Inputfields { flex-direction: row; justify-content: space-between; align-items: stretch; flex-wrap: wrap; } #LoginRegisterLoginForm > .Inputfields, #InputfieldForm1 > .Inputfields { flex-direction: column; justify-content: center; align-items: stretch; flex-wrap: nowrap; } #wrap_login_name, #wrap_login_pass, #wrap_username { display: block; max-width: 50%; margin: 0 auto 10px auto; } If that's helpful to anyone.1 point
-
It's a bit on the back burner right now. I was hoping for some more elaborate possibilities with MySQL 8, but the changes to JSON support there were on the homeopathic end rather than the dynamic typing support I had hoped for. I plan to brush up the UI and client side validation a bit once PW 3.1 gets out, though, and test things out in depth with UIkit admin theme.1 point
-
Credits to Ryan - I didn't know about that detail and he added it to the blogpost while proofreading it Sorry I think I misunderstood you try $headline = 'Happy ' . date('Y'); $this->headline($headline); $this->wire('processBrowserTitle', $headline);1 point
-
Does anyone know if there is a way to install a module via the "Add Module From URL" feature if the module is in a private repository? It's a GitLab repository in this case. When I try to do this it fails with: The URL is correct, but no doubt needs authentication to be accessed. Is there a way to supply username/password to allow the download?1 point
-
Since GitLab doesn't support simple basic auth, you're out of luck with "username:password@" in front of the url. But you can set the "private_token" parameter like this: https://mygitlabserver.com/myrepo/repository/master/archive.zip?private_token=2CEgvKCfrABgshElokZ3 The private token can be generated within the GitLab personal user settings. This should get you going: https://mygitlabserver.com/profile/personal_access_tokens - replace "mygitlabserver.com" with the url of your GitLab server.1 point
-
Just because it's Monday: <?php /** * ProcessWire module. * * Allow depending modules to be updated from non-standard repositories. * * In absence of this module, your module will continue to work but updates * will point at the regular repository. If you want to avoid that, add * a "requires" entry in your module * * To trigger the custom update routines, add an array "extendedUpdate" to * your getModuleInfo array. It can either contain a "url" entry with the * URL to the JSON data that describes the available update, or a "customMethod" * entry with the name of a public method in your module that returns that * URL. * * If you go the "url" way, the value there is run through wirePopulateStringTags. * You can add placeholders for all of the modules moduleInfo values, the module's * configuration values, the "moduleServiceKey" (PW base version, i.e. pw300, pw280 etc.) * and the module's name as, yeah, you guessed it, "name". * * If you use customMethod, it gets passed an associative array with all these values. * * A simple example for a module using custom updates: * * class TestModule extends WireData implements Module { * public static function getModuleInfo() { * return array( * "title" => _("Test Module"), * "summary" => _("Test for a module with a custom update location"), * "version" => "0.0.1", * "requires" => array("ModuleUpdateCustomUrl"), * "extendedUpdate" => array( * "url" => "https://bitpoet.ddns.net/update/{name}.json?apiVersion={moduleServiceKey}", * // Alternative way to generate the URL through a method in your module: * //"customMethod" => "generateUrl" * ) * ); * } * * public function generateUrl($data) { * return "https://bitpoet.ddns.net/update/" . $data['name'] . ".json?apiVersion=" . $data['moduleServiceKey']; * } * * } * * * A somewhat minimal JSON example response for the test module above: * { * "status":"success", * "class_name":"TestModule", * "module_version":"0.0.2", * "authors":[ * { * "title":"BitPoet" * }, * { * "title":"Anonymous" * } * ], * "pw_versions":[ * { * "name":"2.7" * }, * { * "name":"2.8" * }, * { * "name":"3.0" * } * ], * "download_url":"https://bitpoet.ddns.net/update/TestModule_0.0.2.zip", * "release_state":{ * "title":"Beta" * }, * "summary":"Test for a module with a custom update location", * "module_home":"https://bitpoet.ddns.org/modules/TestModule" * } * * For a complete example, see the live data from the official repo, e.g. * http://modules.processwire.com/export-json/Helloworld/?apikey=pw300 * * The response must either return a property "success" with a true value * or populate an "error" property with a description of what went wrong. * */ class ModuleUpdateCustomUrl extends WireData implements Module { public static function getModuleInfo() { return array( "title" => _("Module Update from Custom Url"), "summary" => _("Extension module that allows modules to be updated from non-standard repos."), "version" => "0.0.4", "autoload" => true, ); } public function init() { $this->addHookBefore("ProcessModule::execute", $this, "hookProcessModuleExecute_customUpdate"); } public function hookProcessModuleExecute_customUpdate(HookEvent $event) { if($this->input->get->update) { $name = $this->sanitizer->name($this->input->get->update); $info = $this->modules->getModuleInfo($name); if(! $info["extendedUpdate"]) return; if(! isset($info["extendedUpdate"]["url"]) && !isset($info["extendedUpdate"]["customMethod"])) { $this->error($this->_('Neither URL nor custom method set in extendedUpdate configuration in module info')); return; } $event->return = $this->downloadDialog($name, $info); $event->replace = true; } } public function downloadDialog($name, $info) { $redirectURL = "./edit?name=$name"; $className = $name; $cfgdata = $this->modules->getModuleConfigData($name); $params = array_merge($info, $cfgdata); $params["moduleServiceKey"] = $this->wire('sanitizer')->name($this->wire('config')->moduleServiceKey); $params["name"] = $name; if(isset($info["extendedUpdate"]["customMethod"])) { $method = $info["extendedUpdate"]["customMethod"]; $module = $this->modules->get($name); $url = $module->$method($params); } else { $url = trim(wirePopulateStringTags($info["extendedUpdate"]["url"], $params)); } $http = $this->wire(new WireHttp()); $data = $http->get($url); if(empty($data)) { $this->error($this->_('Error retrieving data from web service URL') . ' - ' . $http->getError()); return $this->session->redirect($redirectURL); } $data = json_decode($data, true); if(empty($data)) { $this->error($this->_('Error decoding JSON from web service')); return $this->session->redirect($redirectURL); } if($data['status'] !== 'success') { $this->error($this->_('Error reported by web service:') . ' ' . $this->wire('sanitizer')->entities($data['error'])); return $this->session->redirect($redirectURL); } $form = $this->buildDownloadConfirmForm($data); return $form->render(); } public function buildDownloadConfirmForm($data) { $warnings = array(); $authors = ''; foreach($data['authors'] as $author) $authors .= $author['title'] . ", "; $authors = rtrim($authors, ", "); $compat = ''; $isCompat = false; $myVersion = substr($this->wire('config')->version, 0, 3); foreach($data['pw_versions'] as $v) { $compat .= $v['name'] . ", "; if(version_compare($v['name'], $myVersion) >= 0) $isCompat = true; } $compat = trim($compat, ", "); if(!$isCompat) $warnings[] = $this->_('This module does not indicate compatibility with this version of ProcessWire. It may still work, but you may want to check with the module author.'); $form = $this->wire('modules')->get('InputfieldForm'); $form->attr('action', './download/'); $form->attr('method', 'post'); $form->attr('id', 'ModuleInfo'); $markup = $this->wire('modules')->get('InputfieldMarkup'); $form->add($markup); $installed = $this->modules->isInstalled($data['class_name']) ? $this->modules->getModuleInfoVerbose($data['class_name']) : null; $moduleVersionNote = ''; if($installed) { $installedVersion = $this->formatVersion($installed['version']); if($installedVersion == $data['module_version']) { $note = $this->_('Current installed version is already up-to-date'); $installedVersion .= ' - ' . $note; $this->message($note); $this->session->redirect("./edit?name=$data[class_name]"); } else { if(version_compare($installedVersion, $data['module_version']) < 0) { $this->message($this->_('An update to this module is available!')); } else { $moduleVersionNote = " <span class='ui-state-error-text'>(" . $this->_('older than the one you already have installed!') . ")</span>"; } } } else { $installedVersion = $this->_x('Not yet', 'install-table'); } $table = $this->wire('modules')->get('MarkupAdminDataTable'); $table->setEncodeEntities(false); $table->row(array($this->_x('Class', 'install-table'), $this->wire('sanitizer')->entities($data['class_name']))); $table->row(array($this->_x('Version', 'install-table'), $this->wire('sanitizer')->entities($data['module_version']) . $moduleVersionNote)); $table->row(array($this->_x('Installed?', 'install-table'), $installedVersion)); $table->row(array($this->_x('Authors', 'install-table'), $this->wire('sanitizer')->entities($authors))); $table->row(array($this->_x('Summary', 'install-table'), $this->wire('sanitizer')->entities($data['summary']))); $table->row(array($this->_x('Release State', 'install-table'), $this->wire('sanitizer')->entities($data['release_state']['title']))); $table->row(array($this->_x('Compatibility', 'install-table'), $this->wire('sanitizer')->entities($compat))); // $this->message("<pre>" . print_r($data, true) . "</pre>", Notice::allowMarkup); $installable = true; if(!empty($data['requires_versions'])) { $requiresVersions = array(); foreach($data['requires_versions'] as $name => $requires) { list($op, $ver) = $requires; $label = $ver ? $this->sanitizer->entities("$name $op $ver") : $this->sanitizer->entities($name); if($this->modules->isInstalled("$name$op$ver") || in_array($name, $data['installs'])) { // installed $requiresVersions[] = "$label <i class='fa fa-fw fa-thumbs-up'></i>"; } else if($this->modules->isInstalled($name)) { // installed, but version isn't adequate $installable = false; $info = $this->modules->getModuleInfo($name); $requiresVersions[] = $this->sanitizer->entities($name) . " " . $this->modules->formatVersion($info['version']) . " " . "<span class='ui-state-error-text'>" . $this->sanitizer->entities("$op $ver") . " " . "<i class='fa fa-fw fa-thumbs-down'></i></span>"; } else { // not installed at all $requiresVersions[] = "<span class='ui-state-error-text'>$label <i class='fa fa-fw fa-thumbs-down'></i></span>"; $installable = false; } } $table->row(array($this->_("Requires"), implode('<br />', $requiresVersions))); if(!$installable) $this->error("Module is not installable because not all required dependencies are currently met."); } if(!empty($data['installs'])) { $installs = $this->sanitizer->entities(implode("\n", $data['installs'])); $table->row(array($this->_("Installs"), nl2br($installs))); } $links = array(); $moduleName = $this->wire('sanitizer')->entities1($data['name']); if($data['module_home']) { $moduleURL = $this->wire('sanitizer')->entities($data['forum_url']); $links[] = "<a target='_blank' href='$moduleURL'>" . $this->_('More Information') . "</a>"; } if($data['project_url']) { $projectURL = $this->wire('sanitizer')->entities($data['project_url']); $links[] = "<a target='_blank' href='$projectURL'>" . $this->_('Project Page') . "</a>"; } if($data['forum_url']) { $forumURL = $this->wire('sanitizer')->entities($data['forum_url']); $links[] = "<a target='_blank' href='$forumURL'>" . $this->_('Support Page') . "</a>"; } if(count($links)) $table->row(array($this->_x('Links', 'install-table'), implode(' / ', $links))); if($data['download_url']) { $downloadURL = $this->wire('sanitizer')->entities($data['download_url']); $table->row(array($this->_x('ZIP file', 'install-table'), $downloadURL)); $warnings[] = $this->_('Ensure that you trust the source of the ZIP file above before continuing!'); } else { $warnings[] = $this->_('This module has no download URL specified and must be installed manually.'); } foreach($warnings as $warning) { $table->row(array($this->_x('Please Note', 'install-table'), "<strong class='ui-state-error-text'> $warning</strong>")); } $markup->value = $table->render(); if($installable && $data['download_url']) { $btn = $this->wire('modules')->get('InputfieldSubmit'); $btn->attr('id+name', 'godownload'); $btn->value = $this->_("Download and install"); $btn->icon = 'cloud-download'; $btn->value .= " ($data[module_version])"; $form->add($btn); $this->session->ProcessModuleDownloadURL = $data['download_url']; $this->session->ProcessModuleClassName = $data['class_name']; } else { $this->session->remove('ProcessModuleDownloadURL'); $this->session->remove('ProcessModuleClassName'); } $btn = $this->wire('modules')->get('InputfieldButton'); $btn->attr('name', 'cancel'); $btn->href ="./edit?name=$data[class_name]"; $btn->value = $this->_("Cancel"); $btn->icon = 'times-circle'; $btn->class .= ' ui-priority-secondary'; $form->add($btn); $form->description = $this->wire('sanitizer')->entities($data['title']); return $form; } /** * Format a module version number from 999 to 9.9.9 * * @param string $version * @return string * */ protected function formatVersion($version) { return $this->wire('modules')->formatVersion($version); } } Created with massive theft of code from ProcessModule.module I'm going to toy around with this in our local environment and see if I can stitch together a nice workflow with the local git repo and a post-receive hook (once I find the time).1 point
-
I have been the webmaster for my company's websites for over seven years using the eZ Publish (www.ez.no) CMS but now my Marketing Department wants a responsive site, which eZ Publish v4 does not do. v5 is supposed to be responsive but they want an arm and a leg for it so I am now looking for a different, more modern solution. I like the looks of Processwire and am trying it out using a Windows IIS 7 web server (a requirement by the IT department where I work. ) Thanks to everyone who has posted here, especially nikola and jamestflynn. Here's an update for those using later software versions: To successfully install Processwire v2.6.1-Master on a Windows IIS 7 Web Server with: PHP v5.6.9 MySql v5.7 Copy the following XML into a file called web.config at the ProcessWire root directory (Most of this file is from user nikola's post from June 19, 2011 with a couple of sections deleted): -------- begin snip ---------------------------------------------------------------- <?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <directoryBrowse enabled="false" /> <rewrite> <rules> <rule name="Handle request for missing favicon.ico" stopProcessing="true"> <match url="favicon\.ico" /> <action type="CustomResponse" statusCode="404" subStatusCode="1" statusReason="The requested file favicon.ico was not found" statusDescription="The requested file favicon.ico was not found" /> </rule> <rule name="Handle request for missing robots.txt" stopProcessing="true"> <match url="robots\.txt" /> <action type="CustomResponse" statusCode="404" subStatusCode="1" statusReason="The requested file robots.txt was not found" statusDescription="The requested file robots.txt was not found" /> </rule> <rule name="Access Restrictions: Keep web users out of directories"> <match url="(^|/)\." ignoreCase="false" /> <action type="CustomResponse" statusCode="403" statusReason="Forbidden" statusDescription="Forbidden" /> </rule> <rule name="Access Restrictions: Protect ProcessWire system files" stopProcessing="true"> <match url="^.*$" ignoreCase="false" /> <conditions logicalGrouping="MatchAny"> <add input="{URL}" pattern="(^|/)site/assets/(cache|logs|backups|sessions|config|install)($|/.*$)" ignoreCase="false" /> <add input="{URL}" pattern="(^|/)site/install($|/.*$)" ignoreCase="false" /> <add input="{URL}" pattern="(^|/)site/config\.php$" ignoreCase="false" /> <add input="{URL}" pattern="(^|/)(wire|site)/templates-admin($|/|/.*\.(php|html?|tpl|inc))$" ignoreCase="false" /> <add input="{URL}" pattern="(^|/)site/templates($|/|/.*\.(php|html?|tpl|inc))$" ignoreCase="false" /> <add input="{URL}" pattern="(^|/)site/assets($|/|/.*\.php)$" ignoreCase="false" /> <add input="{URL}" pattern="(^|/)wire/(core|modules)/.*\.(php|inc|tpl|module)$" ignoreCase="false" /> <add input="{URL}" pattern="(^|/)site/modules/.*\.(php|inc|tpl|module)$" ignoreCase="false" /> <add input="{URL}" pattern="(^|/)(COPYRIGHT|INSTALL|README|htaccess)\.txt$" ignoreCase="false" /> <add input="{URL}" pattern="(^|/)site-default/" ignoreCase="false" /> </conditions> <action type="CustomResponse" statusCode="403" statusReason="Forbidden" statusDescription="Forbidden" /> </rule> <rule name="ProcessWire Rewrite" stopProcessing="true"> <match url="^(.*)$" ignoreCase="false" /> <conditions logicalGrouping="MatchAll"> <add input="{URL}" pattern="^/~?[-_.a-zA-Z0-9/]*$" ignoreCase="false" /> <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" /> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" /> <add input="{REQUEST_FILENAME}" pattern="(favicon\.ico|robots\.txt)" ignoreCase="false" negate="true" /> <add input="{URL}" pattern="\.(gif|jpg|png|ico)$" negate="true" /> </conditions> <action type="Rewrite" url="index.php?it={R:1}" appendQueryString="true" /> </rule> </rules> </rewrite> <defaultDocument> <files> <add value="index.php" /> </files> </defaultDocument> </system.webServer> </configuration> -------- end snip ---------------------------------------------------------------- As mentioned in several of the posts above, be sure to have the IIS URL Rewrite Module 2.0 installed. Also, before starting the installation you will need to replace some values in the .sql database installation commands located in the various site-*/install/install.sql files. In the definition of the "modules" and "pages" tables and in the insertions for the "modules" table replace the default and inserted values for the "created" field, which is a timestamp data type field. The values supplied are all '0000-00-00 00:00:00' which is outside the allowed range for a timestamp type field in this version of MySQL (see https://dev.mysql.com/doc/refman/5.0/en/datetime.html). Replace these zero values with a value within the Unix Epoch, like '1970-01-01 00:00:01'. Begin the installation and ignore the warning about "Unable to determine if Apache mod_rewrite (required by ProcessWire) is installed." Of course it can't be found because we aren't running Apache. Have fun!1 point