diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..cdbb8f86 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +.DS_Store? +.DS_Store +*.old +*.old/* +*.new +*.new/* +old +old/* +*[a-z].1 +*[a-z].1/* +sess_* +*.cache +*.swp +*.swo +site-default/config-dev.php +site-default/assets/logs +site-default/assets/files +site-default/assets/sessions +site-default/assets/cache +site-default/assets/installed.php +site +site-skyscrapers +.htaccess +tmp +upgrade.php +.idea +.svn +.sass-cache +.sass-cache/* +*.css.map +wire/modules/AdminTheme/AdminThemeDefault/styles/sass/*.css +composer.lock +*.min.min.js +wire/modules/Inputfield/InputfieldDatetime/timepicker/i18n/*.min.js +wire/modules/Inputfield/InputfieldDatetime/jquery-ui-timepicker-addon.min.js +wire/modules/Jquery/JqueryFancybox/ +wire/modules/Jquery/JqueryTableSorter/JqueryTableSorter.min.js +pwx.php diff --git a/LICENSE.TXT b/LICENSE.TXT new file mode 100644 index 00000000..094ee521 --- /dev/null +++ b/LICENSE.TXT @@ -0,0 +1,431 @@ +ProcessWire License Information +=============================== + +Unless otherwise stated, all files in ProcessWire's default site +profiles (/site*/*) are MIT licensed, and all files in ProcessWire's +core (/wire/* and /index.php) are MPL 2.0 licensed. Some of +ProcessWire's core framework files are MIT licensed (where +specifically indicated in file header), but if you need a single +license to refer to the product, use MPL 2.0. + +Original works that you create in /site/ (such as templates, modules +and so on) are not bound to licenses used by ProcessWire, and you may +choose to license them however you wish. Likewise, 3rd party modules +by other authors in /site/modules/ may use different licenses where +indicated. + +For more about ProcessWire licenses, HTML versions, and additional +information for 3rd party files, please see: +https://processwire.com/about/license/ + +The full text of the MPL 2.0 and MIT licenses are included in this +document below. + + +Mozilla Public License (MPL) Version 2.0 +======================================== +https://www.mozilla.org/en-US/MPL/2.0/ + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. + + + + +MIT LICENSE +=========== +Applicable where MIT License is indicated at the top of given files in +the ProcessWire core, or to ProcessWire's default site profiles located +in the included /site*/* directories. + +https://processwire.com/about/license/mit/ + +The MIT License (MIT) + +Copyright (c) 2015 Ryan Cramer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md index 9bf153c9..35e4b110 100644 --- a/README.md +++ b/README.md @@ -1 +1,490 @@ -# processwire +# Welcome to ProcessWire 3.x / 2.8.x + +This document is in Markdown. An HTML formatted version of this document +can be read at: https://github.com/processwire/processwire/blob/master/README.md + +## Table of Contents + +1. [About ProcessWire](#about-processwire) +2. [Installing ProcessWire](#installation) + - [Requirements](#requirements) + - [Installation from ZIP file](#installation-from-zip-file) + - [Installation from GitHub](#installation-from-github) + - [Troubleshooting Installation](#troubleshooting-installation) + - [The homepage works but nothing else does](#the-homepage-works-but-nothing-else-does) + - [Resolving an Apache 500 error](#resolving-an-apache-500-error) + - [Resolving other error messages or a blank screen](#resolving-other-error-messages-or-a-blank-screen) +3. [Upgrading ProcessWire](#upgrades) + - [Best Practices Before Upgrading](#best-practices-before-upgrading) + - [General Upgrade Process](#general-upgrade-process) + - [Replacing the /wire/ directory](#replacing-the-wire-directory) + - [Replacing the /index.php file](#replacing-the-indexphp-file) + - [Replacing the .htaccess file](#replacing-the-htaccess-file) + - [Additional upgrade notes](#additional-upgrade-notes) + - [Upgrading from ProcessWire 2.7](#upgrading-from-processwire-27) + - [Upgrading from ProcessWire 2.6](#upgrading-from-processwire-26) + - [Upgrading from ProcessWire 2.5](#upgrading-from-processwire-25) + - [Upgrading from ProcessWire 2.4](#upgrading-from-processwire-24) + - [Upgrading from ProcessWire 2.2 or 2.3](#upgrading-from-processwire-22-or-23) + - [Upgrading from ProcessWire 2.1](#upgrading-from-processwire-21) + - [Upgrading from ProcessWire 2.0](#upgrading-from-processwire-20) + - [Troubleshooting an Upgrade](#troubleshooting-an-upgrade) +4. [Debug Mode](#debug-mode) +5. [Support](#support) + +## About ProcessWire + +ProcessWire is an open source content management system (CMS) and web +application framework aimed at the needs of designers, developers and their +clients. ProcessWire gives you more control over your fields, templates and +markup than other platforms, and provides a powerful template system that +works the way you do. Not to mention, ProcessWire's API makes working with +your content easy and enjoyable. Managing and developing a site in +ProcessWire is shockingly simple compared to what you may be used to. + +* [Learn more about ProcessWire](https://processwire.com) +* [Download the latest ProcessWire](https://processwire.com/download/) +* [Get support for ProcessWire](https://processwire.com/talk/) +* [Browse and install ProcessWire modules/plugins](http://modules.processwire.com) +* [Follow @ProcessWire on Twitter](http://twitter.com/processwire/) +* [Contact ProcessWire](https://processwire.com/contact/) +* [API Cheatsheet](http://cheatsheet.processwire.com/) +* [Sites running ProcessWire](https://processwire.com/about/sites/) +* [Read the ProcessWire Blog](https://processwire.com/blog/) + +## Installation + +### Requirements + +* A web server running Apache. +* PHP version 5.3.8 or newer. +* MySQL 5.0.15 or newer. +* Apache must have mod_rewrite enabled. +* Apache must support .htaccess files. + + +### Installation from ZIP file + +1. Unzip the ProcessWire installation file to the location where you want it + installed on your web server. + +2. Load the location that you unzipped (or uploaded) the files to in your web + browser. This will initiate the ProcessWire installer. The installer will + guide you through the rest of the installation. + + +### Installation from GitHub + +Git clone ProcessWire to the place where you want to install it: + +``` +git clone https://github.com/processwire/processwire.git +``` + +Load the location where you installed ProcessWire into your browser. +This will initiate the ProcessWire installer. The installer will guide +you through the rest of the installation. + + +### Troubleshooting Installation + +#### The homepage works but nothing else does + +This indicates that Apache is not properly reading your .htaccess file. +First we need to determine if Apache is reading your .htaccess file at all. +To do this, open the .htaccess file in an editor and type in some random +characters at the top, like `lkjalefkjalkef` and save. Load your site in +your browser. You should get a "500 Error". If you do not, that means +Apache is not reading your .htaccess file at all. If this is your case, +contact your web host for further assistance. Or if maintaining your own +server, look into the Apache *AllowOverride* directive which you may need +to configure for the account in your httpd.conf file. + +If the above test did result in a 500 error, then that is good because we +know your .htaccess file is at least being used. Go ahead and remove the +random characters you added at the top. Now look further down in the +.htaccess file for suggested changes. Specially, you will want to look at +the *RewriteBase* directive, which is commented out (disabled) by default. +You may need to enable it. + +#### Resolving an Apache 500 error + +The presence of an Apache 500 error indicates that Apache does not +like one or more of the directives in the .htaccess file. Open the +.htaccess file in an editor and read the comments. Note those that +indicate the term "500 NOTE" and they will provide further instructions +on optional directives you can try to comment out. Test one at a time, +save and reload in your browser till you determine which directive is +not working with your server. + +#### Resolving other error messages or a blank screen + +If you are getting an error message, a blank screen, or something +else unexpected, see the section at the end of this document on +enabling debug mode. This will enable more detailed error reporting +which may help to resolve any issues. + +In addition, the ProcessWire error log is located in the file: +/site/assets/logs/errors.txt - look in here to see if more information +is available about the error message you have received. + +If the above suggestions do not help you to resolve the installation +error, please post in the [ProcessWire forums](http://processwire.com/talk). + + +## Upgrades + +### Best Practices Before Upgrading + +1. Backup your database and backup all the files in your site. +2. When possible, test the upgrade on a development/staging site + before performing the upgrade on a live/production site. +3. Login to your ProcessWire admin under a superuser account before + upgrading. This enables you to see more verbose output during the + upgrade process. +4. If you have 3rd party modules installed, confirm that they are + compatible with the ProcessWire version you are upgrading to. + If you cannot confirm compatibility, uninstall the 3rd party + modules before upgrading, when possible. You can attempt to + re-install them after upgrading. If uninstalling is + inconvenient, just be sure you have the ability to revert if for + some reason one of your modules does not like the upgrade. + Modules that are compatible with ProcessWire 2.4-2.7 are generally + going to also be compatible with 3.0 with a few exceptions. + +If you prefer an automatic/web-based upgrade, an +[upgrade module](https://github.com/ryancramerdesign/ProcessWireUpgrade) +is available. This upgrade utility can also help with upgrading other +modules as well. However, the upgrade from 2.x to 3.x is a major upgrade +and we recommend performing this upgrade manually rather than with any +automated tools. + + +### General Upgrade Process + +Before upgrading, login to your ProcessWire admin under a superuser +account. This is not required to upgrade, but is recommended for more +verbose output during the upgrade. + +Upgrading from one version of ProcessWire to another is a matter of +deleting these files/directories from your old version, and putting +in fresh copies from the new version: + +``` +/wire/ +/index.php +/.htaccess +``` + +Removing and replacing the above directory/files is typically the +primary thing you need to do in order to upgrade. But please see +the version-to-version specific upgrade notes documented further +in this section. Further below are more details about how you should +replace the files mentioned above. + +After replacing the /wire/ directory (and the other two files if needed), +hit reload in your browser, anywhere in the ProcessWire admin. You +should see messages at the top of your screen about updates that were +applied. Depending on which version you are upgrading from, you might +also see error messages--this is normal. Keep hitting reload in your +browser until you no longer see any upgrade related messages (up to 5 +reloads may be necessary). + +*NOTE: Renaming is an alternative to deleting, which gives you a quicker +path to revert should you want to. For example, you might rename +your /wire/ directory to be /.wire-2.4.0/ with ".wire" rather than +"wire" to ensure the directory is hidden, and the 2.4.0 indicating the +version that it was. Once your upgrade is safely in place, you could +delete that .wire-2.4.0 directory (or keep it around). If you keep old +version dirs/files in place, make sure they are not http accessible. +This is typically done by preceding the directory with a period to make +it hidden.* + + +#### Replacing the /wire/ directory + +When you put in the new /wire/ directory, make sure that you remove or +rename the old one first. If you just copy or FTP changed files into +the existing /wire/ directory, you will end up with both old and new +files, which will cause an error. + +Note that the /wire/ directory does not contain any files specific to +your site, only to ProcessWire. All the files specific to your site +are stored in /site/ and you would leave that directory alone during +an upgrade. + + +#### Replacing the /index.php file + +This file doesn't change often between minor versions. As a result, +you don't need to replace this file unless it has changed. But when +in doubt, you should replace it. + + +#### Replacing the .htaccess file + +This is also a file that does not always change between versions. +But when it changes, it is usually important for security that you +are up-to-date. When in doubt, replace your old .htaccess file with +the htaccess.txt from the new version. + +This file is initially named htaccess.txt in the ProcessWire source. +You will want to remove your existing .htaccess file and rename the +new htaccess.txt to .htaccess + +Sometimes people have made changes to the .htaccess file. If this is +the case for your site, remember to migrate those changes to the new +.htaccess file. + +**If using ProCache** +If you are using ProCache, it will have added some things to your +.htaccess file. Copy these changes from your old .htaccess file to +your new one. The changes are easy to identify in your previous +.htaccess file as they start and end with a "# ProCache" comment. +Alternatively, you can have ProCache re-apply the changes itself by +logging in to your admin and going to Setup > ProCache. + + +#### Additional upgrade notes + +- Completing an upgrade typically requires hitting reload in your + browser 1-5 times to apply database updates. If logged into your + admin, you will see notices about the updates that it is applying + on each reload. + +- After completing the upgrade test out your site thoroughly + to make sure everything continues to work as you expect. + +- If using Form Builder make sure you have the latest version, + as past versions did not support ProcessWire 2.4+. With ProcessWire + 3.0 we recommend FormBuilder 0.2.6+. + +- If using ProCache and you upgraded your .htaccess file, you should + go to your ProCache settings after the upgrade to have it update + your .htaccess file again. If no upgrades to your .htaccess file + are necessary, than the ProCache settings page own't mention it. + +- If using ListerPro, we recommend using version 1.0.9+ with + ProcessWire 3.x. + + +### Upgrading from ProcessWire 2.7 + +**Upgrading from 2.7 to 3.x** + +1. Login to the admin of your site. + +2. Edit your /site/config.php and set `$config->debug = true;` to ensure you can + see error messages. + +3. Replace your /wire/ directory and /index.php file with the ones from here. + Don't forget the /index.php as it is definitely required (it will tell you + if you forget). + +4. Click a tab page in your admin, such as "Pages". You may notice a delay. + This is ProcessWire compiling 3rd party modules into a format that is + compatible with version 3.x. Keep an eye out for any error messages. + If you see any issues, it's possible you may need to upgrade one or more + 3rd party modules. + +5. Once you've resolved error messages in your admin, you'll want to test out + the front end of your site. Again, expect a delay while ProcessWire compiles + any files to make them compatible with 3.x. Depending on your template file + strategy, updates may or may not be necessary. If you run into any pages + that aren't working, see the section further down on troubleshooting. + +6. When you've confirmed a successful upgrade, remember to restore the + `$config->debug` setting back to `false` in your /site/config.php file. + + +**Upgrading from 2.7 to 2.8.x** +Follow the general upgrade process by replacing your /wire/ directory and +index.php file with the new versions. After confirming successful upgrade, then replace or +update your .htaccess file (with the new provided htaccess.txt file). + +**Troubleshooting a 2.7 to 3.x upgrade** +Before we mention anything else, if you run into any troubles with the 3.x +upgrade, you may want to consider upgrading to version 2.8.x instead. It is identical +to 3.x in terms of features, except that it lacks namespace support (just like 2.7). +Because of that omission, version 2.8 may be more of a turn-key upgrade from 2.7 +if that is your preference. + +Any error messages you see in 3.x are likely related to the fact that this +version of the core is now running in a namespace called ProcessWire, rather than +in the root PHP namespace. Error messages will likely mention a file in your +/site/modules/ directory or a file in your /site/templates/ directory. + +ProcessWire attempts to compile any module or template PHP files that it thinks +will have issues due to namespace. This should work well in most instances. +However, if you come across any instances where it does not work, you may need +to add the ProcessWire namespace to your file. To add the namespace to a file, +simply edit the file and add this at the very top: + +`````````` +`. If this is your case, please delete or + comment out this line in your .htaccess file: + `Header always append X-Frame-Options SAMEORIGIN` + +- **TinyMCE rich text editor was replaced with CKEditor** + 2.5 dropped TinyMCE as the rich text editor and replaced it with + CKEditor. After installation of 2.7+, you will see an error message + on any pages that use TinyMCE. From this point, you may either + [install TinyMCE](mods.pw/7H) or switch your fields using TinyMCE + to CKEditor. To switch to CKEditor, go to Setup > Fields > [field] > Details, + and change the *Inputfield Type* to CKEditor (it may already be + selected), then be sure to Save. + +- **Already have CKEditor or HTML Purifier installed?** + A couple of modules that were previously 3rd party (site) modules + are now core (wire) modules in ProcessWire 2.7+. If you have either + the *InputfieldCKEditor* or *MarkupHTMLPurifier* modules installed, + you will get warnings about that after upgrading. The warnings will + tell you to remove the dirs/files for those modules that you have in + /site/modules/. Don't be alarmed, as this is not an error, just a + warning notice. But it is a good idea to remove duplicate copies + of these modules when possible. + + +### Upgrading from ProcessWire 2.2 or 2.3 + +Newer versions of ProcessWire have these additional requirements: + +- PHP 5.3.8+ (older versions supported PHP 5.2) +- PDO database driver (older versions only used mysqli) + +Please confirm your server meets these requirements before upgrading. +If you are not certain, paste the following into a test PHP file and +load it from your browser: + +``` +httpHosts = array('domain.com', 'www.domain.com'); +``` +Replace domain.com with the hostname(s) your site runs from. + + +### Upgrading from ProcessWire 2.1 + +1. First upgrade to [ProcessWire 2.2](https://github.com/ryancramerdesign/ProcessWire/tree/2.2.9). +2. Follow the instructions above to upgrade from ProcessWire 2.2. + + +### Upgrading from ProcessWire 2.0 + +1. [Download ProcessWire 2.2](https://github.com/ryancramerdesign/ProcessWire/tree/2.2.9) + and follow the upgrade instructions in that version's [README](https://github.com/ryancramerdesign/ProcessWire/blob/2.2.9/README.txt) + file to upgrade from 2.0 to 2.2. +2. After successfully upgrading to 2.2, follow the general upgrade + process above. + + +### Troubleshooting an Upgrade + +If you get an error message when loading your site after an upgrade, +hit "reload" in your browser until the error messages disappear. It +may take up to 5 reloads for ProcessWire to apply all updates. + +If using Form Builder, make sure you have version 0.2.5 or newer, as older +versions did not support ProcessWire 3.x. + +If your site still doesn't work, remove the /wire/ directory completely. +Then upload a fresh copy of the /wire/ directory. + +If your site still doesn't work, view the latest entries in your error +log file to see if it clarifies anything. The error log can be found in: +/site/assets/logs/errors.txt + +If your site still doesn't work, enable debug mode (as described in the +next section) to see if the more verbose error messages help you to determine +what the issue is. If you need help, please post in the +[ProcessWire support forums](http://processwire.com/talk/). + + +## Debug Mode + +Debug mode causes all errors to be reported to the screen, which can be +helpful during development or troubleshooting. When in the admin, it also +enables reporting of extra information in the footer. Debug mode is not +intended for live or production sites, as the information reported could +be a problem for security. So be sure not to leave debug mode on for +any live/production sites. + +1. Edit this file: `/site/config.php` +2. Find this line: `$config->debug = false;` +3. Change the `false` to `true`, like below, and save. + +``` +$config->debug = true; +``` + +This can be found near the bottom of the file, or you can add it if not +already there. It will make PHP and ProcessWire report all errors, warnings, +notices, etc. Of course, you'll want to set it back to false once you've +resolved any issues. + + +## Support + +Get support in the ProcessWire forum at: +[https://processwire.com/talk/](https://processwire.com/talk/) + +------ + +Copyright 2016 by Ryan Cramer / Ryan Cramer Design, LLC + diff --git a/composer.json b/composer.json new file mode 100644 index 00000000..5556b5ce --- /dev/null +++ b/composer.json @@ -0,0 +1,23 @@ +{ + "name": "processwire/processwire", + "type": "library", + "description": "ProcessWire CMS/CMF", + "keywords": [ "cms","cmf", "content management system" ], + "homepage": "https://processwire.com", + "authors": [ + { + "name": "Ryan Cramer", + "email": "ryan@processwire.com", + "homepage": "https://processwire.com", + "role": "Developer" + } + ], + "require": { + "php": ">=5.3.8", + "ext-gd": "*" + }, + "autoload": { + "files": [ "wire/core/ProcessWire.php" ] + }, + "minimum-stability": "dev" +} \ No newline at end of file diff --git a/htaccess.txt b/htaccess.txt new file mode 100644 index 00000000..e8182f1a --- /dev/null +++ b/htaccess.txt @@ -0,0 +1,226 @@ +################################################################################################# +# START PROCESSWIRE HTACCESS DIRECTIVES +# @version 3.0 +# @indexVersion 300 +################################################################################################# + +# ----------------------------------------------------------------------------------------------- +# 1. Don't show directory indexes, but do follow symbolic links +# 500 NOTE: Some cloud hosting companies don't allow +FollowSymLinks. +# Uncomment +SymLinksifOwnerMatch and comment +FollowSymLinks if you have 500 errors. +# If that doesn't resolve the error, then set it back to +FollowSymLinks. +# ----------------------------------------------------------------------------------------------- + +Options -Indexes +Options +FollowSymLinks +# Options +SymLinksifOwnerMatch + +# ----------------------------------------------------------------------------------------------- +# 2. Let ProcessWire handle 404s +# ----------------------------------------------------------------------------------------------- + +ErrorDocument 404 /index.php + +# ----------------------------------------------------------------------------------------------- +# 3. Handle request for missing favicon.ico/robots.txt files (no ending quote for Apache 1.3) +# ----------------------------------------------------------------------------------------------- + + + ErrorDocument 404 "The requested file favicon.ico was not found. + + + + ErrorDocument 404 "The requested file robots.txt was not found. + + +# ----------------------------------------------------------------------------------------------- +# 4. Protect from XSS with Apache headers +# ----------------------------------------------------------------------------------------------- + + + # prevent site from being loaded in an iframe on another site + # you will need to remove this one if you want to allow external iframes + Header always append X-Frame-Options SAMEORIGIN + + # to prevent cross site scripting (IE8+ proprietary) + Header set X-XSS-Protection "1; mode=block" + + # prevent mime-based attacks via content sniffing (IE+Chrome) + # Header set X-Content-Type-Options "nosniff" + + +# ----------------------------------------------------------------------------------------------- +# 5. Protect ProcessWire system files +# ----------------------------------------------------------------------------------------------- + + + + Require all denied + + + Order allow,deny + + + +# ----------------------------------------------------------------------------------------------- +# 6. Override a few PHP settings that can't be changed at runtime (not required) +# 500 NOTE: Try commenting out this entire section below if getting Apache 500 errors. +# ----------------------------------------------------------------------------------------------- + + + php_flag magic_quotes_gpc off + php_flag magic_quotes_sybase off + php_flag register_globals off + + +# ----------------------------------------------------------------------------------------------- +# 7. Set default directory index files +# ----------------------------------------------------------------------------------------------- + +DirectoryIndex index.php index.html index.htm + +# ----------------------------------------------------------------------------------------------- +# 8. ProcessWire requires mod_rewrite +# ----------------------------------------------------------------------------------------------- + + + + RewriteEngine On + AddDefaultCharset UTF-8 + + # ----------------------------------------------------------------------------------------------- + # 9. If you only want to allow HTTPS, uncomment the RewriteCond and RewriteRule lines below. + # ----------------------------------------------------------------------------------------------- + # RewriteCond %{HTTPS} off + # RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] + + # ----------------------------------------------------------------------------------------------- + # 10. Set an environment variable so the installer can detect that mod_rewrite is active. + # Note that some web hosts don't support this. If you get a 500 error, you might try + # commenting out this SetEnv line below. + # ----------------------------------------------------------------------------------------------- + + + SetEnv HTTP_MOD_REWRITE On + + + # ----------------------------------------------------------------------------------------------- + # 11. OPTIONAL: Set a rewrite base if rewrites aren't working properly on your server. + # And if your site directory starts with a "~" you will most likely have to use this. + # ----------------------------------------------------------------------------------------------- + + # RewriteBase / + # RewriteBase /pw/ + # RewriteBase /~user/ + + # ----------------------------------------------------------------------------------------------- + # 12. Access Restrictions: Keep web users out of dirs that begin with a period, + # but let services like Lets Encrypt use the webroot authentication method. + # ----------------------------------------------------------------------------------------------- + + RewriteRule "(^|/)\.(?!well-known)" - [F] + + # ----------------------------------------------------------------------------------------------- + # 13. OPTIONAL: Redirect users to the 'www.' version of the site (uncomment to enable). + # For example: http://processwire.com/ would be redirected to http://www.processwire.com/ + # ----------------------------------------------------------------------------------------------- + + # RewriteCond %{HTTP_HOST} !^www\. [NC] + # RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301] + + # ----------------------------------------------------------------------------------------------- + # 14. OPTIONAL: Send URLs with non-ASCII name-format characters to 404 page (optimization) + # ----------------------------------------------------------------------------------------------- + + # RewriteCond %{REQUEST_URI} "[^-_.a-zA-Z0-9/~]" + # RewriteCond %{REQUEST_FILENAME} !-f + # RewriteCond %{REQUEST_FILENAME} !-d + # RewriteRule ^(.*)$ index.php?it=/http404/ [L,QSA] + + # ----------------------------------------------------------------------------------------------- + # 15. Access Restrictions: Protect ProcessWire system files + # ----------------------------------------------------------------------------------------------- + + # Allow screenshot files (for install.php only: this 1 line below may be removed after install) + RewriteCond %{REQUEST_URI} !(^|/)site-[^/]+/install/[^/]+\.(jpg|jpeg|png|gif)$ + # Block access to any htaccess files + RewriteCond %{REQUEST_URI} (^|/)\.htaccess$ [NC,OR] + # Block access to protected assets directories + RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/assets/(cache|logs|backups|sessions|config|install|tmp)($|/.*$) [OR] + # Block acceess to the /site/install/ directory + RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/install($|/.*$) [OR] + # Block dirs in /site/assets/ dirs that start with a hyphen + RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/assets.*/-.+/.* [OR] + # Block access to /wire/config.php, /site/config.php, /site/config-dev.php, and /wire/index.config.php + RewriteCond %{REQUEST_URI} (^|/)(wire|site|site-[^/]+)/(config|index\.config|config-dev)\.php$ [OR] + # Block access to any PHP-based files in /templates-admin/ + RewriteCond %{REQUEST_URI} (^|/)(wire|site|site-[^/]+)/templates-admin($|/|/.*\.(php|html?|tpl|inc))$ [OR] + # Block access to any PHP or markup files in /site/templates/ + RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/templates($|/|/.*\.(php|html?|tpl|inc))$ [OR] + # Block access to any PHP files in /site/assets/ + RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/assets($|/|/.*\.php)$ [OR] + # Block access to any PHP files in core or core module directories + RewriteCond %{REQUEST_URI} (^|/)wire/(core|modules)/.*\.(php|inc|tpl|module|info\.json)$ [OR] + # Block access to any PHP files in /site/modules/ + RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/modules/.*\.(php|inc|tpl|module|info\.json)$ [OR] + # Block access to any software identifying txt files + RewriteCond %{REQUEST_URI} (^|/)(COPYRIGHT|INSTALL|README|htaccess)\.(txt|md|textile)$ [OR] + # Block all http access to the default/uninstalled site-default directory + RewriteCond %{REQUEST_URI} (^|/)site-default/ + # If any conditions above match, issue a 403 forbidden + RewriteRule ^.*$ - [F,L] + + # PW-PAGENAME + # ----------------------------------------------------------------------------------------------- + # 16a. Ensure that the URL follows the name-format specification required by PW + # See also directive 16b below, you should choose and use either 16a or 16b. + # ----------------------------------------------------------------------------------------------- + + RewriteCond %{REQUEST_URI} "^/~?[-_.a-zA-Z0-9/]*$" + + # ----------------------------------------------------------------------------------------------- + # 16b. Alternative name-format specification for UTF8 page name support. + # If used, comment out section 16a above and uncomment the directive below. If you have updated + # your $config->pageNameWhitelist make the characters below consistent with that. + # ----------------------------------------------------------------------------------------------- + + # RewriteCond %{REQUEST_URI} "^/~?[-_./a-zA-Z0-9æåäßöüđжхцчшщюяàáâèéëêěìíïîõòóôøùúûůñçčćďĺľńňŕřšťýžабвгдеёзийклмнопрстуфыэęąśłżź]*$" + + # END-PW-PAGENAME + # ----------------------------------------------------------------------------------------------- + # 17. If the request is for a file or directory that physically exists on the server, + # then don't give control to ProcessWire, and instead load the file + # ----------------------------------------------------------------------------------------------- + + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !(favicon\.ico|robots\.txt) + + # ----------------------------------------------------------------------------------------------- + # 18. OPTIONAL: Prevent ProcessWire from attempting to serve images or anything in /site/assets/. + # Both of these lines are optional, but can help to reduce server load. However, they + # are not compatible with the $config->pagefileSecure option (if enabled) and they + # may produce an Apache 404 rather than your regular 404. You may uncomment the two lines + # below if you don't need to use the $config->pagefileSecure option. + # ----------------------------------------------------------------------------------------------- + + # RewriteCond %{REQUEST_FILENAME} !\.(jpg|jpeg|gif|png|ico)$ [NC] + # RewriteCond %{REQUEST_FILENAME} !(^|/)site/assets/ + + # ----------------------------------------------------------------------------------------------- + # 19. Pass control to ProcessWire if all the above directives allow us to this point. + # For regular VirtualHosts (most installs) + # ----------------------------------------------------------------------------------------------- + RewriteRule ^(.*)$ index.php?it=$1 [L,QSA] + + # ----------------------------------------------------------------------------------------------- + # 20. If using VirtualDocumentRoot (500 NOTE): comment out the one above and use this one instead + # ----------------------------------------------------------------------------------------------- + # RewriteRule ^(.*)$ /index.php?it=$1 [L,QSA] + + + +################################################################################################# +# END PROCESSWIRE HTACCESS DIRECTIVES +################################################################################################# + diff --git a/index.php b/index.php new file mode 100644 index 00000000..a53bd32e --- /dev/null +++ b/index.php @@ -0,0 +1,66 @@ +debugIf option. + * 250 PW 2.5 support. + * + */ + +if(!defined("PROCESSWIRE")) define("PROCESSWIRE", 300); // index version +$rootPath = __DIR__; +if(DIRECTORY_SEPARATOR != '/') $rootPath = str_replace(DIRECTORY_SEPARATOR, '/', $rootPath); +$composerAutoloader = $rootPath . '/vendor/autoload.php'; // composer autoloader +if(file_exists($composerAutoloader)) require_once($composerAutoloader); +if(!class_exists("ProcessWire", false)) require_once("$rootPath/wire/core/ProcessWire.php"); +$config = ProcessWire::buildConfig($rootPath); + +if(!$config->dbName) { + // If ProcessWire is not installed, go to the installer + if(is_file("./install.php") && strtolower($_SERVER['REQUEST_URI']) == strtolower($config->urls->root)) { + require("./install.php"); + exit(0); + } else { + header("HTTP/1.1 404 Page Not Found"); + echo "404 page not found (no site configuration or install.php available)"; + exit(0); + } +} + +$process = null; +$wire = null; + +try { + // Bootstrap ProcessWire's core and make the API available with $wire + $wire = new ProcessWire($config); + $process = $wire->modules->get('ProcessPageView'); + $wire->wire('process', $process); + echo $process->execute($config->internal); + $config->internal ? $process->finished() : extract($wire->wire('all')->getArray()); + +} catch(\Exception $e) { + // Formulate error message and send to the error handler + if($process) $process->failed($e); + $wire ? $wire->trackException($e) : $config->trackException($e); + $errorMessage = "Exception: " . $e->getMessage() . " (in " . $e->getFile() . " line " . $e->getLine() . ")"; + if($config->debug || ($wire && $wire->user && $wire->user->isSuperuser())) $errorMessage .= "\n\n" . $e->getTraceAsString(); + trigger_error($errorMessage, E_USER_ERROR); +} + diff --git a/install.php b/install.php new file mode 100644 index 00000000..4793639d --- /dev/null +++ b/install.php @@ -0,0 +1,1270 @@ +initProfile(); break; + + case 1: $this->compatibilityCheck(); break; + + case 2: $this->dbConfig(); break; + + case 4: $this->dbSaveConfig(); break; + + case 5: require("./index.php"); + $this->adminAccountSave($wire); + break; + + default: + $this->welcome(); + + } else $this->welcome(); + + require("./wire/modules/AdminTheme/AdminThemeDefault/install-foot.inc"); + } + + + /** + * Welcome/Intro screen + * + */ + protected function welcome() { + $this->h("Welcome. This tool will guide you through the installation process."); + $this->p("Thanks for choosing ProcessWire! If you downloaded this copy of ProcessWire from somewhere other than processwire.com or our GitHub page, please download a fresh copy before installing. If you need help or have questions during installation, please stop by our support board and we'll be glad to help."); + $this->btn("Get Started", 0, 'sign-in'); + } + + + /** + * Check if the given function $name exists and report OK or fail with $label + * + */ + protected function checkFunction($name, $label) { + if(function_exists($name)) $this->ok("$label"); + else $this->err("Fail: $label"); + } + + /** + * Find all profile directories (site-*) in the current dir and return info array for each + * + * @return array + * + */ + protected function findProfiles() { + $profiles = array( + 'site-beginner' => null, + 'site-default' => null, // preferred starting order + 'site-languages' => null, + 'site-blank' => null + ); + $dirTests = array( + 'install', + 'templates', + 'assets', + ); + $fileTests = array( + 'config.php', + 'templates/admin.php', + 'install/install.sql', + ); + foreach(new \DirectoryIterator(dirname(__FILE__)) as $dir) { + if($dir->isDot() || !$dir->isDir()) continue; + $name = $dir->getBasename(); + $path = rtrim($dir->getPathname(), '/') . '/'; + if(strpos($name, 'site-') !== 0) continue; + $passed = true; + foreach($dirTests as $test) if(!is_dir($path . $test)) $passed = false; + foreach($fileTests as $test) if(!file_exists($path . $test)) $passed = false; + if(!$passed) continue; + $profile = array('name' => str_replace('site-', '', $name)); + $infoFile = $path . 'install/info.php'; + if(file_exists($infoFile)) { + include($infoFile); + if(isset($info) && is_array($info)) { + $profile = array_merge($profile, $info); + } + } + $profiles[$name] = $profile; + } + // remove any preferred starting order profiles that weren't present + foreach($profiles as $name => $profile) { + if(is_null($profile)) unset($profiles[$name]); + } + return $profiles; + } + + protected function selectProfile() { + $options = ''; + $out = ''; + $profiles = $this->findProfiles(); + if(!count($profiles)) $this->err("No profiles found!"); + foreach($profiles as $name => $profile) { + $title = empty($profile['title']) ? ucfirst($profile['name']) : $profile['title']; + //$selected = $name == 'site-default' ? " selected='selected'" : ""; + $options .= ""; + $out .= ""; + } + + echo " +

