From 1462dc5c0a6722086054e59da16838a20afca841 Mon Sep 17 00:00:00 2001 From: Andrew Aitken-Fincham Date: Wed, 17 Feb 2021 14:05:52 +1300 Subject: [PATCH 01/12] return nginx.conf example to docs --- .../01_Installation/How_To/Configure_Nginx.md | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/docs/en/00_Getting_Started/01_Installation/How_To/Configure_Nginx.md b/docs/en/00_Getting_Started/01_Installation/How_To/Configure_Nginx.md index da5cc6527d1..d376ad7e65d 100644 --- a/docs/en/00_Getting_Started/01_Installation/How_To/Configure_Nginx.md +++ b/docs/en/00_Getting_Started/01_Installation/How_To/Configure_Nginx.md @@ -23,6 +23,68 @@ Especially be aware of [accidental php-execution](https://nealpoole.com/blog/201 But enough of the disclaimer, on to the actual configuration — typically in `nginx.conf`: +```nginx +server { + include mime.types; + default_type application/octet-stream; + client_max_body_size 0; # Manage this in php.ini + listen 80; + root /path/to/ss/folder; + server_name example.com www.example.com; + # Defend against SS-2015-013 -- http://www.silverstripe.org/software/download/security-releases/ss-2015-013 + if ($http_x_forwarded_host) { + return 400; + } + location / { + try_files $uri /framework/main.php?url=$uri&$query_string; + } + error_page 404 /assets/error-404.html; + error_page 500 /assets/error-500.html; + location ^~ /assets/ { + sendfile on; + try_files $uri =404; + } + location ~ /framework/.*(main|rpc|tiny_mce_gzip)\.php$ { + fastcgi_buffer_size 32k; + fastcgi_busy_buffers_size 64k; + fastcgi_buffers 4 32k; + fastcgi_keep_conn on; + fastcgi_pass 127.0.0.1:9000; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + } + # Denials + location ~ /\.. { + deny all; + } + location ~ \.ss$ { + satisfy any; + allow 127.0.0.1; + deny all; + } + location ~ web\.config$ { + deny all; + } + location ~ \.ya?ml$ { + deny all; + } + location ~* README.*$ { + deny all; + } + location ^~ /vendor/ { + deny all; + } + location ~* /silverstripe-cache/ { + deny all; + } + location ~* composer\.(json|lock)$ { + deny all; + } + location ~* /(cms|framework)/silverstripe_version$ { + deny all; + } +} ``` The above configuration sets up a virtual host `example.com` with From f69daa8aeb4d5e44b0e39751c0e9f3137494d9ba Mon Sep 17 00:00:00 2001 From: Andrew Aitken-Fincham Date: Wed, 17 Feb 2021 14:11:22 +1300 Subject: [PATCH 02/12] return windows examples to docs --- .../00_Getting_Started/01_Installation/03_Windows.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/en/00_Getting_Started/01_Installation/03_Windows.md b/docs/en/00_Getting_Started/01_Installation/03_Windows.md index a61260911d5..6ddee7c987e 100644 --- a/docs/en/00_Getting_Started/01_Installation/03_Windows.md +++ b/docs/en/00_Getting_Started/01_Installation/03_Windows.md @@ -32,6 +32,9 @@ See the [Composer documentation](https://getcomposer.org/doc/00-intro.md#install Once you have installed the above, open a command line and use the following command to get a fresh copy of SilverStripe stable code installed into a 'silverstripe' sub-folder (note here we are using gitbash paths). +```shell +$ cd /c/wamp/www +$ composer create-project silverstripe/installer ./silverstripe ``` ### Zip download @@ -66,4 +69,12 @@ control. Due to some changes to `mod_dir` in [Apache 2.4](http://httpd.apache.org/docs/current/mod/mod_dir.html#DirectoryCheckHandler) (precedence of handlers), index.php gets added to the URLs as soon as you navigate to the homepage of your site. Further requests are then handled by index.php rather than `mod_rewrite` (framework/main.php). To fix this place the following within the `mod_rewrite` section of your .htaccess file: +```apacheconf + + # Turn off index.php handling requests to the homepage fixes issue in apache >=2.4 + + DirectoryIndex disabled + +# ------ # + ``` From c5b86d2b05ea90c6ab4e2509e0e46bddf9d67036 Mon Sep 17 00:00:00 2001 From: Andrew Aitken-Fincham Date: Wed, 17 Feb 2021 14:16:24 +1300 Subject: [PATCH 03/12] return macosx examples to docs --- .../Mac_OSX_Homebrew.md | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/docs/en/00_Getting_Started/01_Installation/04_Other_installation_Options/Mac_OSX_Homebrew.md b/docs/en/00_Getting_Started/01_Installation/04_Other_installation_Options/Mac_OSX_Homebrew.md index ddc0a4add80..850d7fe6a78 100644 --- a/docs/en/00_Getting_Started/01_Installation/04_Other_installation_Options/Mac_OSX_Homebrew.md +++ b/docs/en/00_Getting_Started/01_Installation/04_Other_installation_Options/Mac_OSX_Homebrew.md @@ -19,11 +19,15 @@ Run the following command to install Xcode Command Line Tools. ``` +Now you can install Homebrew itself: + ``` ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" ``` +## Install PHP + First we're telling Homebrew about some new repositories to get the PHP installation from: ``` @@ -32,11 +36,15 @@ First we're telling Homebrew about some new repositories to get the PHP installa ``` +We're installing PHP 5.6 here, with the required `mcrypt` module: + ``` - brew install php55 php55-mcrypt + brew install php56 php56-mcrypt ``` +There's a [Homebrew Troubleshooting](https://github.com/Homebrew/homebrew/blob/master/share/doc/homebrew/Troubleshooting.md) guide if Homebrew doesn't work out as expected (run `brew update` and `brew doctor`). + Have a look at the [brew-php-switcher](https://github.com/philcook/brew-php-switcher) project to install multiple PHP versions in parallel and switch between them easily. @@ -51,11 +59,15 @@ project to install multiple PHP versions in parallel and switch between them eas ``` +To start the database server on boot, run the following: + ``` ln -sfv /usr/local/opt/mariadb/*.plist ~/Library/LaunchAgents ``` +You can also use `mysql.server start` and `mysql.server stop` on demand. + ## Configure PHP and Apache We're not installing Apache, since OSX already ships with a perfectly fine installation of it. @@ -69,10 +81,15 @@ and uncomment/add the following lines to activate the required modules: ``` +Change the `DocumentRoot` setting to your user folder (replacing `` with your OSX user name): +``` + ``` DocumentRoot "/Users//Sites" ``` + +Now find the section starting with `` and change it as follows, again replacing `` with your OSX user name: ``` @@ -84,6 +101,8 @@ again replacing `` with your OSX user name: ``` + +We also recommend running the web server process with your own user on a development environment, since it makes permissions easier to handle when running commands both from the command line and through the web server. Find and adjust the following options, replacing the `` placeholder: @@ -94,20 +113,27 @@ replacing the `` placeholder: ``` +Now start the web server: + ``` sudo apachectl start ``` +Every configuration change requires a restart: + ``` sudo apachectl restart ``` +You can also load this webserver on boot: + ``` sudo launchctl load -w /System/Library/LaunchDaemons/org.apache.httpd.plist ``` +After staring the webserver, you should see a simple "Forbidden" page generated by Apache when accessing `http://localhost`. ## SilverStripe Installation From fd96017cddab5730fdb7c4226236fbd268104890 Mon Sep 17 00:00:00 2001 From: Andrew Aitken-Fincham Date: Wed, 17 Feb 2021 14:26:37 +1300 Subject: [PATCH 04/12] return vagrant examples to docs --- .../Vagrant_Virtualbox.md | 103 +++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-) diff --git a/docs/en/00_Getting_Started/01_Installation/04_Other_installation_Options/Vagrant_Virtualbox.md b/docs/en/00_Getting_Started/01_Installation/04_Other_installation_Options/Vagrant_Virtualbox.md index bc8f302fce9..c23d767b94c 100644 --- a/docs/en/00_Getting_Started/01_Installation/04_Other_installation_Options/Vagrant_Virtualbox.md +++ b/docs/en/00_Getting_Started/01_Installation/04_Other_installation_Options/Vagrant_Virtualbox.md @@ -26,10 +26,17 @@ Vagrant downloads and sets up an entire operating system. Most of this requires using only the command line and text editor or IDE. Create a folder where your vagrant will be in and browse to the folder in the command line: + +```shell +mkdir virtuallythere +cd virtuallythere ``` ### Creating the Vagrantfile Create/Browse to the folder you’ll be developing in: + +```shell +vagrant init ``` In its current state, you could start the vagrant machine and it will run, but you won't be able to do much with it yet. @@ -38,11 +45,17 @@ In its current state, you could start the vagrant machine and it will run, but y Open the `Vagrantfile` that was created in your vagrant folder with your preferred text editor. Look for the line which describes the box you are going to use: + +```ruby +config.vm.box = "base" ``` This defines what pre-built Operating System the vagrant machine will be using. We'll be changing `base` to something closer to what we’d like, perhaps similar to your production server, you can find a range of boxes [listed here](https://atlas.hashicorp.com/search) We've chosen to use `RHEL7.0`, but you can easily change it to suit your needs. + +```ruby +config.vm.box = "box-cutter/centos70" ``` *Important*: Because this is redhat, the shell commands used later on will be using `yum install` instead of `apt-get install` for Debian based boxes. @@ -52,23 +65,43 @@ Now we’ll add the vagrant machine to our computer’s private network, this wi So this will be your own development environment! To do that, look for this line: + +```ruby +# config.vm.network "private_network", ip: "192.168.33.10" ``` First we’ll need to uncomment it, so delete only the `#` at the start of the line, then add a hostname IP address of your choice to use. + +```ruby +config.vm.hostname = "virtuallythere.dev" +config.vm.network "privatenetwork", ip: "10.1.2.50" ``` + ### Syncing files Next we’ll sync our website folder to the virtual machine, so it has the files needed to run SilverStripe. There are many different ways to do this, depending on your own preferences and possibly different boxes. To keep things simple, we’re going to sync our vagrant folder to the virtual machine, so everything in your vagrant folder will be visible to the virtual machine. Find this line: + +```ruby +config.vm.synced_folder "../data", "/vagrant_data" ``` Then change to match this: + +```ruby +config.vm.synced_folder ".", "/vagrant" ``` ### Setting resources This step is optional, but it is recommended to configure the virtual machine resources allocated to it, so it doesn’t take more resources than it should, something like this should be enough to start with: + +```ruby +config.vm.provider "virtualbox" do |vb| + vb.memory = "1024" + vb.name = "virtuallythere" +end ``` *Important*: This is for Virtualbox again, change “virtualbox” to the virtual platform that you are using, you might need to make sure the setting `vb.memory` is supported by the platform you’re using because it may be different. @@ -77,13 +110,36 @@ This step is optional, but it is recommended to configure the virtual machine re Now we need to setup our environment using shell scripts, this will install software that you need for your server to be working and usable. You could even customise the setup to be closer like your production server. For now find these lines: + +```ruby +# config.vm.provision "shell", inline: <<-SHELL +# sudo apt-get update +# sudo apt-get install -y apache2 +# SHELL ``` + And modify it to call a shell script in your vagrant folder: + +```ruby +config.vm.provision "shell", path: "setup.sh" ``` *Important*: We’re using shell script because we’re using a Linux server, please use the scripting language that your server environment supports. Now to create the `setup.sh` file. This script will setup `php+modules`, `mariadb/mysql` and `apache`, the ones I had listed is the minimal required to get SilverStripe started and working out of the box. + +```shell +yum update -y --disableplugin=fastestmirror +systemctl restart sshd +yum install -y httpd httpd-devel mod_ssl +yum -y install php php-common php-mysql php-pdo php-mcrypt* php-gd php-xml php-mbstring +echo "Include /vagrant/apache/*.conf" >> /etc/httpd/conf/httpd.conf +echo "date.timezone = Pacific/Auckland" >> /etc/php.ini +systemctl start httpd.service +systemctl enable httpd.service +yum install -y mariadb-server mariadb +systemctl start mariadb.service +systemctl enable mariadb.service ``` *Important*: Again, as noted above, this uses RHEL so `yum install` is used, please remember to change to `apt-get install` or other packaging tool as necessary. @@ -92,15 +148,56 @@ Save `setup.sh` in the same folder as your Vagrantfile. ### Setting up Apache If you inspect the script I’ve included above, you’ll notice this line: + +```shell +echo "Include /vagrant/apache/*.conf" >> /etc/httpd/conf/httpd.conf ``` + This will allow us to customise our apache, particularly the VirtualHost part Earlier in the post, I had defined a hostname: + +```ruby +config.vm.hostname = "virtuallythere.dev" ``` -We’ll need to create a conf file for this hostname in a apache folder, create the folder first: + +We’ll need to create a conf file for this hostname in an Apache folder, create the folder first: + +```bash +mkdir apache ``` We'll save a `vagrant.conf` file in the newly created apache folder, and inside we’ll define the VirtualHost: + +```apache +ServerRoot "/etc/httpd" + + AllowOverride none + Require all denied + +DocumentRoot "/vagrant/public" + + Options Indexes FollowSymLinks + AllowOverride All + Require all granted + + + ServerName virtuallythere.dev + ServerAlias www.virtuallythere.dev + DocumentRoot /vagrant/public + LogLevel warn + ServerSignature Off + + Options +FollowSymLinks + Options -ExecCGI -Includes -Indexes + AllowOverride all + Require all granted + + # SilverStripe specific + + php_flag engine off + + ``` ### Download SilverStripe @@ -109,8 +206,10 @@ As mentioned above, you could install SilverStripe by [Composer](https://getcomp ### We’re ready for launch That’s all! When that’s done, run: -``` +```shell +vagrant up +``` If you've been following this guide, you can browse to http://virtuallythere.dev/install if you are using a new installation, or go to http://virtuallythere.dev if you are using an existing SilverStripe installation. If you've modified the hostname, follow the new hostname you've chosen. From 1c674454f058699c25c0ba8ad8b8c58a50178ba9 Mon Sep 17 00:00:00 2001 From: Andrew Aitken-Fincham Date: Wed, 17 Feb 2021 14:33:26 +1300 Subject: [PATCH 05/12] return windows_iis7 examples to docs --- .../04_Other_installation_Options/Windows_IIS7.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/en/00_Getting_Started/01_Installation/04_Other_installation_Options/Windows_IIS7.md b/docs/en/00_Getting_Started/01_Installation/04_Other_installation_Options/Windows_IIS7.md index 70f3680a7b7..39c50a280de 100644 --- a/docs/en/00_Getting_Started/01_Installation/04_Other_installation_Options/Windows_IIS7.md +++ b/docs/en/00_Getting_Started/01_Installation/04_Other_installation_Options/Windows_IIS7.md @@ -135,6 +135,8 @@ This is an op-code cacher which speeds up PHP execution on Windows. php_tidy.dll ``` + + * Go to **Configure error reporting** and check **Development machine** * Go to **Manage all settings** and set the following: ``` @@ -145,6 +147,8 @@ This is an op-code cacher which speeds up PHP execution on Windows. ``` +Tweak the above values as necessary if your requirements differ. + ## Folder permissions for PHP Now we need to set up folder permissions for PHP. Open the php.ini and find the paths for sessions and file uploads. They will look like this: @@ -155,6 +159,8 @@ Now we need to set up folder permissions for PHP. Open the php.ini and find the ``` +Two other important folders to set the permissions on are `assets` and `silverstripe-cache` (if used) in your web root. + You will need to give **Modify** permission to **IUSR** user. To do it right click the folder and choose **Properties**. Then open the security tab, press **Edit** and add the **IUSR** user to the list by clicking the **Add** button. Afterwards tick **Modify** under **Allow** for that user. Repeat these steps for each folder. ![](../../../_images/iis7-iusr-permissions.jpg) @@ -183,10 +189,12 @@ Inside the newly created _ss_environment.php file, insert the following code: ``` +Insert the password you created for SQL Server earlier into the **SS_DATABASE_PASSWORD** field that is currently empty. + * Grab the latest stable version from here: http://www.silverstripe.org/stable-download * Extract contents to **C:\inetpub\wwwroot\ss** -After gettng the code installed, make sure you set the folder permissions properly (see *Folder permissions for PHP* above). +After getting the code installed, make sure you set the folder permissions properly (see *Folder permissions for PHP* above). ## Install the SilverStripe SQL Server module ("mssql") From 50418dc4039ce8a434068ca4e7a52a5af62e772d Mon Sep 17 00:00:00 2001 From: Andrew Aitken-Fincham Date: Wed, 17 Feb 2021 14:41:45 +1300 Subject: [PATCH 06/12] return common_problems examples to docs --- .../01_Installation/05_Common_Problems.md | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/docs/en/00_Getting_Started/01_Installation/05_Common_Problems.md b/docs/en/00_Getting_Started/01_Installation/05_Common_Problems.md index 0980310534e..aecd4762540 100644 --- a/docs/en/00_Getting_Started/01_Installation/05_Common_Problems.md +++ b/docs/en/00_Getting_Started/01_Installation/05_Common_Problems.md @@ -27,6 +27,7 @@ If you can log-in to the CMS as an administrator, append `?isDev=1` to any URL t environment_type: 'dev' ``` + On "live" environments, the `?isDev=1` solution is preferred, as it means that your other visitors don't see ugly (and potentially security sensitive) PHP errors as well. [/warning] @@ -35,6 +36,14 @@ On "live" environments, the `?isDev=1` solution is preferred, as it means that y Due to some changes to `mod_dir` in [Apache 2.4](http://httpd.apache.org/docs/current/mod/mod_dir.html#DirectoryCheckHandler) (precedence of handlers), index.php gets added to the URLs as soon as you navigate to the homepage of your site. Further requests are then handled by index.php rather than `mod_rewrite` (framework/main.php). To fix this place the following within the `mod_rewrite` section of your .htaccess file: +```apacheconf + + # Turn off index.php handling requests to the homepage fixes issue in apache >=2.4 + + DirectoryIndex disabled + +# ------ # + ``` ## My templates don't update on page refresh @@ -100,4 +109,24 @@ If that doesn't work out, here's a little script to run checks in all relevant P Save it as `check.php` into your webroot, and run it as `php check.php` (or open it in your browser). After using the script (and fixing errors afterwards), please remember to remove it again. +```php + $file) { + if ($file->getExtension() != 'php') continue; + if (preg_match('/thirdparty|vendor/',$file->getPathname())) continue; + $content = file_get_contents($file->getPathname()); + if (preg_match('/^[[:blank:]]+<\?' . 'php/', $content)) { + echo sprintf("%s: Space before opening bracket\n", $file->getPathname()); + $matched = true; + } + if (preg_match('/^\?' . '>\n?[[:blank:]]+/m', $content)) { + echo sprintf("%s: Space after closing bracket\n", $file->getPathname()); + $matched = true; + } +} ``` From 432213750221d3ea7f353a4d0b417b537bdecd93 Mon Sep 17 00:00:00 2001 From: Andrew Aitken-Fincham Date: Wed, 17 Feb 2021 14:43:38 +1300 Subject: [PATCH 07/12] return mysql_ssl_support heading to docs --- .../01_Installation/How_To/MySQL_SSL_Support.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/00_Getting_Started/01_Installation/How_To/MySQL_SSL_Support.md b/docs/en/00_Getting_Started/01_Installation/How_To/MySQL_SSL_Support.md index 03bb6b7c48d..64be2879b3b 100644 --- a/docs/en/00_Getting_Started/01_Installation/How_To/MySQL_SSL_Support.md +++ b/docs/en/00_Getting_Started/01_Installation/How_To/MySQL_SSL_Support.md @@ -140,6 +140,8 @@ On your Silverstripe instance: ``` +### Setting up _ss_environment.php to use SSL certificates + [notice] `SS_DATABASE_SERVER does not accept IP-based hostnames. Also, if the domain name of the host does not match the common name you used to generate the server certificate, you will get an `SSL certificate mismatch error`. [/notice] @@ -170,4 +172,4 @@ When running the installer, make sure to check on the `Use _ss_environment file ## Conclusion -That's it! We hope that this article was able to help you configure your remote MySQL SSL secure database connection. \ No newline at end of file +That's it! We hope that this article was able to help you configure your remote MySQL SSL secure database connection. From 3cd68727ee10c207be5967f417470cf2a906b69a Mon Sep 17 00:00:00 2001 From: Andrew Aitken-Fincham Date: Wed, 17 Feb 2021 14:45:32 +1300 Subject: [PATCH 08/12] return hhvm_nginx examples to docs --- .../01_Installation/How_To/Setup_Nginx_and_HHVM.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/en/00_Getting_Started/01_Installation/How_To/Setup_Nginx_and_HHVM.md b/docs/en/00_Getting_Started/01_Installation/How_To/Setup_Nginx_and_HHVM.md index 71abbe917cb..532cf78aff8 100644 --- a/docs/en/00_Getting_Started/01_Installation/How_To/Setup_Nginx_and_HHVM.md +++ b/docs/en/00_Getting_Started/01_Installation/How_To/Setup_Nginx_and_HHVM.md @@ -18,22 +18,30 @@ Install apt sources on Debian 7 (wheezy): ``` +Install apt sources on Ubuntu 14.04 (trusty): + ``` wget -O - http://dl.hhvm.com/conf/hhvm.gpg.key | sudo apt-key add - echo deb http://dl.hhvm.com/ubuntu trusty main | sudo tee /etc/apt/sources.list.d/hhvm.list ``` +Now install the required packages: + ``` sudo apt-get update sudo apt-get install hhvm libgmp-dev libmemcached-dev ``` +Start HHVM automatically on boot: + ``` sudo update-rc.d hhvm defaults ``` + +Please see [Prebuilt Packages for HHVM on HHVM wiki](https://github.com/facebook/hhvm/wiki/Prebuilt%20Packages%20for%20HHVM) for more installation options. Assuming you already have nginx installed, you can then run a script to enable support for @@ -43,6 +51,7 @@ nginx and/or apache2 depending on whether they are installed or not: sudo /usr/share/hhvm/install_fastcgi.sh ``` +For nginx, this will place a file at `/etc/nginx/hhvm.conf` which you can use to include in your nginx server definitions to provide support for PHP requests. In order to get SilverStripe working, you need to add some custom nginx configuration. @@ -95,6 +104,7 @@ Create `/etc/nginx/silverstripe.conf` and add this configuration: } ``` +The above script passes all non-static file requests to `/framework/main.php` in the webroot which relies on `hhvm.conf` being included prior so that php requests are handled. Now in your nginx `server` configuration you can then include the `hhvm.conf` and `silverstripe.conf` files @@ -116,3 +126,5 @@ e.g. `/etc/nginx/sites-enabled/mysite`: } ``` + +For more information on nginx configuration, please see the [nginx installation](configure_nginx) page. From a127a9b954366e0aca896908ecfa194ade3e5b74 Mon Sep 17 00:00:00 2001 From: Andrew Aitken-Fincham Date: Wed, 17 Feb 2021 14:54:03 +1300 Subject: [PATCH 09/12] return composer examples to docs --- docs/en/00_Getting_Started/02_Composer.md | 80 ++++++++++++++++------- 1 file changed, 57 insertions(+), 23 deletions(-) diff --git a/docs/en/00_Getting_Started/02_Composer.md b/docs/en/00_Getting_Started/02_Composer.md index 70521654cb2..d7665dd55b7 100644 --- a/docs/en/00_Getting_Started/02_Composer.md +++ b/docs/en/00_Getting_Started/02_Composer.md @@ -20,7 +20,7 @@ Next, [install composer](https://getcomposer.org/download/). For our documentati You can then run Composer commands by calling `composer`. For example: -``` +```shell composer help ``` @@ -31,7 +31,7 @@ It is also possible to keep `composer.phar` out of your path, for example, to pu If you already have composer installed you can update it by running: -``` +```shell sudo composer self-update ``` @@ -43,7 +43,7 @@ For those that use WAMP as a development environment, [detailed information is a Composer can create a new site for you, using the installer as a template (by default composer will download the latest stable version): -``` +```shell composer create-project silverstripe/installer ./my/website/folder ``` @@ -53,10 +53,12 @@ Now visit the site in your web browser, and the installation process will be com You can also specify a version to download that version explicitly, i.e. this will download the older `3.0.3` release: -``` +```shell composer create-project silverstripe/installer ./my/website/folder 3.0.3 ``` + +When `create-project` is used with a release version like above, it will try to get the code from archives instead of creating git repositories. If you're planning to contribute to SilverStripe, see [Using development versions](#using-development-versions). @@ -65,26 +67,32 @@ see [Using development versions](#using-development-versions). Composer isn't only used to download SilverStripe CMS, it can also be used to manage all SilverStripe modules. Installing a module can be done with the following command: -``` +```shell composer require "silverstripe/forum:*" ``` + +This will install the forum module in the latest compatible version. By default, Composer updates other existing modules (like `framework` and `cms`), and installs "dev" dependencies like PHPUnit. In case you don't need those dependencies, use the following command instead: -``` +```shell composer require --no-update "silverstripe/forum:*" composer update --no-dev ``` + +The `require` command has two parts. First is `silverstripe/forum`. This is the name of the package. You can find other packages with the following command: -``` +```shell composer search silverstripe ``` +This will return a list of package names of the forum `vendor/package`. If you prefer, you can search for packages on [packagist.org](https://packagist.org/search/?q=silverstripe). + The second part after the colon, `*`, is a version string. `*` is a good default: it will give you the latest version that works with the other modules you have installed. Alternatively, you can specificy a specific version, or a constraint such as `>=3.0`. For more information, read the [Composer documentation](http://getcomposer.org/doc/01-basic-usage.md#the-require-key). [warning] @@ -97,11 +105,13 @@ Except for the control code of the Voyager space probe, every piece of code in t To get the latest updates of the modules in your project, run this command: -``` +```shell composer update --no-dev ``` +Updates to the required modules will be installed, and the `composer.lock` file will get updated with the specific commits of each of those. + ## Deploying projects with Composer When deploying projects with composer, you could just push the code and run `composer update`. However, this is risky. In particular, if you were referencing development dependencies and a change was made between your testing and your depoyment to production, you would end up deploying untested code. Not cool! @@ -123,7 +133,7 @@ Since SilverStripe modules are installed into their own folder, you have to mana Here is the default SilverStripe [.gitignore](http://git-scm.com/docs/gitignore) with the forum module ignored -``` +```.gitignore assets/* _ss_environment.php tools/phing-metadata @@ -139,6 +149,8 @@ Here is the default SilverStripe [.gitignore](http://git-scm.com/docs/gitignore) ``` +In large projects it can get difficult to manage your [.gitignore](http://git-scm.com/docs/gitignore) and ensure it contains all composer managed modules and themes. + You can automate this with the [SSAutoGitIgnore](https://github.com/guru-digital/SSAutoGitIgnore/) package. This package will maintain your [.gitignore](http://git-scm.com/docs/gitignore) and ensure it is kept up to date with your composer managed modules without affecting custom ignores. Once installed and setup, it will automatically run every time you install, remove or update modules using composer. @@ -146,23 +158,28 @@ This package will maintain your [.gitignore](http://git-scm.com/docs/gitignore) Include the package in your project by running this command -``` +```shell composer require gdmedia/ss-auto-git-ignore --dev ``` -``` +Edit your `composer.json` and insert + +```json "scripts": { "post-update-cmd": "GDM\\SSAutoGitIgnore\\UpdateScript::Go" } ``` + +This will instruct composer to run SSAutoGitIgnore after every update. SSAutoGitIgnore will then ensure composer managed models and themes are correctly added to your [.gitignore](http://git-scm.com/docs/gitignore). + For more information about SSAutoGitIgnore, see the [SSAutoGitIgnore home page](https://github.com/guru-digital/SSAutoGitIgnore/). For more information about post-updated-cmd and scripts, read the ["Scripts" chapter of the Composer documentation](https://getcomposer.org/doc/articles/scripts.md). -Full example of composer.json with the SSAutoGitIgnore installed and enabled +Full example of `composer.json` with the SSAutoGitIgnore installed and enabled -``` +```json { "name": "silverstripe/installer", "description": "The SilverStripe Framework Installer", @@ -185,6 +202,8 @@ Full example of composer.json with the SSAutoGitIgnore installed and enabled ``` +# Dev Environments for Contributing Code {#contributing} + So you want to contribute to SilverStripe? Fantastic! You can do this with composer too. You have to tell composer three things in order to be able to do this: @@ -195,10 +214,11 @@ You have to tell composer three things in order to be able to do this: The first two steps are done as part of the initial create project using additional arguments. -``` +```shell composer create-project --keep-vcs --dev silverstripe/installer ./my/website/folder 3.0.x-dev - ``` + +The process will take a bit longer, since all modules are checked out as full git repositories which you can work on. The command checks out from the 3.0 release line. To check out from master instead, replace `3.0.x-dev` with `dev-master` (more info on [composer version naming](http://getcomposer.org/doc/02-libraries.md#specifying-the-version)). The `--keep-vcs` flag will make sure you have access to the git history of the installer and the requirements @@ -224,7 +244,7 @@ create forks and send pull requests. To remove dependencies, or if you prefer seeing all your dependencies in a text file, you can edit the `composer.json` file. It will appear in your project root, and by default, it will look something like this: -``` +```json { "name": "silverstripe/installer", "description": "The SilverStripe Framework Installer", @@ -246,11 +266,13 @@ To add modules, you should add more entries into the `"require"` section. For e Save your file, and then run the following command to refresh the installed packages: -``` +```shell composer update ``` +## Using development versions + Composer will by default download the latest stable version of silverstripe/installer. The `composer.json` file that comes with silverstripe/installer may also explicitly state it requires the stable version of cms and framework - this is to ensure that when developers are getting started, running `composer update` won't upgrade their project to an unstable version @@ -260,16 +282,20 @@ is this required if you want to contribute back to the SilverStripe project, it This is a two step process. First you get composer to start a project based on the latest unstable silverstripe/installer -``` +```shell composer create-project silverstripe/installer ./my/website/folder master-dev ``` -``` +Or for the latest development version in the 3.0.x series + +```shell composer create-project silverstripe/installer ./my/website/folder 3.0.x-dev ``` +## Working with project forks and unreleased modules + By default, Composer will install modules listed on the packagist site. There a few reasons that you might not want to do this. For example: @@ -280,10 +306,11 @@ There are many ways that you can address this, but this is one that we recommend This is how you do it: - * **Ensure that all of your fork repositories have correct composer.json files.** Set up the project forks as you would a distributed package. If you have cloned a repository that already has a composer.json file, then there's nothing you need to do, but if not, you will need to create one yourself. + * **Ensure that all of your fork repositories have correct composer.json files.** Set up the project forks as you would a distributed package. If you have cloned a repository that already has a `composer.json` file, then there's nothing you need to do, but if not, you will need to create one yourself. * **List all your fork repositories in your project's composer.json files.** You do this in a `repositories` section. Set the `type` to `vcs`, and `url` to the URL of the repository. The result will look something like this: +```json { "name": "silverstripe/installer", "description": "The SilverStripe Framework Installer", @@ -296,21 +323,26 @@ This is how you do it: ], ... } +``` * **Install the module as you would normally.** Use the regular composer function - there are no special flags to use a fork. Your fork will be used in place of the package version. +```shell composer require silverstripe/cms +``` Composer will scan all of the repositories you list, collect meta-data about the packages within them, and use them in favour of the packages listed on packagist. To switch back to using the mainline version of the package, just remove the `repositories` section from `composer.json` and run `composer update`. Now add an "upstream" remote to the original repository location so you can rebase or merge your fork as required. -``` +```shell cd cms git remote add -f upstream git://github.com/silverstripe/silverstripe-cms.git ``` +For more information, read the ["Repositories" chapter of the Composer documentation](http://getcomposer.org/doc/05-repositories.md). + ### Forks and branch names Generally, you should keep using the same pattern of branch names as the main repositories does. If your version is a fork of 3.0, then call the branch `3.0`, not `3.0-myproj` or `myproj`. Otherwise, the dependency resolution gets confused. @@ -321,7 +353,7 @@ In this case, you need to use Composer's aliasing feature to specify how you wan Open `composer.json`, and find the module's `require`. Then put `as (core version name)` on the end. -``` +```json { ... "require": { @@ -335,6 +367,8 @@ Open `composer.json`, and find the module's `require`. Then put `as (core versi ``` +What this means is that when the `myproj` branch is checked out into a project, this will satisfy any dependencies that 3.0.x-dev would meet. So, if another module has `"silverstripe/framework": ">=3.0.0"` in its dependency list, it won't get a conflict. + Both the version and the alias are specified as Composer versions, not branch names. For the relationship between branch/tag names and Composer versions, read [the relevant Composer documentation](http://getcomposer.org/doc/02-libraries.md#specifying-the-version). This is not the only way to set things up in Composer. For more information on this topic, read the ["Aliases" chapter of the Composer documentation](http://getcomposer.org/doc/articles/aliases.md). @@ -362,7 +396,7 @@ Then register the module on [packagist.org](http://packagist.org). Follow the packagist.org advice on choosing a [unique name and vendor prefix](https://packagist.org/about). Please don't use the `silverstripe/` vendor prefix, since that's reserved for modules produced by SilverStripe Ltd. In order to declare that your module is -in fact a SilverStripe module, use the "silverstripe" tag in the composer.json file, +in fact a SilverStripe module, use the "silverstripe" tag in the `composer.json` file, and set the "type" to "silverstripe-module". ### What about themes? From ef01137350de559c99f41bcac35f3d7f9b676a86 Mon Sep 17 00:00:00 2001 From: Andrew Aitken-Fincham Date: Wed, 17 Feb 2021 14:56:45 +1300 Subject: [PATCH 10/12] return env mgmt examples to docs --- docs/en/00_Getting_Started/03_Environment_Management.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/en/00_Getting_Started/03_Environment_Management.md b/docs/en/00_Getting_Started/03_Environment_Management.md index fa2dcd830b8..74e763d0dbc 100644 --- a/docs/en/00_Getting_Started/03_Environment_Management.md +++ b/docs/en/00_Getting_Started/03_Environment_Management.md @@ -109,6 +109,8 @@ This is my `_ss_environment.php` file. I have it placed in `/var`, as each of th ``` +### Example settings to enable Database SSL + In some circumstances, like connecting to a database on a remote host for example, you may wish to enable SSL encryption to ensure the protection of sensitive information and database access credentials. The code below illustrates how to do so. [notice] From 7e222743a32d69a02bfa2e10c4cdebbb19ee1e9a Mon Sep 17 00:00:00 2001 From: Andrew Aitken-Fincham Date: Mon, 22 Feb 2021 20:01:34 +1300 Subject: [PATCH 11/12] restore coding convention ss3 docs --- .../05_Coding_Conventions.md | 79 +++++++++++++++---- 1 file changed, 63 insertions(+), 16 deletions(-) diff --git a/docs/en/00_Getting_Started/05_Coding_Conventions.md b/docs/en/00_Getting_Started/05_Coding_Conventions.md index 0ee36b4494d..5447fe3c2f6 100644 --- a/docs/en/00_Getting_Started/05_Coding_Conventions.md +++ b/docs/en/00_Getting_Started/05_Coding_Conventions.md @@ -19,7 +19,7 @@ If you are unsure about a specific standard, imitate existing SilverStripe code. ### Indentation -Always use hard tabs rather then spaces for indentation, with one tab per nesting level. +Always use hard tabs rather than spaces for indentation, with one tab per nesting level. ### Maximum Line Length @@ -46,8 +46,9 @@ Class and filenames are in `UpperCamelCase` format: ```php class MyClass {} - ``` + +If a class name is comprised of more than one word, the first letter of each new words must be capitalized. Successive capitalized letters are used in acronyms, e.g. a class `XMLImporter` is used while `XmlImporter` is not. @@ -57,16 +58,18 @@ Static methods should be in `lowercase_with_underscores()` format: ```php public static function my_static_method() {} - ``` + +Action handlers on controllers should be in `completelylowercase()` format. This is because they go into the controller URL in the same format (eg, `home/successfullyinstalled`). Method names are allowed to contain underscores here, in order to allow URL parts with dashes (`mypage\my-action` gets translated to `my_action()` automatically). ```php public function mycontrolleraction() {} - ``` + +Object methods that will be callable from templates should be in `$this->UpperCamelCase()` format. Alternatively, `$this->getUpperCamelCase()` will work the same way in templates - you can access both coding styles as `$UpperCamelCase`. @@ -74,23 +77,26 @@ Other instance methods should be in `$this->lowerCamelCase()` format: ```php public function myInstanceMethod() {} - ``` +Methods inside classes must always declare their visibility by using one of the private, protected, or public modifiers. + ### Variables -Static variables should be `self::$lowercase_with_underscores` +Static variables should be `self::$lowercase_with_underscores`: ```php self::$my_static_variable = 'foo'; - ``` +Member variables should be `$this->lowerCamelCase`: + ```php $this->myMemberVariable = 'foo'; - ``` +Member variables always declare their visibility by using one of the private, protected, or public modifiers. + ### Constants All letters used in a constant name must be capitalized, @@ -102,6 +108,8 @@ while all words in a constant name must be separated by underscore characters. define('INTEREST_RATE', 0.19); ``` + +Constants must be defined as class members with the `const` modifier. Defining constants in the global scope with the `define` function is permitted but strongly discouraged. ### File Naming and Directory Structure @@ -120,9 +128,10 @@ Example: `mysite/code/MyClass.php` class MyClass_Controller {} class MyClass_OtherRelatedClass {} - ``` +To help with namespacing common class names (like Database) it is recommended to use a prefix convention `SS_ClassName` but the filename will remain `ClassName.php`. + See [directory structure](directory_structure) for more information. ## Coding Style @@ -152,6 +161,8 @@ When a string is literal (contains no variable substitutions), the apostrophe or ``` +#### String Literals Containing Apostrophes + When a literal string itself contains apostrophes, it is permitted to demarcate the string with quotation marks or "double quotes". ```php @@ -159,6 +170,8 @@ When a literal string itself contains apostrophes, it is permitted to demarcate ``` +This syntax is preferred over escaping apostrophes as it is much easier to read. + #### String Substitution Variable substitution is permitted using either of these forms: @@ -169,10 +182,7 @@ Variable substitution is permitted using either of these forms: ``` -```php - $greeting = "Hello ${name}, welcome back!"; - -``` +#### String Concatenation Strings must be concatenated using the "." operator. A space must always be added before and after the "." operator to improve readability: @@ -180,6 +190,8 @@ Strings must be concatenated using the "." operator. A space must always be adde $copyright = 'SilverStripe Ltd (' . $year . ')'; ``` + +When concatenating strings with the "." operator, it is encouraged to break the statement into multiple lines to improve readability. In these cases, each successive line should be padded with white space such that the "."; operator is aligned under the "=" operator: ```php @@ -189,6 +201,8 @@ In these cases, each successive line should be padded with white space such that ``` +### Arrays + #### Numerically Indexed Arrays Negative numbers are not permitted as indices. @@ -200,6 +214,8 @@ When declaring indexed arrays with the Array function, a trailing space must be $sampleArray = array(1, 2, 3, 'Zend', 'Studio'); ``` + +It is permitted to declare multi-line indexed arrays using the "array" construct. In this case, each successive line must be padded with spaces such that beginning of each line is aligned: ```php @@ -208,6 +224,8 @@ In this case, each successive line must be padded with spaces such that beginnin 56.44, $d, 500); ``` + +Alternately, the initial array item may begin on the following line. If so, it should be padded at one indentation level greater than the line containing the array declaration, and all successive lines should have the same indentation; the closing paren should be on a line by itself at the same indentation level as the line containing the array declaration: @@ -220,6 +238,8 @@ the closing paren should be on a line by itself at the same indentation level as ); ``` + +When using this latter declaration, we encourage using a trailing comma for the last item in the array; this minimizes the impact of adding new items on successive lines, and helps to ensure no parse errors occur due to a missing comma. #### Associative Arrays @@ -232,6 +252,8 @@ In this case, each successive line must be padded with white space such that bot 'secondKey' => 'secondValue'); ``` + +Alternately, the initial array item may begin on the following line. If so, it should be padded at one indentation level greater than the line containing the array declaration, and all successive lines should have the same indentation; the closing paren should be on a line by itself at the same indentation level as the line containing the array declaration. @@ -245,8 +267,10 @@ For readability, the various "=>" assignment operators should be padded such tha ``` +### Function and Method Declaration + No method or function invocation is allowed to have spaces directly -before or after the opening parathesis, as well as no space before the closing parenthesis. +before or after the opening parenthesis, as well as no space before the closing parenthesis. ```php public function foo($arg1, $arg2) {} // good @@ -254,6 +278,8 @@ before or after the opening parathesis, as well as no space before the closing p ``` +Keep the opening brace on the same line as the statement. + ```php // good public function foo() { @@ -267,6 +293,8 @@ before or after the opening parathesis, as well as no space before the closing p } ``` + +In cases where the argument list exceeds the maximum line length, you may introduce line breaks. Additional arguments to the function or method must be indented one additional level beyond the function or method declaration. A line break should then occur before the closing argument paren, which should then be placed on the same line as the opening brace of the function @@ -280,6 +308,8 @@ or method with one space separating the two, and at the same indentation level a } ``` + +Function and method arguments should be separated by a single trailing space after the comma delimiter, apart from the last argument. ### Control Structures @@ -298,6 +328,8 @@ Any content within the braces must be indented using a tab. } ``` + +If the conditional statement causes the line length to exceed the maximum line length and has several clauses, you may break the conditional into multiple lines. In such a case, break the line prior to a logic operator, and pad the line such that it aligns under the first character of the conditional clause. The closing paren in the conditional will then be placed on a line with the opening brace, @@ -312,6 +344,8 @@ with one space separating the two, at an indentation level equivalent to the ope } ``` + +The intention of this latter declaration format is to prevent issues when adding or removing clauses from the conditional during later revisions. For `if` statements that include `elseif` or `else`, the formatting conventions are similar to the `if` construct. The following examples demonstrate proper formatting for `if` statements with `else` and/or `elseif` constructs: @@ -327,6 +361,8 @@ The following examples demonstrate proper formatting for `if` statements with `e ``` +Statements with `if` can be written without braces on a single line as the block, as long as no `else` statement exists. + ```php // good if($a == $b) doThis(); @@ -337,6 +373,8 @@ The following examples demonstrate proper formatting for `if` statements with `e ``` +#### switch + All content within the "switch" statement must be indented using tabs. Content under each "case" statement must be indented using an additional tab. @@ -352,6 +390,8 @@ Content under each "case" statement must be indented using an additional tab. ``` +The construct `default` should never be omitted from a switch statement. + #### for/foreach/while Loop constructs follow the same principles as "Control Structures: if/else/elseif". @@ -371,6 +411,8 @@ Try to avoid using PHP's ability to mix HTML into the code. ``` +Better: Keep HTML in template files: + ```php // PHP code public function getTitle() { @@ -382,6 +424,8 @@ Try to avoid using PHP's ability to mix HTML into the code. ``` +## Comments + Use [phpdoc](http://phpdoc.org/) syntax before each definition (see [tutorial](http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_phpDocumentor.quickstart.pkg.html) and [tag overview](http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_tags.pkg.html)). @@ -445,15 +489,18 @@ with the column or table name escaped with double quotes as below. MyClass::get()->where(array("\"Score\" > ?" => 50)); ``` + +It is preferable to use parameterised queries whenever necessary to provide conditions to a SQL query, where values placeholders are each replaced with a single unquoted question mark. -If it's absolutely necessary to use literal values in a query make sure that values +If it's absolutely necessary to use literal values in a query, make sure that values are single quoted. ```php MyClass::get()->where("\"Title\" = 'my title'"); - ``` +Use [ANSI SQL](http://en.wikipedia.org/wiki/SQL#Standardization) format where possible. + ### Secure Development See [security](/developer_guides/security) for conventions related to handing security permissions. From b00cad13d9b2a5ed00163318614bd21156a59c78 Mon Sep 17 00:00:00 2001 From: Andrew Aitken-Fincham Date: Mon, 22 Feb 2021 20:08:02 +1300 Subject: [PATCH 12/12] restore building a basic site ss3 docs --- .../01_Tutorials/01_Building_A_Basic_Site.md | 45 ++++++++++++++----- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/docs/en/01_Tutorials/01_Building_A_Basic_Site.md b/docs/en/01_Tutorials/01_Building_A_Basic_Site.md index fa6c5510d73..b521b9755e8 100644 --- a/docs/en/01_Tutorials/01_Building_A_Basic_Site.md +++ b/docs/en/01_Tutorials/01_Building_A_Basic_Site.md @@ -37,16 +37,15 @@ If you installed on windows with WAMP, it will likely be at *c:\wamp\www*. On Ma Let's have a look at the folder structure. - | Directory | | Description | - | --------- | | ----------- | - | assets/ | | Contains images and other files uploaded via the SilverStripe CMS. You can also place your own content inside it, and link to it from within the content area of the CMS. | - | cms/ | | Contains all the files that form the CMS area of your site. Its structure is similar to the mysite/ directory, so if you find something interesting, it should be easy enough to look inside and see how it was built. | - | framework/ | | The framework that builds both your own site and the CMS that powers it. You’ll be utilizing files in this directory often, both directly and indirectly. | - | mysite/ | | Contains all your site's code (mainly PHP). | - | themes/ | | Combines all images, stylesheets, javascript and templates powering your website into a reusable "theme". | -``` - -``` + | Directory | Description | + | --------- | ----------- | + | assets/ | Contains images and other files uploaded via the SilverStripe CMS. You can also place your own content inside it, and link to it from within the content area of the CMS. | + | cms/ | Contains all the files that form the CMS area of your site. Its structure is similar to the mysite/ directory, so if you find something interesting, it should be easy enough to look inside and see how it was built. | + | framework/ | The framework that builds both your own site and the CMS that powers it. You’ll be utilizing files in this directory often, both directly and indirectly. | + | mysite/ | Contains all your site's code (mainly PHP). | + | themes/ | Combines all images, stylesheets, javascript and templates powering your website into a reusable "theme". | + +When designing your site you should only need to modify the *mysite*, *themes* and *assets* folders. The rest of the folders contain files and data that are not specific to any site. ## Using the CMS @@ -118,6 +117,8 @@ Open *themes/simple/templates/Page.ss*. It uses standard HTML apart from these e <% base_tag %> ``` + +The base_tag variable is replaced with the HTML [base element](http://www.w3.org/TR/html401/struct/links.html#h-12.4). This ensures the browser knows where to locate your site's images and css files. ```ss @@ -126,21 +127,30 @@ ensures the browser knows where to locate your site's images and css files. ``` +These two variables are found within the html `` tag, and are replaced by the "Page Name" and "Settings -> Site Title" fields in the CMS. + ```ss $MetaTags ``` + +The MetaTags variable will add meta tags, which are used by search engines. You can define your meta tags in the tab fields at the bottom of the content editor in the CMS. + ```ss $Layout ``` +The Layout variable is replaced with the contents of a template file with the same name as the page type we are using. + Open *themes/simple/templates/Layout/Page.ss*. You will see more HTML and more SilverStripe template replacement tags and variables. ```ss $Content ``` + +The Content variable is replaced with the content of the page currently being viewed. This allows you to make all changes to your site's content in the CMS. These template markers are processed by SilverStripe into HTML before being sent to your @@ -169,6 +179,8 @@ The Menu for our site is created using a **loop**. Loops allow us to iterate ove <% loop $Menu(1) %> ``` + +returns a set of first level menu items. We can then use the template variable *$MenuTitle* to show the title of the page we are linking to, *$Link* for the URL of the page, and `$isSection` and `$isCurrent` to help style our menu with CSS (explained in more detail shortly). > *$Title* refers to **Page Name** in the CMS, whereas *$MenuTitle* refers to (the often shorter) **Navigation label** @@ -184,6 +196,8 @@ The Menu for our site is created using a **loop**. Loops allow us to iterate ove </ul> ``` + +Here we've created an unordered list called *Menu1*, which *themes/simple/css/layout.css* will style into the menu. Then, using a loop over the page control *Menu(1)*, we add a link to the list for each menu item. This creates the navigation at the top of the page: @@ -205,11 +219,15 @@ For example, if you were here: "Home > Company > Staff > Bob Smith", you may wan ``` +You will then be able to target a section in css (*simple/css/layout.css*), e.g.: + ```css .section { background:#ccc; } ``` +## A second level of navigation + The top navigation system is currently quite restrictive. There is no way to nest pages, so we have a completely flat site. Adding a second level in SilverStripe is easy. First (if you haven't already done so), let's add some pages. @@ -240,6 +258,8 @@ Adding a second level menu is very similar to adding the first level menu. Open </ul> ``` + +This should look very familiar. It is the same idea as our first menu, except the loop block now uses *Menu(2)* instead of *Menu(1)*. As we can see here, the *Menu* control takes a single argument - the level of the menu we want to get. Our css file will style this linked list into the second level menu, using our usual `is` technique to highlight the current page. @@ -265,6 +285,8 @@ like this: <% end_if %> ``` + +The `if` block only includes the code inside it if the condition is true. In this case, it checks for the existence of *Menu(2)*. If it exists then the code inside will be processed and the menu will be shown. Otherwise the code will not be processed and the menu will not be shown. @@ -280,6 +302,8 @@ Open up */themes/simple/templates/Includes/BreadCrumbs.ss* template and look at <% end_if %> ``` + +Breadcrumbs are only useful on pages that aren't in the top level. We can ensure that we only show them if we aren't in the top level with another if statement. The *Level* page control allows you to get data from the page's parents, e.g. if you used *Level(1)*, you could use: @@ -289,6 +313,7 @@ The *Level* page control allows you to get data from the page's parents, e.g. if ``` +to get the top level page title. In this case, we merely use it to check the existence of a second level page: if one exists then we include breadcrumbs. Both the top menu, and the sidebar menu should be updating and highlighting as you move from page to page. They will also mirror changes done in the SilverStripe CMS, such as renaming pages or moving them around. ![](../_images/tutorial1_menu-two-level.jpg)