A site installation profile is a ready-to-use and modify site for ProcessWire. + If you are just getting started with ProcessWire, we recommend choosing + the Default site profile. If you already know what you are doing, + you might prefer the Blank site profile. +

+ + Select each installation profile to see more information and a preview. +

+ $out + + "; + + } + + /** + * Step 1a: Determine profile + * + */ + protected function initProfile() { + + $this->h('Site Installation Profile'); + + if(is_file("./site/install/install.sql")) { + $this->ok("Found installation profile in /site/install/"); + + } else if(is_dir("./site/")) { + $this->ok("Found /site/ -- already installed? "); + + } else if(isset($_POST['profile'])) { + + $profiles = $this->findProfiles(); + $profile = preg_replace('/[^-a-zA-Z0-9_]/', '', $_POST['profile']); + if(empty($profile) || !isset($profiles[$profile]) || !is_dir(dirname(__FILE__) . "/$profile")) { + $this->err("Profile not found"); + $this->selectProfile(); + $this->btn("Continue", 0); + return; + } + // $info = $profiles[$profile]; + // $this->h(empty($info['title']) ? ucfirst($info['name']) : $info['title']); + + if(@rename("./$profile", "./site")) { + $this->ok("Renamed /$profile => /site"); + } else { + $this->err("File system is not writable by this installer. Before continuing, please rename '/$profile' to '/site'"); + $this->btn("Continue", 0); + return; + } + + } else { + $this->selectProfile(); + $this->btn("Continue", 0); + return; + } + + $this->compatibilityCheck(); + } + + /** + * Step 1b: Check for ProcessWire compatibility + * + */ + protected function compatibilityCheck() { + + $this->h("Compatibility Check"); + + if(version_compare(PHP_VERSION, self::MIN_REQUIRED_PHP_VERSION) >= 0) { + $this->ok("PHP version " . PHP_VERSION); + } else { + $this->err("ProcessWire requires PHP version " . self::MIN_REQUIRED_PHP_VERSION . " or newer. You are running PHP " . PHP_VERSION); + } + + if(extension_loaded('pdo_mysql')) { + $this->ok("PDO (mysql) database"); + } else { + $this->err("PDO (pdo_mysql) is required (for MySQL database)"); + } + + if(self::TEST_MODE) { + $this->err("Example error message for test mode"); + $this->warn("Example warning message for test mode"); + } + + $this->checkFunction("filter_var", "Filter functions (filter_var)"); + $this->checkFunction("mysqli_connect", "MySQLi (not required by core, but may be required by some 3rd party modules)"); + $this->checkFunction("imagecreatetruecolor", "GD 2.0 or newer"); + $this->checkFunction("json_encode", "JSON support"); + $this->checkFunction("preg_match", "PCRE support"); + $this->checkFunction("ctype_digit", "CTYPE support"); + $this->checkFunction("iconv", "ICONV support"); + $this->checkFunction("session_save_path", "SESSION support"); + $this->checkFunction("hash", "HASH support"); + $this->checkFunction("spl_autoload_register", "SPL support"); + + if(function_exists('apache_get_modules')) { + if(in_array('mod_rewrite', apache_get_modules())) $this->ok("Found Apache module: mod_rewrite"); + else $this->err("Apache mod_rewrite does not appear to be installed and is required by ProcessWire."); + } else { + // apache_get_modules doesn't work on a cgi installation. + // check for environment var set in htaccess file, as submitted by jmarjie. + $mod_rewrite = getenv('HTTP_MOD_REWRITE') == 'On' || getenv('REDIRECT_HTTP_MOD_REWRITE') == 'On' ? true : false; + if($mod_rewrite) { + $this->ok("Found Apache module (cgi): mod_rewrite"); + } else { + $this->err("Unable to determine if Apache mod_rewrite (required by ProcessWire) is installed. On some servers, we may not be able to detect it until your .htaccess file is place. Please click the 'check again' button at the bottom of this screen, if you haven't already."); + } + } + + if(class_exists('\ZipArchive')) { + $this->ok("ZipArchive support"); + } else { + $this->warn("ZipArchive support was not found. This is recommended, but not required to complete installation."); + } + + $dirs = array( + // directory => required? + './site/assets/' => true, + './site/modules/' => false, + ); + foreach($dirs as $dir => $required) { + $d = ltrim($dir, '.'); + if(!file_exists($dir)) { + $this->err("Directory $d does not exist! Please create this and make it writable before continuing."); + } else if(is_writable($dir)) { + $this->ok("$d is writable"); + } else if($required) { + $this->err("Directory $d must be writable. Please adjust the server permissions before continuing."); + } else { + $this->warn("We recommend that directory $d be made writable before continuing."); + } + } + + if(is_writable("./site/config.php")) $this->ok("/site/config.php is writable"); + else $this->err("/site/config.php must be writable. Please adjust the server permissions before continuing."); + + if(!is_file("./.htaccess") || !is_readable("./.htaccess")) { + if(@rename("./htaccess.txt", "./.htaccess")) $this->ok("Installed .htaccess"); + else $this->err("/.htaccess doesn't exist. Before continuing, you should rename the included htaccess.txt file to be .htaccess (with the period in front of it, and no '.txt' at the end)."); + + } else if(!strpos(file_get_contents("./.htaccess"), "PROCESSWIRE")) { + $this->err("/.htaccess file exists, but is not for ProcessWire. Please overwrite or combine it with the provided /htaccess.txt file (i.e. rename /htaccess.txt to /.htaccess, with the period in front)."); + + } else { + $this->ok(".htaccess looks good"); + } + + if($this->numErrors) { + $this->p("One or more errors were found above. We recommend you correct these issues before proceeding or contact ProcessWire support if you have questions or think the error is incorrect. But if you want to proceed anyway, click Continue below."); + $this->btn("Check Again", 1, 'refresh', false, true); + $this->btn("Continue to Next Step", 2, 'angle-right', true); + } else { + $this->btn("Continue to Next Step", 2, 'angle-right', false); + } + } + + /** + * Step 2: Configure the database and file permission settings + * + */ + protected function dbConfig($values = array()) { + + if(!is_file("./site/install/install.sql")) die("There is no installation profile in /site/. Please place one there before continuing. You can get it at processwire.com/download"); + + + $this->h("MySQL Database"); + $this->p("Please specify a MySQL 5.x database and user account on your server. If the database does not exist, we will attempt to create it. If the database already exists, the user account should have full read, write and delete permissions on the database.*"); + $this->p("*Recommended permissions are select, insert, update, delete, create, alter, index, drop, create temporary tables, and lock tables.", "detail"); + + if(!isset($values['dbName'])) $values['dbName'] = ''; + // @todo: are there PDO equivalents for the ini_get()s below? + if(!isset($values['dbHost'])) $values['dbHost'] = ini_get("mysqli.default_host"); + if(!isset($values['dbPort'])) $values['dbPort'] = ini_get("mysqli.default_port"); + if(!isset($values['dbUser'])) $values['dbUser'] = ini_get("mysqli.default_user"); + if(!isset($values['dbPass'])) $values['dbPass'] = ini_get("mysqli.default_pw"); + if(!isset($values['dbEngine'])) $values['dbEngine'] = 'MyISAM'; + + if(!$values['dbHost']) $values['dbHost'] = 'localhost'; + if(!$values['dbPort']) $values['dbPort'] = 3306; + if(empty($values['dbCharset'])) $values['dbCharset'] = 'utf8'; + + foreach($values as $key => $value) { + if(strpos($key, 'chmod') === 0) { + $values[$key] = (int) $value; + } else if($key != 'httpHosts') { + $values[$key] = htmlspecialchars($value, ENT_QUOTES, 'utf-8'); + } + } + + + $this->input('dbName', 'DB Name', $values['dbName']); + $this->input('dbUser', 'DB User', $values['dbUser']); + $this->input('dbPass', 'DB Pass', $values['dbPass'], false, 'password', false); + $this->input('dbHost', 'DB Host', $values['dbHost']); + $this->input('dbPort', 'DB Port', $values['dbPort'], true); + + echo + "
" . + "" . + " Advanced: Charset & Engine …" . + "
"; + + echo ""; + + $cgi = false; + $defaults = array(); + + if(is_writable(__FILE__)) { + $defaults['chmodDir'] = "755"; + $defaults['chmodFile'] = "644"; + $cgi = true; + } else { + $defaults['chmodDir'] = "777"; + $defaults['chmodFile'] = "666"; + } + + $timezone = isset($values['timezone']) ? $values['timezone'] : date_default_timezone_get(); + $timezones = $this->timezones(); + if(!$timezone || !in_array($timezone, $timezones)) { + $timezone = ini_get('date.timezone'); + if(!$timezone || !in_array($timezone, $timezones)) $timezone = 'America/New_York'; + } + + $defaults['timezone'] = $timezone; + $defaults['httpHosts'] = strtolower(filter_var($_SERVER['HTTP_HOST'], FILTER_SANITIZE_URL)); + + if(strpos($defaults['httpHosts'], 'www.') === 0) { + $defaults['httpHosts'] .= "\n" . substr($defaults['httpHosts'], 4); + } else if(substr_count($defaults['httpHosts'], '.') == 1) { + $defaults['httpHosts'] .= "\n" . "www.$defaults[httpHosts]"; + } + if($_SERVER['SERVER_NAME'] && $_SERVER['SERVER_NAME'] != $_SERVER['HTTP_HOST']) { + $defaults['httpHosts'] .= "\n" . $_SERVER['SERVER_NAME']; + } + + if(isset($values['httpHosts']) && is_array($values['httpHosts'])) $values['httpHosts'] = implode("\n", $values['httpHosts']); + + $values = array_merge($defaults, $values); + + $this->h("Default Time Zone"); + echo "

"; + + $this->h("File Permissions"); + $this->p( + "When ProcessWire creates directories or files, it assigns permissions to them. " . + "Enter the most restrictive permissions possible that give ProcessWire (and you) read and write access to the web server (Apache). " . + "The safest setting to use varies from server to server. " . + "If you are not on a dedicated or private server, or are in any kind of shared environment, you may want to contact your web host to advise on what are the best permissions to use in your environment. " . + "Read more about securing file permissions" + ); + + $this->p("Permissions must be 3 digits each. Should you opt to use the defaults provided, you can also adjust these permissions later if desired by editing /site/config.php.", "detail"); + + $this->input('chmodDir', 'Directories', $values['chmodDir']); + $this->input('chmodFile', 'Files', $values['chmodFile'], true); + + if($cgi) { + echo "

We detected that this file (install.php) is writable. That means Apache may be running as your user account. Given that, we populated the permissions above (755 & 644) as possible starting point.

"; + } else { + echo "

WARNING: 777 and 666 permissions mean that directories and files are readable and writable to everyone on the server (and thus not particularly safe). If in any kind of shared hosting environment, please consult your web host for their recommended permission settings for Apache readable/writable directories and files before proceeding. More

"; + } + + $this->h("HTTP Host Names"); + $this->p("What host names will this installation run on now and in the future? Please enter one host per line. You may also choose to leave this blank to auto-detect on each request, but we recommend using this whitelist for the best security in production environments."); + $this->p("This field is recommended but not required. You can set this later by editing the file /site/config.php (setting \$config->httpHosts).", "detail"); + $rows = substr_count($values['httpHosts'], "\n") + 2; + echo "

"; + + $this->btn("Continue", 4); + + $this->p("Note: After you click the button above, be patient … it may take a minute.", "detail"); + } + + /** + * Step 3: Save database configuration, then begin profile import + * + */ + protected function dbSaveConfig() { + + $values = array(); + + // file permissions + $fields = array('chmodDir', 'chmodFile'); + foreach($fields as $field) { + $value = (int) $_POST[$field]; + if(strlen("$value") !== 3) $this->err("Value for '$field' is invalid"); + else $this->$field = "0$value"; + $values[$field] = $value; + } + + $timezone = (int) $_POST['timezone']; + $timezones = $this->timezones(); + if(isset($timezones[$timezone])) { + $value = $timezones[$timezone]; + if(strpos($value, '|')) list($label, $value) = explode('|', $value); + $values['timezone'] = $value; + } else { + $values['timezone'] = 'America/New_York'; + } + + $values['httpHosts'] = array(); + $httpHosts = trim($_POST['httpHosts']); + if(strlen($httpHosts)) { + $httpHosts = str_replace(array("'", '"'), '', $httpHosts); + $httpHosts = explode("\n", $httpHosts); + foreach($httpHosts as $key => $host) { + $host = strtolower(trim(filter_var($host, FILTER_SANITIZE_URL))); + $httpHosts[$key] = $host; + } + $values['httpHosts'] = $httpHosts; + } + + // db configuration + $fields = array('dbUser', 'dbName', 'dbPass', 'dbHost', 'dbPort', 'dbEngine', 'dbCharset'); + foreach($fields as $field) { + $value = get_magic_quotes_gpc() ? stripslashes($_POST[$field]) : $_POST[$field]; + $value = substr($value, 0, 255); + if(strpos($value, "'") !== false) $value = str_replace("'", "\\" . "'", $value); // allow for single quotes (i.e. dbPass) + $values[$field] = trim($value); + } + + $values['dbCharset'] = ($values['dbCharset'] === 'utf8mb4' ? 'utf8mb4' : 'utf8'); + $values['dbEngine'] = ($values['dbEngine'] === 'InnoDB' ? 'InnoDB' : 'MyISAM'); + // if(!ctype_alnum($values['dbCharset'])) $values['dbCharset'] = 'utf8'; + + if(!$values['dbUser'] || !$values['dbName'] || !$values['dbPort']) { + + $this->err("Missing database configuration fields"); + + } else { + + error_reporting(0); + + $dsn = "mysql:dbname=$values[dbName];host=$values[dbHost];port=$values[dbPort]"; + $driver_options = array( + \PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'", + \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION + ); + + try { + $database = new \PDO($dsn, $values['dbUser'], $values['dbPass'], $driver_options); + + } catch(\Exception $e) { + + if($e->getCode() == 1049) { + // If schema does not exist, try to create it + $database = $this->dbCreateDatabase($dsn, $values, $driver_options); + + } else { + $this->err("Database connection information did not work."); + $this->err($e->getMessage()); + } + } + } + + if($this->numErrors || !$database) { + $this->dbConfig($values); + return; + } + + $this->h("Test Database and Save Configuration"); + $this->ok("Database connection successful to " . htmlspecialchars($values['dbName'])); + $options = array( + 'dbCharset' => strtolower($values['dbCharset']), + 'dbEngine' => $values['dbEngine'] + ); + + if($options['dbEngine'] == 'InnoDB') { + $query = $database->query("SELECT VERSION()"); + list($dbVersion) = $query->fetch(\PDO::FETCH_NUM); + if(version_compare($dbVersion, "5.6.4", "<")) { + $options['dbEngine'] = 'MyISAM'; + $values['dbEngine'] = 'MyISAM'; + $this->err("Your MySQL version is $dbVersion and InnoDB requires 5.6.4 or newer. Engine changed to MyISAM."); + } + } + + if($this->dbSaveConfigFile($values)) { + $this->profileImport($database, $options); + } else { + $this->dbConfig($values); + } + } + + /** + * Create database + * + * Note: only handles database names that stick to ascii _a-zA-Z0-9. + * For database names falling outside that set, they should be created + * ahead of time. + * + * Contains contributions from @plauclair PR #950 + * + * @param string $dsn + * @param array $values + * @param array $driver_options + * @return PDO|null + * + */ + protected function dbCreateDatabase($dsn, $values, $driver_options) { + + $dbCharset = preg_replace('/[^a-z0-9]/', '', strtolower(substr($values['dbCharset'], 0, 64))); + $dbName = preg_replace('/[^_a-zA-Z0-9]/', '', substr($values['dbName'], 0, 64)); + $dbNameTest = str_replace('_', '', $dbName); + + if(ctype_alnum($dbNameTest) && $dbName === $values['dbName'] + && ctype_alnum($dbCharset) && $dbCharset === $values['dbCharset']) { + + // valid database name with no changes after sanitization + + try { + $dsn2 = "mysql:host=$values[dbHost];port=$values[dbPort]"; + $database = new \PDO($dsn2, $values['dbUser'], $values['dbPass'], $driver_options); + $database->exec("CREATE SCHEMA IF NOT EXISTS `$dbName` DEFAULT CHARACTER SET `$dbCharset`"); + // reconnect + $database = new \PDO($dsn, $values['dbUser'], $values['dbPass'], $driver_options); + if($database) $this->ok("Created database: $dbName"); + + } catch(\Exception $e) { + $this->err("Failed to create database with name $dbName"); + $this->err($e->getMessage()); + $database = null; + } + + } else { + $database = null; + $this->err("Unable to create database with that name. Please create the database with another tool and try again."); + } + + return $database; + } + + /** + * Save configuration to /site/config.php + * + */ + protected function dbSaveConfigFile(array $values) { + + if(self::TEST_MODE) return true; + + $salt = md5(mt_rand() . microtime(true)); + + $cfg = "\n/**" . + "\n * Installer: Database Configuration" . + "\n * " . + "\n */" . + "\n\$config->dbHost = '$values[dbHost]';" . + "\n\$config->dbName = '$values[dbName]';" . + "\n\$config->dbUser = '$values[dbUser]';" . + "\n\$config->dbPass = '$values[dbPass]';" . + "\n\$config->dbPort = '$values[dbPort]';"; + + if(!empty($values['dbCharset']) && strtolower($values['dbCharset']) != 'utf8') $cfg .= "\n\$config->dbCharset = '$values[dbCharset]';"; + if(!empty($values['dbEngine']) && $values['dbEngine'] == 'InnoDB') $cfg .= "\n\$config->dbEngine = 'InnoDB';"; + + $cfg .= + "\n" . + "\n/**" . + "\n * Installer: User Authentication Salt " . + "\n * " . + "\n * Must be retained if you migrate your site from one server to another" . + "\n * " . + "\n */" . + "\n\$config->userAuthSalt = '$salt'; " . + "\n" . + "\n/**" . + "\n * Installer: File Permission Configuration" . + "\n * " . + "\n */" . + "\n\$config->chmodDir = '0$values[chmodDir]'; // permission for directories created by ProcessWire" . + "\n\$config->chmodFile = '0$values[chmodFile]'; // permission for files created by ProcessWire " . + "\n" . + "\n/**" . + "\n * Installer: Time zone setting" . + "\n * " . + "\n */" . + "\n\$config->timezone = '$values[timezone]';" . + "\n" . + "\n/**" . + "\n * Installer: Unix timestamp of date/time installed" . + "\n * " . + "\n * This is used to detect which when certain behaviors must be backwards compatible." . + "\n * Please leave this value as-is." . + "\n * " . + "\n */" . + "\n\$config->installed = " . time() . ";" . + "\n\n"; + + if(!empty($values['httpHosts'])) { + $cfg .= "" . + "\n/**" . + "\n * Installer: HTTP Hosts Whitelist" . + "\n * " . + "\n */" . + "\n\$config->httpHosts = array("; + foreach($values['httpHosts'] as $host) $cfg .= "'$host', "; + $cfg = rtrim($cfg, ", ") . ");\n\n"; + } + + if(($fp = fopen("./site/config.php", "a")) && fwrite($fp, $cfg)) { + fclose($fp); + $this->ok("Saved configuration to ./site/config.php"); + return true; + } else { + $this->err("Error saving configuration to ./site/config.php. Please make sure it is writable."); + return false; + } + } + + /** + * Step 3b: Import profile + * + */ + protected function profileImport($database, array $options) { + + if(self::TEST_MODE) { + $this->ok("TEST MODE: Skipping profile import"); + $this->adminAccount(); + return; + } + + $profile = "./site/install/"; + if(!is_file("{$profile}install.sql")) die("No installation profile found in {$profile}"); + + // checks to see if the database exists using an arbitrary query (could just as easily be something else) + try { + $query = $database->prepare("SHOW COLUMNS FROM pages"); + $result = $query->execute(); + } catch(\Exception $e) { + $result = false; + } + + if(self::REPLACE_DB || !$result || $query->rowCount() == 0) { + + $this->profileImportSQL($database, "./wire/core/install.sql", $profile . "install.sql", $options); + + if(is_dir($profile . "files")) $this->profileImportFiles($profile); + else $this->mkdir("./site/assets/files/"); + + $this->mkdir("./site/assets/cache/"); + $this->mkdir("./site/assets/logs/"); + $this->mkdir("./site/assets/sessions/"); + + } else { + $this->ok("A profile is already imported, skipping..."); + } + + // copy default site modules /site-default/modules/ to /site/modules/ + $dir = "./site/modules/"; + $defaultDir = "./site-default/modules/"; + if(!is_dir($dir)) $this->mkdir($dir); + if(is_dir($defaultDir)) { + if(is_writable($dir)) { + $result = $this->copyRecursive($defaultDir, $dir, false); + if($result) { + $this->ok("Imported: $defaultDir => $dir"); + + } else { + $this->warn("Error Importing: $defaultDir => $dir"); + } + } else { + $this->warn("$dir is not writable, unable to install default site modules (recommended, but not required)"); + } + } else { + // they are installing site-default already + } + + $this->adminAccount(); + } + + + /** + * Import files to profile + * + */ + protected function profileImportFiles($fromPath) { + + if(self::TEST_MODE) { + $this->ok("TEST MODE: Skipping file import - $fromPath"); + return; + } + + $dir = new \DirectoryIterator($fromPath); + + foreach($dir as $file) { + + if($file->isDot()) continue; + if(!$file->isDir()) continue; + + $dirname = $file->getFilename(); + $pathname = $file->getPathname(); + + if(is_writable($pathname) && self::FORCE_COPY == false) { + // if it's writable, then we know all the files are likely writable too, so we can just rename it + $result = rename($pathname, "./site/assets/$dirname/"); + + } else { + // if it's not writable, then we will make a copy instead, and that copy should be writable by the server + $result = $this->copyRecursive($pathname, "./site/assets/$dirname/"); + } + + if($result) $this->ok("Imported: $pathname => ./site/assets/$dirname/"); + else $this->err("Error Importing: $pathname => ./site/assets/$dirname/"); + + } + } + + /** + * Import profile SQL dump + * + */ + protected function profileImportSQL($database, $file1, $file2, array $options = array()) { + $defaults = array( + 'dbEngine' => 'MyISAM', + 'dbCharset' => 'utf8', + ); + $options = array_merge($defaults, $options); + if(self::TEST_MODE) return; + $restoreOptions = array(); + $replace = array(); + if($options['dbEngine'] != 'MyISAM') { + $replace['ENGINE=MyISAM'] = "ENGINE=$options[dbEngine]"; + $this->warn("Engine changed to '$options[dbEngine]', please keep an eye out for issues."); + } + if($options['dbCharset'] != 'utf8') { + $replace['CHARSET=utf8'] = "CHARSET=$options[dbCharset]"; + if(strtolower($options['dbCharset']) === 'utf8mb4') { + $replace['(255)'] = '(250)'; // max ley length in utf8mb4 is 1000 (250 * 4) + } + $this->warn("Character set has been changed to '$options[dbCharset]', please keep an eye out for issues."); + } + if(count($replace)) $restoreOptions['findReplaceCreateTable'] = $replace; + require("./wire/core/WireDatabaseBackup.php"); + $backup = new WireDatabaseBackup(); + $backup->setDatabase($database); + if($backup->restoreMerge($file1, $file2, $restoreOptions)) { + $this->ok("Imported database file: $file1"); + $this->ok("Imported database file: $file2"); + } else { + foreach($backup->errors() as $error) $this->err($error); + } + } + + /** + * Present form to create admin account + * + */ + protected function adminAccount($wire = null) { + + $values = array( + 'admin_name' => 'processwire', + 'username' => 'admin', + 'userpass' => '', + 'userpass_confirm' => '', + 'useremail' => '', + ); + + $clean = array(); + + foreach($values as $key => $value) { + if($wire && $wire->input->post->$key) $value = $wire->input->post->$key; + $value = htmlentities($value, ENT_QUOTES, "UTF-8"); + $clean[$key] = $value; + } + + $this->h("Admin Panel Information"); + $this->input("admin_name", "Admin Login URL", $clean['admin_name'], false, "name"); + $js = "$('link#colors').attr('href', $('link#colors').attr('href').replace(/main-.*$/, 'main-' + $(this).val() + '.css'))"; + echo "

Change for a live preview

"; + + $this->p(" You can change the admin URL later by editing the admin page and changing the name on the settings tab.
You can change the colors later by going to Admin Modules Core Admin Theme Settings.", "detail"); + $this->h("Admin Account Information"); + $this->p("You will use this account to login to your ProcessWire admin. It will have superuser access, so please make sure to create a strong password."); + $this->input("username", "User", $clean['username'], false, "name"); + $this->input("userpass", "Password", $clean['userpass'], false, "password"); + $this->input("userpass_confirm", "Password (again)", $clean['userpass_confirm'], true, "password"); + $this->input("useremail", "Email Address", $clean['useremail'], true, "email"); + $this->p(" Please remember the password you enter above as you will not be able to retrieve it again.", "detail"); + + $this->h("Cleanup"); + $this->p("Directories and files listed below are no longer needed and should be removed. If you choose to leave any of them in place, you should delete them before migrating to a production environment.", "detail"); + $this->p($this->getRemoveableItems($wire, true)); + + $this->btn("Continue", 5); + } + + protected function getRemoveableItems($wire, $getMarkup = false, $removeNow = false) { + + $root = dirname(__FILE__) . '/'; + $isPost = $wire->input->post->remove_items !== null; + $postItems = $isPost ? $wire->input->post->remove_items : array(); + if(!is_array($postItems)) $postItems = array(); + $out = ''; + + $items = array( + 'install-php' => array( + 'label' => 'Remove installer (install.php) when finished', + 'file' => "/install.php", + 'path' => $root . "install.php", + ), + 'install-dir' => array( + 'label' => 'Remove installer site profile assets (/site/install/)', + 'path' => $root . "site/install/", + 'file' => '/site/install/', + ), + 'gitignore' => array( + 'label' => 'Remove .gitignore file', + 'path' => $root . ".gitignore", + 'file' => '/.gitignore', + ) + ); + + foreach($this->findProfiles() as $name => $profile) { + $title = empty($profile['title']) ? $name : $profile['title']; + $items[$name] = array( + 'label' => "Remove unused $title site profile (/$name/)", + 'path' => $root . "$name/", + 'file' => "/$name/", + ); + } + + foreach($items as $name => $item) { + if(!file_exists($item['path'])) continue; + $disabled = is_writable($item['path']) ? "" : "disabled"; + $checked = !$isPost || in_array($name, $postItems) ? "checked" : ""; + $note = $disabled ? "(not writable/deletable by this installer)" : ""; + $markup = + ""; + $items[$name]['markup'] = $markup; + $out .= $out ? "
$markup" : $markup; + + if($removeNow && $isPost) { + if($checked && !$disabled) { + if(is_dir($item['path'])) { + $success = wireRmdir($item['path'], true); + } else if(is_file($item['path'])) { + $success = @unlink($item['path']); + } else { + $success = true; + } + if($success) { + $this->ok("Completed: " . $item['label']); + } else { + $this->err("Unable to remove $item[file] - please remove manually, as it is no longer needed"); + } + } else if($disabled) { + $this->warn("Please remove $item[file] from the file system as it is no longer needed"); + } else if(!$checked) { + $this->warn("Remember to remove $item[file] from the file system before migrating to production use"); + } + } + } + + if($getMarkup) return $out; + return $items; + } + + /** + * Save submitted admin account form + * + */ + protected function adminAccountSave($wire) { + + $input = $wire->input; + $sanitizer = $wire->sanitizer; + + if(!$input->post->username || !$input->post->userpass) $this->err("Missing account information"); + if($input->post->userpass !== $input->post->userpass_confirm) $this->err("Passwords do not match"); + if(strlen($input->post->userpass) < 6) $this->err("Password must be at least 6 characters long"); + + $username = $sanitizer->pageName($input->post->username); + if($username != $input->post->username) $this->err("Username must be only a-z 0-9"); + if(strlen($username) < 2) $this->err("Username must be at least 2 characters long"); + + $adminName = $sanitizer->pageName($input->post->admin_name); + if($adminName != $input->post->admin_name) $this->err("Admin login URL must be only a-z 0-9"); + if($adminName == 'wire' || $adminName == 'site') $this->err("Admin name may not be 'wire' or 'site'"); + if(strlen($adminName) < 2) $this->err("Admin login URL must be at least 2 characters long"); + + $email = strtolower($sanitizer->email($input->post->useremail)); + if($email != strtolower($input->post->useremail)) $this->err("Email address did not validate"); + + if($this->numErrors) return $this->adminAccount($wire); + + $superuserRole = $wire->roles->get("name=superuser"); + $user = $wire->users->get($wire->config->superUserPageID); + + if(!$user->id) { + $user = new User(); + $user->id = $wire->config->superUserPageID; + } + + $user->name = $username; + $user->pass = $input->post->userpass; + $user->email = $email; + + if(!$user->roles->has("superuser")) $user->roles->add($superuserRole); + + $admin = $wire->pages->get($wire->config->adminRootPageID); + $admin->of(false); + $admin->name = $adminName; + + try { + if(self::TEST_MODE) { + $this->ok("TEST MODE: skipped user creation"); + } else { + $wire->users->save($user); + $wire->pages->save($admin); + } + + } catch(\Exception $e) { + $this->err($e->getMessage()); + return $this->adminAccount($wire); + } + + $adminName = htmlentities($adminName, ENT_QUOTES, "UTF-8"); + + $this->h("Admin Account Saved"); + $this->ok("User account saved: {$user->name}"); + + $colors = $wire->sanitizer->pageName($input->post->colors); + if(!in_array($colors, $this->colors)) $colors = reset($this->colors); + $theme = $wire->modules->getInstall('AdminThemeDefault'); + $configData = $wire->modules->getModuleConfigData('AdminThemeDefault'); + $configData['colors'] = $colors; + $wire->modules->saveModuleConfigData('AdminThemeDefault', $configData); + $this->ok("Saved admin color set $colors - you will see this when you login."); + + $this->h("Complete & Secure Your Installation"); + $this->getRemoveableItems($wire, false, true); + + $this->ok("Note that future runtime errors are logged to /site/assets/logs/errors.txt (not web accessible)."); + $this->ok("For more configuration options see /wire/config.php."); + $this->warn("Please make your /site/config.php file non-writable, and readable only to you and Apache."); + $this->p("How to secure your /site/config.php file "); + + if(is_writable("./site/modules/")) wireChmod("./site/modules/", true); + + $this->h("Use The Site!"); + $this->ok("Your admin URL is /$adminName/"); + $this->p("If you'd like, you may change this later by editing the admin page and changing the name.", "detail"); + $this->btn("Login to Admin", 1, 'sign-in', false, true, "./$adminName/"); + $this->btn("View Site ", 1, 'angle-right', true, false, "./"); + + // set a define that indicates installation is completed so that this script no longer runs + if(!self::TEST_MODE) { + file_put_contents("./site/assets/installed.php", "numErrors++; + echo "\n
  • $str
  • "; + return false; + } + + /** + * Action/warning + * + */ + protected function warn($str) { + $this->numErrors++; + echo "\n
  • $str
  • "; + return false; + } + /** + * Report success + * + */ + protected function ok($str) { + echo "\n
  • $str
  • "; + return true; + } + + /** + * Output a button + * + */ + protected function btn($label, $value, $icon = 'angle-right', $secondary = false, $float = false, $href ='') { + $class = $secondary ? 'ui-priority-secondary' : ''; + if($float) $class .= " floated"; + $type = 'submit'; + if($href) $type = 'button'; + if($href) echo ""; + echo "\n

    "; + if($href) echo "
    "; + } + + /** + * Output a headline + * + */ + protected function h($label) { + echo "\n

    $label

    "; + } + + /** + * Output a paragraph + * + */ + protected function p($text, $class = '') { + if($class) echo "\n

    $text

    "; + else echo "\n

    $text

    "; + } + + /** + * Output an + * + */ + protected function input($name, $label, $value, $clear = false, $type = "text", $required = true) { + $width = 135; + $required = $required ? "required='required'" : ""; + $pattern = ''; + $note = ''; + if($type == 'email') { + $width = ($width*2); + $required = ''; + } else if($type == 'name') { + $type = 'text'; + $pattern = "pattern='[-_a-z0-9]{2,50}' "; + if($name == 'admin_name') $width = ($width*2); + $note = "(a-z 0-9)"; + } + $inputWidth = $width - 15; + $value = htmlentities($value, ENT_QUOTES, "UTF-8"); + echo "\n

    "; + if($clear) echo "\n
    "; + } + + + /****************************************************************************************************************** + * FILE FUNCTIONS + * + */ + + /** + * Create a directory and assign permission + * + */ + protected function mkdir($path, $showNote = true) { + if(self::TEST_MODE) return; + if(is_dir($path) || mkdir($path)) { + chmod($path, octdec($this->chmodDir)); + if($showNote) $this->ok("Created directory: $path"); + return true; + } else { + if($showNote) $this->err("Error creating directory: $path"); + return false; + } + } + + /** + * Copy directories recursively + * + */ + protected function copyRecursive($src, $dst, $overwrite = true) { + + if(self::TEST_MODE) return; + + if(substr($src, -1) != '/') $src .= '/'; + if(substr($dst, -1) != '/') $dst .= '/'; + + $dir = opendir($src); + $this->mkdir($dst, false); + + while(false !== ($file = readdir($dir))) { + if($file == '.' || $file == '..') continue; + if(is_dir($src . $file)) { + $this->copyRecursive($src . $file, $dst . $file); + } else { + if(!$overwrite && file_exists($dst . $file)) { + // don't replace existing files when $overwrite == false; + } else { + copy($src . $file, $dst . $file); + chmod($dst . $file, octdec($this->chmodFile)); + } + } + } + + closedir($dir); + return true; + } + + protected function timezones() { + $timezones = timezone_identifiers_list(); + $extras = array( + 'US Eastern|America/New_York', + 'US Central|America/Chicago', + 'US Mountain|America/Denver', + 'US Mountain (no DST)|America/Phoenix', + 'US Pacific|America/Los_Angeles', + 'US Alaska|America/Anchorage', + 'US Hawaii|America/Adak', + 'US Hawaii (no DST)|Pacific/Honolulu', + ); + foreach($extras as $t) $timezones[] = $t; + return $timezones; + } + + +} + +/****************************************************************************************************/ + +if(!Installer::TEST_MODE && is_file("./site/assets/installed.php")) die("This installer has already run. Please delete it."); +error_reporting(E_ALL | E_STRICT); +$installer = new Installer(); +$installer->execute(); + diff --git a/site-beginner/assets/index.php b/site-beginner/assets/index.php new file mode 100644 index 00000000..c93fc071 --- /dev/null +++ b/site-beginner/assets/index.php @@ -0,0 +1,4 @@ +debug = false; + +/** + * Prepend template file + * + * PHP file in /site/templates/ that will be loaded before each page's template file. + * Example: _init.php + * + * @var string + * + */ +$config->prependTemplateFile = '_init.php'; + + +/*** INSTALLER CONFIG ********************************************************************/ diff --git a/site-beginner/install/files/1/airport_cartoon_3.0x100.jpg b/site-beginner/install/files/1/airport_cartoon_3.0x100.jpg new file mode 100644 index 00000000..a4246c66 Binary files /dev/null and b/site-beginner/install/files/1/airport_cartoon_3.0x100.jpg differ diff --git a/site-beginner/install/files/1/airport_cartoon_3.400x0.jpg b/site-beginner/install/files/1/airport_cartoon_3.400x0.jpg new file mode 100644 index 00000000..206d0461 Binary files /dev/null and b/site-beginner/install/files/1/airport_cartoon_3.400x0.jpg differ diff --git a/site-beginner/install/files/1/airport_cartoon_3.jpg b/site-beginner/install/files/1/airport_cartoon_3.jpg new file mode 100644 index 00000000..c4c89a01 Binary files /dev/null and b/site-beginner/install/files/1/airport_cartoon_3.jpg differ diff --git a/site-beginner/install/files/1/rough_cartoon_puppet.0x100.jpg b/site-beginner/install/files/1/rough_cartoon_puppet.0x100.jpg new file mode 100644 index 00000000..265d0042 Binary files /dev/null and b/site-beginner/install/files/1/rough_cartoon_puppet.0x100.jpg differ diff --git a/site-beginner/install/files/1/rough_cartoon_puppet.400x0.jpg b/site-beginner/install/files/1/rough_cartoon_puppet.400x0.jpg new file mode 100644 index 00000000..71461c5c Binary files /dev/null and b/site-beginner/install/files/1/rough_cartoon_puppet.400x0.jpg differ diff --git a/site-beginner/install/files/1/rough_cartoon_puppet.jpg b/site-beginner/install/files/1/rough_cartoon_puppet.jpg new file mode 100644 index 00000000..05c34b09 Binary files /dev/null and b/site-beginner/install/files/1/rough_cartoon_puppet.jpg differ diff --git a/site-beginner/install/files/1002/psych_cartoon_4-20.0x100.jpg b/site-beginner/install/files/1002/psych_cartoon_4-20.0x100.jpg new file mode 100644 index 00000000..5fb20491 Binary files /dev/null and b/site-beginner/install/files/1002/psych_cartoon_4-20.0x100.jpg differ diff --git a/site-beginner/install/files/1002/psych_cartoon_4-20.400x0.jpg b/site-beginner/install/files/1002/psych_cartoon_4-20.400x0.jpg new file mode 100644 index 00000000..436896c1 Binary files /dev/null and b/site-beginner/install/files/1002/psych_cartoon_4-20.400x0.jpg differ diff --git a/site-beginner/install/files/1002/psych_cartoon_4-20.jpg b/site-beginner/install/files/1002/psych_cartoon_4-20.jpg new file mode 100644 index 00000000..ffa7edff Binary files /dev/null and b/site-beginner/install/files/1002/psych_cartoon_4-20.jpg differ diff --git a/site-beginner/install/files/README.txt b/site-beginner/install/files/README.txt new file mode 100644 index 00000000..c3f275a3 --- /dev/null +++ b/site-beginner/install/files/README.txt @@ -0,0 +1 @@ +This file is here to ensure Git adds the dir to the repo. You may delete this file. diff --git a/site-beginner/install/info.php b/site-beginner/install/info.php new file mode 100644 index 00000000..233245c8 --- /dev/null +++ b/site-beginner/install/info.php @@ -0,0 +1,6 @@ + "Default (Beginner Edition)", + 'summary' => "A minimal responsive site profile that serves as a good starting point for new sites or for learning about ProcessWire. Focuses on using the easiest to understand template concepts for new users.", + 'screenshot' => "screenshot.png" + ); diff --git a/site-beginner/install/install.sql b/site-beginner/install/install.sql new file mode 100644 index 00000000..45dc8c1d --- /dev/null +++ b/site-beginner/install/install.sql @@ -0,0 +1,538 @@ +--- WireDatabaseBackup {"time":"2014-08-27 12:18:44","user":"","dbName":"pw2_blank","description":"","tables":[],"excludeTables":["pages_drafts","pages_roles","permissions","roles","roles_permissions","users","users_roles","user","role","permission"],"excludeCreateTables":[],"excludeExportTables":["field_roles","field_permissions","field_email","field_pass","caches","session_login_throttle","page_path_history"]} + +DROP TABLE IF EXISTS `caches`; +CREATE TABLE `caches` ( + `name` varchar(255) NOT NULL, + `data` mediumtext NOT NULL, + `expires` datetime NOT NULL, + PRIMARY KEY (`name`), + KEY `expires` (`expires`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `field_body`; +CREATE TABLE `field_body` ( + `pages_id` int(10) unsigned NOT NULL, + `data` mediumtext NOT NULL, + PRIMARY KEY (`pages_id`), + FULLTEXT KEY `data` (`data`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `field_body` (`pages_id`, `data`) VALUES('27', '

    The page you were looking for is not found.

    Please use our search engine or navigation above to find the page.

    '); +INSERT INTO `field_body` (`pages_id`, `data`) VALUES('1', '

    What is ProcessWire?

    \r\n\r\n

    ProcessWire gives you full control over your fields, templates and markup. It provides a powerful template system that works the way you do. Not to mention, ProcessWire\'s API makes working with your content easy and enjoyable. Learn more

    \r\n\r\n

    About this site profile

    \r\n\r\n

    This is a basic minimal site for you to use in developing your own site or to learn from. There are a few pages here to serve as examples, but this site profile does not make any attempt to demonstrate all that ProcessWire can do. To learn more or ask questions, visit the ProcessWire forums or browse more site profiles. If you are building a new site, this minimal profile is a good place to start. You may use these existing templates and design as they are, or you may replace them entirely.

    \r\n\r\n

    Browse the site

    '); +INSERT INTO `field_body` (`pages_id`, `data`) VALUES('1002', '

    Ut capio feugiat saepius torqueo olim

    \r\n\r\n

    In utinam facilisi eum vicis feugait nimis

    \r\n\r\n

    Iusto incassum appellatio cui macto genitus vel. Lobortis aliquam luctus, roto enim, imputo wisi tamen. Ratis odio, genitus acsi, neo illum consequat consectetuer ut.

    \r\n\r\n
    \r\n

    Wisi fere virtus cogo, ex ut vel nullus similis vel iusto. Tation incassum adsum in, quibus capto premo diam suscipere facilisi. Uxor laoreet mos capio premo feugait ille et. Pecus abigo immitto epulae duis vel. Neque causa, indoles verto, decet ingenium dignissim.

    \r\n
    \r\n\r\n

    Patria iriure vel vel autem proprius indoles ille sit. Tation blandit refoveo, accumsan ut ulciscor lucidus inhibeo capto aptent opes, foras.

    \r\n\r\n

    Dolore ea valde refero feugait utinam luctus

    \r\n\r\n

    \"CopyrightUsitas, nostrud transverbero, in, amet, nostrud ad. Ex feugiat opto diam os aliquam regula lobortis dolore ut ut quadrum. Esse eu quis nunc jugis iriure volutpat wisi, fere blandit inhibeo melior, hendrerit, saluto velit. Eu bene ideo dignissim delenit accumsan nunc. Usitas ille autem camur consequat typicus feugait elit ex accumsan nutus accumsan nimis pagus, occuro. Immitto populus, qui feugiat opto pneum letalis paratus. Mara conventio torqueo nibh caecus abigo sit eum brevitas. Populus, duis ex quae exerci hendrerit, si antehabeo nobis, consequat ea praemitto zelus.

    \r\n\r\n

    Immitto os ratis euismod conventio erat jus caecus sudo. code test Appellatio consequat, et ibidem ludus nulla dolor augue abdo tego euismod plaga lenis. Sit at nimis venio venio tego os et pecus enim pneum magna nobis ad pneum. Saepius turpis probo refero molior nonummy aliquam neque appellatio jus luctus acsi. Ulciscor refero pagus imputo eu refoveo valetudo duis dolore usitas. Consequat suscipere quod torqueo ratis ullamcorper, dolore lenis, letalis quia quadrum plaga minim.

    '); +INSERT INTO `field_body` (`pages_id`, `data`) VALUES('1001', '

    Si lobortis singularis genitus ibidem saluto.

    Dolore ad nunc, mos accumsan paratus duis suscipit luptatum facilisis macto uxor iaceo quadrum. Demoveo, appellatio elit neque ad commodo ea. Wisi, iaceo, tincidunt at commoveo rusticus et, ludus. Feugait at blandit bene blandit suscipere abdo duis ideo bis commoveo pagus ex, velit. Consequat commodo roto accumsan, duis transverbero.

    '); +INSERT INTO `field_body` (`pages_id`, `data`) VALUES('1004', '

    Pertineo vel dignissim, natu letalis fere odio

    Magna in gemino, gilvus iusto capto jugis abdo mos aptent acsi qui. Utrum inhibeo humo humo duis quae. Lucidus paulatim facilisi scisco quibus hendrerit conventio adsum.

    Si lobortis singularis genitus ibidem saluto

    Iriure, ex velit, praesent vulpes delenit capio vero gilvus inhibeo letatio aliquip metuo qui eros. Transverbero demoveo euismod letatio torqueo melior. Ut odio in suscipit paulatim amet huic letalis suscipere eros causa, letalis magna.

    1. Feugiat eligo foras ex elit sed indoles hos elit ex antehabeo defui et nostrud.
    2. Letatio valetudo multo consequat inhibeo ille dignissim pagus et in quadrum eum eu.
    3. Aliquam si consequat, ut nulla amet et turpis exerci, adsum luctus ne decet, delenit.
    4. Commoveo nunc diam valetudo cui, aptent commoveo at obruo uxor nulla aliquip augue.
    '); + +DROP TABLE IF EXISTS `field_email`; +CREATE TABLE `field_email` ( + `pages_id` int(10) unsigned NOT NULL, + `data` varchar(255) NOT NULL DEFAULT '', + PRIMARY KEY (`pages_id`), + KEY `data_exact` (`data`), + FULLTEXT KEY `data` (`data`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `field_headline`; +CREATE TABLE `field_headline` ( + `pages_id` int(10) unsigned NOT NULL, + `data` text NOT NULL, + PRIMARY KEY (`pages_id`), + FULLTEXT KEY `data` (`data`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `field_headline` (`pages_id`, `data`) VALUES('1', 'Minimal Site Profile'); +INSERT INTO `field_headline` (`pages_id`, `data`) VALUES('1001', 'About Us'); +INSERT INTO `field_headline` (`pages_id`, `data`) VALUES('27', '404 Page Not Found'); + +DROP TABLE IF EXISTS `field_images`; +CREATE TABLE `field_images` ( + `pages_id` int(10) unsigned NOT NULL, + `data` varchar(255) NOT NULL, + `sort` int(10) unsigned NOT NULL, + `description` text NOT NULL, + `modified` datetime DEFAULT NULL, + `created` datetime DEFAULT NULL, + PRIMARY KEY (`pages_id`,`sort`), + KEY `data` (`data`), + KEY `modified` (`modified`), + KEY `created` (`created`), + FULLTEXT KEY `description` (`description`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `field_images` (`pages_id`, `data`, `sort`, `description`, `modified`, `created`) VALUES('1002', 'psych_cartoon_4-20.jpg', '0', 'Copyright by Austin Cramer for DesignIntelligence. This is a placeholder while he makes new ones for us.', NOW(), NOW()); +INSERT INTO `field_images` (`pages_id`, `data`, `sort`, `description`, `modified`, `created`) VALUES('1', 'rough_cartoon_puppet.jpg', '1', 'Copyright by Austin Cramer for DesignIntelligence. This is a placeholder while he makes new ones for us.', NOW(), NOW()); +INSERT INTO `field_images` (`pages_id`, `data`, `sort`, `description`, `modified`, `created`) VALUES('1', 'airport_cartoon_3.jpg', '0', 'Copyright by Austin Cramer for DesignIntelligence. This is a placeholder while he makes new ones for us.', NOW(), NOW()); + +DROP TABLE IF EXISTS `field_pass`; +CREATE TABLE `field_pass` ( + `pages_id` int(10) unsigned NOT NULL, + `data` char(40) NOT NULL, + `salt` char(32) NOT NULL, + PRIMARY KEY (`pages_id`), + KEY `data` (`data`) +) ENGINE=MyISAM DEFAULT CHARSET=ascii; + +DROP TABLE IF EXISTS `field_permissions`; +CREATE TABLE `field_permissions` ( + `pages_id` int(10) unsigned NOT NULL, + `data` int(11) NOT NULL, + `sort` int(10) unsigned NOT NULL, + PRIMARY KEY (`pages_id`,`sort`), + KEY `data` (`data`,`pages_id`,`sort`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `field_process`; +CREATE TABLE `field_process` ( + `pages_id` int(11) NOT NULL DEFAULT '0', + `data` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`pages_id`), + KEY `data` (`data`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('6', '17'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('3', '12'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('8', '12'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('9', '14'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('10', '7'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('11', '47'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('16', '48'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('300', '104'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('21', '50'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('29', '66'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('23', '10'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('304', '138'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('31', '136'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('22', '76'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('30', '68'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('303', '129'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('2', '87'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('302', '121'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('301', '109'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('28', '76'); +INSERT INTO `field_process` (`pages_id`, `data`) VALUES('1007', '150'); + +DROP TABLE IF EXISTS `field_roles`; +CREATE TABLE `field_roles` ( + `pages_id` int(10) unsigned NOT NULL, + `data` int(11) NOT NULL, + `sort` int(10) unsigned NOT NULL, + PRIMARY KEY (`pages_id`,`sort`), + KEY `data` (`data`,`pages_id`,`sort`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `field_sidebar`; +CREATE TABLE `field_sidebar` ( + `pages_id` int(10) unsigned NOT NULL, + `data` mediumtext NOT NULL, + PRIMARY KEY (`pages_id`), + FULLTEXT KEY `data` (`data`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `field_sidebar` (`pages_id`, `data`) VALUES('1', '

    About ProcessWire

    \r\n\r\n

    ProcessWire is an open source CMS and web application framework aimed at the needs of designers, developers and their clients.

    \r\n\r\n'); +INSERT INTO `field_sidebar` (`pages_id`, `data`) VALUES('1002', '

    Sudo nullus

    \r\n\r\n

    Et torqueo vulpes vereor luctus augue quod consectetuer antehabeo causa patria tation ex plaga ut. Abluo delenit wisi iriure eros feugiat probo nisl aliquip nisl, patria. Antehabeo esse camur nisl modo utinam. Sudo nullus ventosus ibidem facilisis saepius eum sino pneum, vicis odio voco opto.

    '); + +DROP TABLE IF EXISTS `field_summary`; +CREATE TABLE `field_summary` ( + `pages_id` int(10) unsigned NOT NULL, + `data` mediumtext NOT NULL, + PRIMARY KEY (`pages_id`), + FULLTEXT KEY `data` (`data`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `field_summary` (`pages_id`, `data`) VALUES('1002', 'Dolore ea valde refero feugait utinam luctus. Probo velit commoveo et, delenit praesent, suscipit zelus, hendrerit zelus illum facilisi, regula. '); +INSERT INTO `field_summary` (`pages_id`, `data`) VALUES('1001', 'This is a placeholder page with two child pages to serve as an example. '); +INSERT INTO `field_summary` (`pages_id`, `data`) VALUES('1005', 'View this template\'s source for a demonstration of how to create a basic site map. '); +INSERT INTO `field_summary` (`pages_id`, `data`) VALUES('1004', 'Mos erat reprobo in praesent, mara premo, obruo iustum pecus velit lobortis te sagaciter populus.'); +INSERT INTO `field_summary` (`pages_id`, `data`) VALUES('1', 'ProcessWire is an open source CMS and web application framework aimed at the needs of designers, developers and their clients. '); + +DROP TABLE IF EXISTS `field_title`; +CREATE TABLE `field_title` ( + `pages_id` int(10) unsigned NOT NULL, + `data` text NOT NULL, + PRIMARY KEY (`pages_id`), + KEY `data_exact` (`data`(255)), + FULLTEXT KEY `data` (`data`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('11', 'Templates'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('16', 'Fields'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('22', 'Setup'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('3', 'Pages'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('6', 'Add Page'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('8', 'Tree'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('9', 'Save Sort'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('10', 'Edit Page'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('21', 'Modules'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('29', 'Users'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('30', 'Roles'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('2', 'Admin'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('7', 'Trash'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('27', '404 Page'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('302', 'Insert Link'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('23', 'Login'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('304', 'Profile'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('301', 'Empty Trash'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('300', 'Search'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('303', 'Insert Image'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('28', 'Access'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('31', 'Permissions'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('32', 'Edit pages'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('34', 'Delete pages'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('35', 'Move pages (change parent)'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('36', 'View pages'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('50', 'Sort child pages'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('51', 'Change templates on pages'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('52', 'Administer users'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('53', 'User can update profile/password'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('54', 'Lock or unlock a page'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('1', 'Home'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('1001', 'About'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('1002', 'Child page example 1'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('1000', 'Search'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('1004', 'Child page example 2'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('1005', 'Site Map'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('1006', 'Use Page Lister'); +INSERT INTO `field_title` (`pages_id`, `data`) VALUES('1007', 'Find'); + +DROP TABLE IF EXISTS `fieldgroups`; +CREATE TABLE `fieldgroups` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) CHARACTER SET ascii NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM AUTO_INCREMENT=97 DEFAULT CHARSET=utf8; + +INSERT INTO `fieldgroups` (`id`, `name`) VALUES('2', 'admin'); +INSERT INTO `fieldgroups` (`id`, `name`) VALUES('3', 'user'); +INSERT INTO `fieldgroups` (`id`, `name`) VALUES('4', 'role'); +INSERT INTO `fieldgroups` (`id`, `name`) VALUES('5', 'permission'); +INSERT INTO `fieldgroups` (`id`, `name`) VALUES('1', 'home'); +INSERT INTO `fieldgroups` (`id`, `name`) VALUES('88', 'sitemap'); +INSERT INTO `fieldgroups` (`id`, `name`) VALUES('83', 'basic-page'); +INSERT INTO `fieldgroups` (`id`, `name`) VALUES('80', 'search'); + +DROP TABLE IF EXISTS `fieldgroups_fields`; +CREATE TABLE `fieldgroups_fields` ( + `fieldgroups_id` int(10) unsigned NOT NULL DEFAULT '0', + `fields_id` int(10) unsigned NOT NULL DEFAULT '0', + `sort` int(11) unsigned NOT NULL DEFAULT '0', + `data` text, + PRIMARY KEY (`fieldgroups_id`,`fields_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('2', '2', '1', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('2', '1', '0', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('3', '3', '0', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('3', '4', '2', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('4', '5', '0', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('5', '1', '0', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('3', '92', '1', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('1', '1', '0', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('1', '44', '5', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('1', '76', '3', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('80', '1', '0', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('83', '44', '5', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('83', '76', '3', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('1', '78', '1', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('83', '1', '0', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('88', '79', '1', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('1', '79', '2', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('1', '82', '4', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('88', '1', '0', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('83', '82', '4', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('83', '78', '1', NULL); +INSERT INTO `fieldgroups_fields` (`fieldgroups_id`, `fields_id`, `sort`, `data`) VALUES('83', '79', '2', NULL); + +DROP TABLE IF EXISTS `fields`; +CREATE TABLE `fields` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `type` varchar(128) CHARACTER SET ascii NOT NULL, + `name` varchar(255) CHARACTER SET ascii NOT NULL, + `flags` int(11) NOT NULL DEFAULT '0', + `label` varchar(255) NOT NULL DEFAULT '', + `data` text NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`), + KEY `type` (`type`) +) ENGINE=MyISAM AUTO_INCREMENT=97 DEFAULT CHARSET=utf8; + +INSERT INTO `fields` (`id`, `type`, `name`, `flags`, `label`, `data`) VALUES('1', 'FieldtypePageTitle', 'title', '13', 'Title', '{\"required\":1,\"textformatters\":[\"TextformatterEntities\"],\"size\":0,\"maxlength\":255}'); +INSERT INTO `fields` (`id`, `type`, `name`, `flags`, `label`, `data`) VALUES('2', 'FieldtypeModule', 'process', '25', 'Process', '{\"description\":\"The process that is executed on this page. Since this is mostly used by ProcessWire internally, it is recommended that you don\'t change the value of this unless adding your own pages in the admin.\",\"collapsed\":1,\"required\":1,\"moduleTypes\":[\"Process\"],\"permanent\":1}'); +INSERT INTO `fields` (`id`, `type`, `name`, `flags`, `label`, `data`) VALUES('3', 'FieldtypePassword', 'pass', '24', 'Set Password', '{\"collapsed\":1,\"size\":50,\"maxlength\":128}'); +INSERT INTO `fields` (`id`, `type`, `name`, `flags`, `label`, `data`) VALUES('5', 'FieldtypePage', 'permissions', '24', 'Permissions', '{\"derefAsPage\":0,\"parent_id\":31,\"labelFieldName\":\"title\",\"inputfield\":\"InputfieldCheckboxes\"}'); +INSERT INTO `fields` (`id`, `type`, `name`, `flags`, `label`, `data`) VALUES('4', 'FieldtypePage', 'roles', '24', 'Roles', '{\"derefAsPage\":0,\"parent_id\":30,\"labelFieldName\":\"name\",\"inputfield\":\"InputfieldCheckboxes\",\"description\":\"User will inherit the permissions assigned to each role. You may assign multiple roles to a user. When accessing a page, the user will only inherit permissions from the roles that are also assigned to the page\'s template.\"}'); +INSERT INTO `fields` (`id`, `type`, `name`, `flags`, `label`, `data`) VALUES('92', 'FieldtypeEmail', 'email', '9', 'E-Mail Address', '{\"size\":70,\"maxlength\":255}'); +INSERT INTO `fields` (`id`, `type`, `name`, `flags`, `label`, `data`) VALUES('82', 'FieldtypeTextarea', 'sidebar', '0', 'Sidebar', '{\"inputfieldClass\":\"InputfieldCKEditor\",\"rows\":5,\"contentType\":1,\"toolbar\":\"Format, Bold, Italic, -, RemoveFormat\\r\\nNumberedList, BulletedList, -, Blockquote\\r\\nPWLink, Unlink, Anchor\\r\\nPWImage, Table, HorizontalRule, SpecialChar\\r\\nPasteText, PasteFromWord\\r\\nScayt, -, Sourcedialog\",\"inlineMode\":0,\"useACF\":1,\"usePurifier\":1,\"formatTags\":\"p;h2;h3;h4;h5;h6;pre;address\",\"extraPlugins\":[\"pwimage\",\"pwlink\",\"sourcedialog\"],\"removePlugins\":\"image,magicline\",\"toggles\":[2,4,8],\"collapsed\":2}'); +INSERT INTO `fields` (`id`, `type`, `name`, `flags`, `label`, `data`) VALUES('44', 'FieldtypeImage', 'images', '0', 'Images', '{\"extensions\":\"gif jpg jpeg png\",\"adminThumbs\":1,\"inputfieldClass\":\"InputfieldImage\",\"maxFiles\":0,\"descriptionRows\":1,\"fileSchema\":2,\"textformatters\":[\"TextformatterEntities\"],\"outputFormat\":1,\"defaultValuePage\":0,\"defaultGrid\":0,\"icon\":\"camera\"}'); +INSERT INTO `fields` (`id`, `type`, `name`, `flags`, `label`, `data`) VALUES('79', 'FieldtypeTextarea', 'summary', '1', 'Summary', '{\"textformatters\":[\"TextformatterEntities\"],\"inputfieldClass\":\"InputfieldTextarea\",\"collapsed\":2,\"rows\":3,\"contentType\":0}'); +INSERT INTO `fields` (`id`, `type`, `name`, `flags`, `label`, `data`) VALUES('76', 'FieldtypeTextarea', 'body', '0', 'Body', '{\"inputfieldClass\":\"InputfieldCKEditor\",\"rows\":10,\"contentType\":1,\"toolbar\":\"Format, Bold, Italic, -, RemoveFormat\\r\\nNumberedList, BulletedList, -, Blockquote\\r\\nPWLink, Unlink, Anchor\\r\\nPWImage, Table, HorizontalRule, SpecialChar\\r\\nPasteText, PasteFromWord\\r\\nScayt, -, Sourcedialog\",\"inlineMode\":0,\"useACF\":1,\"usePurifier\":1,\"formatTags\":\"p;h2;h3;h4;h5;h6;pre;address\",\"extraPlugins\":[\"pwimage\",\"pwlink\",\"sourcedialog\"],\"removePlugins\":\"image,magicline\",\"toggles\":[2,4,8]}'); +INSERT INTO `fields` (`id`, `type`, `name`, `flags`, `label`, `data`) VALUES('78', 'FieldtypeText', 'headline', '0', 'Headline', '{\"description\":\"Use this instead of the Title if a longer headline is needed than what you want to appear in navigation.\",\"textformatters\":[\"TextformatterEntities\"],\"collapsed\":2,\"size\":0,\"maxlength\":1024}'); + +DROP TABLE IF EXISTS `modules`; +CREATE TABLE `modules` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `class` varchar(128) CHARACTER SET ascii NOT NULL, + `flags` int(11) NOT NULL DEFAULT '0', + `data` text NOT NULL, + `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `class` (`class`) +) ENGINE=MyISAM AUTO_INCREMENT=158 DEFAULT CHARSET=utf8; + +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('1', 'FieldtypeTextarea', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('2', 'FieldtypeNumber', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('3', 'FieldtypeText', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('4', 'FieldtypePage', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('30', 'InputfieldForm', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('6', 'FieldtypeFile', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('7', 'ProcessPageEdit', '1', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('10', 'ProcessLogin', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('12', 'ProcessPageList', '0', '{\"pageLabelField\":\"title\",\"paginationLimit\":25,\"limit\":50}', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('121', 'ProcessPageEditLink', '1', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('14', 'ProcessPageSort', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('15', 'InputfieldPageListSelect', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('117', 'JqueryUI', '1', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('17', 'ProcessPageAdd', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('125', 'SessionLoginThrottle', '3', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('122', 'InputfieldPassword', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('25', 'InputfieldAsmSelect', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('116', 'JqueryCore', '1', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('27', 'FieldtypeModule', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('28', 'FieldtypeDatetime', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('29', 'FieldtypeEmail', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('108', 'InputfieldURL', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('32', 'InputfieldSubmit', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('33', 'InputfieldWrapper', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('34', 'InputfieldText', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('35', 'InputfieldTextarea', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('36', 'InputfieldSelect', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('37', 'InputfieldCheckbox', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('38', 'InputfieldCheckboxes', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('39', 'InputfieldRadios', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('40', 'InputfieldHidden', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('41', 'InputfieldName', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('43', 'InputfieldSelectMultiple', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('45', 'JqueryWireTabs', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('46', 'ProcessPage', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('47', 'ProcessTemplate', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('48', 'ProcessField', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('50', 'ProcessModule', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('114', 'PagePermissions', '3', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('97', 'FieldtypeCheckbox', '1', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('115', 'PageRender', '3', '{\"clearCache\":1}', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('55', 'InputfieldFile', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('56', 'InputfieldImage', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('57', 'FieldtypeImage', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('60', 'InputfieldPage', '0', '{\"inputfieldClasses\":[\"InputfieldSelect\",\"InputfieldSelectMultiple\",\"InputfieldCheckboxes\",\"InputfieldRadios\",\"InputfieldAsmSelect\",\"InputfieldPageListSelect\",\"InputfieldPageListSelectMultiple\"]}', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('61', 'TextformatterEntities', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('66', 'ProcessUser', '0', '{\"showFields\":[\"name\",\"email\",\"roles\"]}', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('67', 'MarkupAdminDataTable', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('68', 'ProcessRole', '0', '{\"showFields\":[\"name\"]}', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('76', 'ProcessList', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('78', 'InputfieldFieldset', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('79', 'InputfieldMarkup', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('80', 'InputfieldEmail', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('89', 'FieldtypeFloat', '1', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('83', 'ProcessPageView', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('84', 'FieldtypeInteger', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('85', 'InputfieldInteger', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('86', 'InputfieldPageName', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('87', 'ProcessHome', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('90', 'InputfieldFloat', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('94', 'InputfieldDatetime', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('98', 'MarkupPagerNav', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('129', 'ProcessPageEditImageSelect', '1', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('103', 'JqueryTableSorter', '1', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('104', 'ProcessPageSearch', '1', '{\"searchFields\":\"title\",\"displayField\":\"title path\"}', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('105', 'FieldtypeFieldsetOpen', '1', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('106', 'FieldtypeFieldsetClose', '1', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('107', 'FieldtypeFieldsetTabOpen', '1', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('109', 'ProcessPageTrash', '1', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('111', 'FieldtypePageTitle', '1', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('112', 'InputfieldPageTitle', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('113', 'MarkupPageArray', '3', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('131', 'InputfieldButton', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('133', 'FieldtypePassword', '1', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('134', 'ProcessPageType', '1', '{\"showFields\":[]}', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('135', 'FieldtypeURL', '1', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('136', 'ProcessPermission', '1', '{\"showFields\":[\"name\",\"title\"]}', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('137', 'InputfieldPageListSelectMultiple', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('138', 'ProcessProfile', '1', '{\"profileFields\":[\"pass\",\"email\"]}', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('139', 'SystemUpdater', '1', '{\"systemVersion\":7}', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('148', 'AdminThemeDefault', '2', '{\"colors\":\"classic\"}', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('149', 'InputfieldSelector', '2', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('150', 'ProcessPageLister', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('151', 'JqueryMagnific', '1', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('152', 'PagePathHistory', '3', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('155', 'InputfieldCKEditor', '0', '', NOW()); +INSERT INTO `modules` (`id`, `class`, `flags`, `data`, `created`) VALUES('156', 'MarkupHTMLPurifier', '0', '', NOW()); + +DROP TABLE IF EXISTS `page_path_history`; +CREATE TABLE `page_path_history` ( + `path` varchar(255) NOT NULL, + `pages_id` int(10) unsigned NOT NULL, + `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`path`), + KEY `pages_id` (`pages_id`), + KEY `created` (`created`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `pages`; +CREATE TABLE `pages` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `parent_id` int(11) unsigned NOT NULL DEFAULT '0', + `templates_id` int(11) unsigned NOT NULL DEFAULT '0', + `name` varchar(128) CHARACTER SET ascii NOT NULL, + `status` int(10) unsigned NOT NULL DEFAULT '1', + `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `modified_users_id` int(10) unsigned NOT NULL DEFAULT '2', + `created` timestamp NOT NULL DEFAULT '2015-12-18 06:09:00', + `created_users_id` int(10) unsigned NOT NULL DEFAULT '2', + `sort` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + UNIQUE KEY `name_parent_id` (`name`,`parent_id`), + KEY `parent_id` (`parent_id`), + KEY `templates_id` (`templates_id`), + KEY `modified` (`modified`), + KEY `created` (`created`), + KEY `status` (`status`) +) ENGINE=MyISAM AUTO_INCREMENT=1009 DEFAULT CHARSET=utf8; + +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('1', '0', '1', 'home', '9', NOW(), '41', NOW(), '2', '0'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('2', '1', '2', 'processwire', '1035', NOW(), '40', NOW(), '2', '5'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('3', '2', '2', 'page', '21', NOW(), '41', NOW(), '2', '0'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('6', '3', '2', 'add', '1045', NOW(), '41', NOW(), '2', '0'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('7', '1', '2', 'trash', '1039', NOW(), '41', NOW(), '2', '6'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('8', '3', '2', 'list', '21', NOW(), '41', NOW(), '2', '1'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('9', '3', '2', 'sort', '1047', NOW(), '41', NOW(), '2', '2'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('10', '3', '2', 'edit', '1045', NOW(), '41', NOW(), '2', '3'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('11', '22', '2', 'template', '21', NOW(), '41', NOW(), '2', '0'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('16', '22', '2', 'field', '21', NOW(), '41', NOW(), '2', '2'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('21', '2', '2', 'module', '21', NOW(), '41', NOW(), '2', '2'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('22', '2', '2', 'setup', '21', NOW(), '41', NOW(), '2', '1'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('23', '2', '2', 'login', '1035', NOW(), '41', NOW(), '2', '4'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('27', '1', '29', 'http404', '1035', NOW(), '41', NOW(), '3', '4'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('28', '2', '2', 'access', '13', NOW(), '41', NOW(), '2', '3'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('29', '28', '2', 'users', '29', NOW(), '41', NOW(), '2', '0'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('30', '28', '2', 'roles', '29', NOW(), '41', NOW(), '2', '1'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('31', '28', '2', 'permissions', '29', NOW(), '41', NOW(), '2', '2'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('32', '31', '5', 'page-edit', '25', NOW(), '41', NOW(), '2', '2'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('34', '31', '5', 'page-delete', '25', NOW(), '41', NOW(), '2', '3'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('35', '31', '5', 'page-move', '25', NOW(), '41', NOW(), '2', '4'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('36', '31', '5', 'page-view', '25', NOW(), '41', NOW(), '2', '0'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('37', '30', '4', 'guest', '25', NOW(), '41', NOW(), '2', '0'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('38', '30', '4', 'superuser', '25', NOW(), '41', NOW(), '2', '1'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('41', '29', '3', 'admin', '1', NOW(), '40', NOW(), '2', '0'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('40', '29', '3', 'guest', '25', NOW(), '41', NOW(), '2', '1'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('50', '31', '5', 'page-sort', '25', NOW(), '41', NOW(), '41', '5'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('51', '31', '5', 'page-template', '25', NOW(), '41', NOW(), '41', '6'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('52', '31', '5', 'user-admin', '25', NOW(), '41', NOW(), '41', '10'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('53', '31', '5', 'profile-edit', '1', NOW(), '41', NOW(), '41', '13'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('54', '31', '5', 'page-lock', '1', NOW(), '41', NOW(), '41', '8'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('300', '3', '2', 'search', '1045', NOW(), '41', NOW(), '2', '5'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('301', '3', '2', 'trash', '1047', NOW(), '41', NOW(), '2', '5'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('302', '3', '2', 'link', '1041', NOW(), '41', NOW(), '2', '6'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('303', '3', '2', 'image', '1041', NOW(), '41', NOW(), '2', '7'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('304', '2', '2', 'profile', '1025', NOW(), '41', NOW(), '41', '5'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('1000', '1', '26', 'search', '1025', NOW(), '41', NOW(), '2', '3'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('1001', '1', '29', 'about', '1', NOW(), '41', NOW(), '2', '0'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('1002', '1001', '29', 'what', '1', NOW(), '41', NOW(), '2', '0'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('1004', '1001', '29', 'background', '1', NOW(), '41', NOW(), '2', '1'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('1005', '1', '34', 'site-map', '1', NOW(), '41', NOW(), '2', '2'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('1006', '31', '5', 'page-lister', '1', NOW(), '40', NOW(), '40', '9'); +INSERT INTO `pages` (`id`, `parent_id`, `templates_id`, `name`, `status`, `modified`, `modified_users_id`, `created`, `created_users_id`, `sort`) VALUES('1007', '3', '2', 'lister', '1', NOW(), '40', NOW(), '40', '8'); + +DROP TABLE IF EXISTS `pages_access`; +CREATE TABLE `pages_access` ( + `pages_id` int(11) NOT NULL, + `templates_id` int(11) NOT NULL, + `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`pages_id`), + KEY `templates_id` (`templates_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `pages_access` (`pages_id`, `templates_id`, `ts`) VALUES('37', '2', NOW()); +INSERT INTO `pages_access` (`pages_id`, `templates_id`, `ts`) VALUES('38', '2', NOW()); +INSERT INTO `pages_access` (`pages_id`, `templates_id`, `ts`) VALUES('32', '2', NOW()); +INSERT INTO `pages_access` (`pages_id`, `templates_id`, `ts`) VALUES('34', '2', NOW()); +INSERT INTO `pages_access` (`pages_id`, `templates_id`, `ts`) VALUES('35', '2', NOW()); +INSERT INTO `pages_access` (`pages_id`, `templates_id`, `ts`) VALUES('36', '2', NOW()); +INSERT INTO `pages_access` (`pages_id`, `templates_id`, `ts`) VALUES('50', '2', NOW()); +INSERT INTO `pages_access` (`pages_id`, `templates_id`, `ts`) VALUES('51', '2', NOW()); +INSERT INTO `pages_access` (`pages_id`, `templates_id`, `ts`) VALUES('52', '2', NOW()); +INSERT INTO `pages_access` (`pages_id`, `templates_id`, `ts`) VALUES('53', '2', NOW()); +INSERT INTO `pages_access` (`pages_id`, `templates_id`, `ts`) VALUES('54', '2', NOW()); +INSERT INTO `pages_access` (`pages_id`, `templates_id`, `ts`) VALUES('1006', '2', NOW()); + +DROP TABLE IF EXISTS `pages_parents`; +CREATE TABLE `pages_parents` ( + `pages_id` int(10) unsigned NOT NULL, + `parents_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`pages_id`,`parents_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('2', '1'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('3', '1'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('3', '2'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('7', '1'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('22', '1'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('22', '2'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('28', '1'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('28', '2'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('29', '1'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('29', '2'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('29', '28'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('30', '1'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('30', '2'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('30', '28'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('31', '1'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('31', '2'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('31', '28'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('1001', '1'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('1002', '1'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('1002', '1001'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('1004', '1'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('1004', '1001'); +INSERT INTO `pages_parents` (`pages_id`, `parents_id`) VALUES('1005', '1'); + +DROP TABLE IF EXISTS `pages_sortfields`; +CREATE TABLE `pages_sortfields` ( + `pages_id` int(10) unsigned NOT NULL DEFAULT '0', + `sortfield` varchar(20) NOT NULL DEFAULT '', + PRIMARY KEY (`pages_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +DROP TABLE IF EXISTS `session_login_throttle`; +CREATE TABLE `session_login_throttle` ( + `name` varchar(128) NOT NULL, + `attempts` int(10) unsigned NOT NULL DEFAULT '0', + `last_attempt` int(10) unsigned NOT NULL, + PRIMARY KEY (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `templates`; +CREATE TABLE `templates` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) CHARACTER SET ascii NOT NULL, + `fieldgroups_id` int(10) unsigned NOT NULL DEFAULT '0', + `flags` int(11) NOT NULL DEFAULT '0', + `cache_time` mediumint(9) NOT NULL DEFAULT '0', + `data` text NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`), + KEY `fieldgroups_id` (`fieldgroups_id`) +) ENGINE=MyISAM AUTO_INCREMENT=43 DEFAULT CHARSET=utf8; + +INSERT INTO `templates` (`id`, `name`, `fieldgroups_id`, `flags`, `cache_time`, `data`) VALUES('2', 'admin', '2', '8', '0', '{\"useRoles\":1,\"parentTemplates\":[2],\"allowPageNum\":1,\"redirectLogin\":23,\"slashUrls\":1,\"noGlobal\":1,\"modified\":1406317841}'); +INSERT INTO `templates` (`id`, `name`, `fieldgroups_id`, `flags`, `cache_time`, `data`) VALUES('3', 'user', '3', '8', '0', '{\"useRoles\":1,\"noChildren\":1,\"parentTemplates\":[2],\"slashUrls\":1,\"pageClass\":\"User\",\"noGlobal\":1,\"noMove\":1,\"noTrash\":1,\"noSettings\":1,\"noChangeTemplate\":1,\"nameContentTab\":1}'); +INSERT INTO `templates` (`id`, `name`, `fieldgroups_id`, `flags`, `cache_time`, `data`) VALUES('4', 'role', '4', '8', '0', '{\"noChildren\":1,\"parentTemplates\":[2],\"slashUrls\":1,\"pageClass\":\"Role\",\"noGlobal\":1,\"noMove\":1,\"noTrash\":1,\"noSettings\":1,\"noChangeTemplate\":1,\"nameContentTab\":1}'); +INSERT INTO `templates` (`id`, `name`, `fieldgroups_id`, `flags`, `cache_time`, `data`) VALUES('5', 'permission', '5', '8', '0', '{\"noChildren\":1,\"parentTemplates\":[2],\"slashUrls\":1,\"guestSearchable\":1,\"pageClass\":\"Permission\",\"noGlobal\":1,\"noMove\":1,\"noTrash\":1,\"noSettings\":1,\"noChangeTemplate\":1,\"nameContentTab\":1}'); +INSERT INTO `templates` (`id`, `name`, `fieldgroups_id`, `flags`, `cache_time`, `data`) VALUES('1', 'home', '1', '0', '0', '{\"useRoles\":1,\"noParents\":1,\"slashUrls\":1,\"modified\":1409155727,\"roles\":[37]}'); +INSERT INTO `templates` (`id`, `name`, `fieldgroups_id`, `flags`, `cache_time`, `data`) VALUES('29', 'basic-page', '83', '0', '0', '{\"slashUrls\":1,\"modified\":1409155715}'); +INSERT INTO `templates` (`id`, `name`, `fieldgroups_id`, `flags`, `cache_time`, `data`) VALUES('26', 'search', '80', '0', '0', '{\"noChildren\":1,\"noParents\":1,\"allowPageNum\":1,\"slashUrls\":1,\"modified\":1409155785}'); +INSERT INTO `templates` (`id`, `name`, `fieldgroups_id`, `flags`, `cache_time`, `data`) VALUES('34', 'sitemap', '88', '0', '0', '{\"noChildren\":1,\"noParents\":1,\"redirectLogin\":23,\"slashUrls\":1,\"modified\":1409155794}'); + +UPDATE pages SET created_users_id=41, modified_users_id=41, created=NOW(), modified=NOW(); + +--- /WireDatabaseBackup {"numTables":20,"numCreateTables":27,"numInserts":305,"numSeconds":0} \ No newline at end of file diff --git a/site-beginner/install/screenshot.png b/site-beginner/install/screenshot.png new file mode 100644 index 00000000..e1001143 Binary files /dev/null and b/site-beginner/install/screenshot.png differ diff --git a/site-beginner/modules/README.txt b/site-beginner/modules/README.txt new file mode 100644 index 00000000..8844fbe0 --- /dev/null +++ b/site-beginner/modules/README.txt @@ -0,0 +1,89 @@ +ABOUT /SITE/MODULES/ +==================== +This directory /site/modules/ is where you may install additional plugin modules. +These modules are specific to your site only. There is also a corresponding +/wire/modules/ directory, which contains ProcessWire's core modules (and best to +leave those alone). + +If safe for your hosting environment, you may wish to make this directory +writable to PHP so that the installation of your modules can be managed from +ProcessWire's admin. However, this is not necessarily safe in all shared hosting +environments and is completely optional. + + +Where to get modules? +--------------------- +Visit the modules directory at: http://modules.processwire.com + + +Installing modules from the ProcessWire admin +--------------------------------------------- +If your /site/modules/ directory is writable, you can install modules from +ProcessWire's admin directly from the Modules Directory, from a ZIP file or from +a URL to a ZIP file. In your ProcessWire admin, see Modules > New for +installation options. + + +Installing modules from the file system +--------------------------------------- +Each module (and any related files) should live in a directory of its own. The +directory should generally carry the same name as the module. For instance, if +you are installing a module named ProcessDatabaseBackups.module, then it should +live in the directory /site/modules/ProcessDatabaseBackups/. + +Once you have placed a new module in this directory, you need to let ProcessWire +know about it. Login to the admin and click "Modules". Then click the "Check for +new modules" button. It will find your new module(s). Click the "Install" button +next to any new modules that you want to install. + + +Removing modules +---------------- +The first step in removing a module is to uninstall it from ProcessWire (if it +isn't already). You do this by going to the "Modules" page, and "Site" tab in +your ProcessWire admin. Click the "Uninstall" button next to the module you +want to remove. + +After the module is uninstalled, you may remove the module files. If your +modules file system is writable to ProcessWire, it will give you a "Delete" +button next to the module in your "Modules" admin page. You may click that to +remove the module files. + +If your file system is not writable, you may remove the module files manually +from the file system (via SFTP or whatever tool you are using to manage your +files on the server). + + +Interested in learning how to make your own modules? +---------------------------------------------------- +We've created two "Hello World" modules as examples for those interested in +learning module development: + +- Helloworld.module demonstrates the basics of modules and hooks. + http://modules.processwire.com/modules/helloworld/ + +- ProcessHello.module demonstrates the basics of how to create a Process + module. Process modules are those that create applications in the admin. + http://modules.processwire.com/modules/process-hello/ + +There is a module development forum located at: +https://processwire.com/talk/forum/19-moduleplugin-development/ + +For a tutorial on how to create modules, see: +http://wiki.processwire.com/index.php/Module_Creation + + +Additional resources +-------------------- + +To find and download new modules, see the modules directory at: +http://modules.processwire.com/ + +For more information about modules, see the documentation at: +http://processwire.com/api/modules/ + +For discussion and support of modules, see: +http://processwire.com/talk/forum/4-modulesplugins/ + + + diff --git a/site-beginner/templates/README.txt b/site-beginner/templates/README.txt new file mode 100644 index 00000000..f0b4b60a --- /dev/null +++ b/site-beginner/templates/README.txt @@ -0,0 +1,221 @@ +Welcome to the Default/Basic Site Profile (Beginner Edition) +============================================================ + +This is a plain text document. If you are currently online with +internet access, you will find it much nicer to read an HTML +formatted version of this document located at: + +http://processwire.com/docs/tutorials/default-site-profile/ + +Are you already somewhat familiar with ProcessWire and/or PHP? You +might also want to look into the Intermediate Edition of this profile. + +Need multi-language support? The multi-language version of this +default site profile is a good place to start. + +Both the intermediate and multi-language versions of this site +profile are available as installation options when installing +ProcessWire. + +Introduction +============ + +Just getting started with ProcessWire and aren't totally clear on what +template files are? The good news is that template files aren't anything +other than regular HTML or PHP files, and you can use them however you +want! + +If you know enough to create an HTML or PHP document, then you already +know how to use ProcessWire template files. The only difference is that +ProcessWire provides your template files with certain variables that +you may choose to use, or not use. Most notable is the $page variable, +which contains all the fields of text or other information contained +by the page being viewed. + +For instance, $page->title contains the text contained in the Title +field of the current page, and $page->body contains the text for the +Body field of the current page. You can choose to output those wherever +you want. A really simple template file might look like a regular HTML +document except for where you want to output the dynamic portions (like +title and body). Here's an example: + + + + <?= $page->title ?> + + +

    title ?>

    + body ?> + + + +That's all that a template file is. Now when we're building something +for real, we like to save ourselves as much work as possible and avoid +writing the same HTML markup in multiple places. In order to do that +we'll usually isolate the repetitive markup into separate files or +functions so that we don't have to write it more than once. That's +not required of course, but it's a good strategy to save you time and +make it easier to maintain your site further down the road. + +Template file strategies +======================== + +The two most popular strategies for template files are: + + 1. Direct Output is the simplest strategy and the one used by the + beginner edition of this site profile. While it doesn't scale as + well as other strategies, it is a very good point to start from. + If you've ever worked with WordPress templates, chances are you + already know how Direct Output works. Read more about the Direct + Output strategy: + http://processwire.com/to/direct-output/ + + 2. Delayed Output is the strategy used by the intermediate edition + of this site profile. It is also quite simple but involves + populating content to placeholder variables rather than outputting + directly. As a result it may take a few more seconds to understand + than direct output, but the result is more scalable and + maintainable. Read more about Delayed Output here: + http://processwire.com/to/delayed-output/ + + +How this Default Site Profile works (Beginner Edition) +====================================================== + +This Default Site Profile (beginner edition) uses the Direct Output +strategy. When a page is viewed on your site, here's what happens: + + 1. The initialization file is loaded (_init.php). + Here we use it just to define a shared function for navigation. + + 2. The template file is loaded (i.e. basic-page.php or another). + It outputs the content for the page. + + +Below are more details on exactly what takes place and in these two +steps outlined above: + + 1. The initialization file is loaded (_init.php) + --------------------------------------------- + This step is completely optional with direct output, but we find + it handy to use this file to define our shared functions (if any). + In the case of this profile, we define a single renderNavTree() + function. It is useful to have this as a re-usable function since + we use it to generate markup for more than one place (specifically, + for sidebar navigation and for the sitemap). However, if you have + any confusion about this, ignore it for now and focus on #2 below + as an initialization file is completely optional. + + + 2. The template file is loaded (i.e. basic-page.php or another) + ------------------------------------------------------ + Next, ProcessWire loads the template file used by the page being + viewed. For example, most pages here use basic-page.php. + + The first thing that our template file does is include the HTML + header markup, which we've put in a file called _head.php: + + include("./_head.php"); + + The above is simply a PHP function that says "include this file". + The leading "./" just means "from the current directory". We also + have an underscore "_" prepended to our filename here as a way + to identify this as an include file rather than a regular template + file. While completely optional, the underscore does also make + ProcessWire ignore it when looking for new template files, so you + may find it handy to use this convention in your own include files. + An alternate would be to use .inc as an extension rather than .php. + + Have a look in the _head.php file now so you can see what's there. + It is basically half of an HTML file. Now have a look in _foot.php, + that's the other half. Notice that all the template files that + include _head.php at the beginning also include _foot.php at the + ending. This is to ensure there is a complete HTML document being + output. + + To conclude, our template files (using direct output) are focused + on outputting what goes in-between the _head.php and _foot.php. + In our case, this is always a
    ...
    and + optionally a . But for your own + template files you might choose to output something completely + different. + +Files that make up this profile +=============================== + +Here is a summary of what is in each of the files in this directory. +We also recommend reviewing them in this order: + +- _head.php + HTML header (top half of HTML document) + +- _foot.php + HTML footer (bottom half of HTML document) + +- basic-page.php + Template file outputting #content and #sidebar columns. This + template file is used by most pages in this small site. + +- home.php + Template file used by homepage. Note that since the homepage uses + nearly the same layout as the other pages in the site, this + template file simply includes basic-page.php. No need two have + more than one template file with the same contents. + +- sitemap.php + Outputs a sitemap of the entire site. + +- search.php + Outputs results of site search queries. + +- _init.php + Initialization file that we use to define a shared function for + generating navigation markup. + + +More template file resources +============================ + +- How do template files work? + https://processwire.com/api/templates/ + Official documentation on template files. + +- API variables + https://processwire.com/api/variables/ + We mentioned $page above, but here are all the other API variables + your template file can make use of. + +- API cheatsheet + http://cheatsheet.processwire.com/ + Once you've got the basics down, this cheatsheet is invaluable in + describing all the properties and functions available to your + template files. + + +Tutorials that help with template files +======================================= + +- Hello Worlds Tutoral, by Ryan Cramer + http://processwire.com/docs/tutorials/hello-worlds/ + The Hello Worlds tutorial gently introduces ProcessWire and template + files, starting from a blank slate. + +- "But what if I don't know how to code?", by Joss Sanglier + http://processwire.com/docs/tutorials/but-what-if-i-dont-know-how-to-code/ + This particular series of tutorials will not only introduce you to + ProcessWire, but step by step, will give you those small bits of coding + knowledge that will get you going and open up this amazing world of a + Content Management Framework. + +- Installing a CSS Framework, by Joss Sanglier + http://processwire.com/docs/tutorials/installing-a-css-framework/ + A quick demonstration about how easy it is to use one of the many CSS + frameworks available to designers. + +- How to structure your template files, by Ryan Cramer + http://processwire.com/docs/tutorials/how-to-structure-your-template-files/ + This tutorial contrasts and compares the direct output and delayed + output strategies and more. It is a very good introduction to using + ProcessWire template files. + + diff --git a/site-beginner/templates/_foot.php b/site-beginner/templates/_foot.php new file mode 100644 index 00000000..1480f492 --- /dev/null +++ b/site-beginner/templates/_foot.php @@ -0,0 +1,22 @@ + + + + + + + + + diff --git a/site-beginner/templates/_func.php b/site-beginner/templates/_func.php new file mode 100644 index 00000000..4a35e515 --- /dev/null +++ b/site-beginner/templates/_func.php @@ -0,0 +1,98 @@ + navigation + * + * This is here to demonstrate an example of a simple shared function. + * Usage is completely optional. + * + * @param PageArray $items + * + */ +function renderNav(PageArray $items) { + + if(!$items->count()) return; + + echo ""; +} + + +/** + * Given a group of pages render a tree of navigation + * + * @param Page|PageArray $items Page to start the navigation tree from or pages to render + * @param int $maxDepth How many levels of navigation below current should it go? + * + */ +function renderNavTree($items, $maxDepth = 3) { + + // if we've been given just one item, convert it to an array of items + if($items instanceof Page) $items = array($items); + + // if there aren't any items to output, exit now + if(!count($items)) return; + + // $out is where we store the markup we are creating in this function + // start our