Charcoal Boilerplate -> Locomotive front-end boilerplate
- Removing Charcoal files and configuration to be backend agnostic (therefore moving the assets) - Using HTML5 Boilerplate .htaccess to which framework specific rules can be added later on - Updating README with more information and documentation on the boilerplate
This commit is contained in:
1029
www/.htaccess
1029
www/.htaccess
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Default front-end section controller
|
||||
* Simply delegates initiation to the Boilerplate Module.
|
||||
*/
|
||||
|
||||
// Project configuration and Charcoal instanciation
|
||||
include 'config/config.php';
|
||||
|
||||
// Charcoal init
|
||||
Charcoal::init();
|
||||
|
||||
// Project init (front-page controller)
|
||||
$opts = [];
|
||||
Boilerplate_Module::init($opts);
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
Order Deny,Allow
|
||||
Deny from all
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
{
|
||||
"project_name": "Boilerplate",
|
||||
"databases": {
|
||||
"local": {
|
||||
"database": "gdfg",
|
||||
"username": "root",
|
||||
"password": ""
|
||||
},
|
||||
"lab": {
|
||||
"database": "",
|
||||
"username": "",
|
||||
"password": ""
|
||||
},
|
||||
"live": {
|
||||
"database": "",
|
||||
"username": "",
|
||||
"password": ""
|
||||
}
|
||||
},
|
||||
"default_database": "local",
|
||||
"languages": {
|
||||
"fr": {
|
||||
"active": true
|
||||
},
|
||||
"en": {
|
||||
"active": true
|
||||
}
|
||||
},
|
||||
"default_language": "fr",
|
||||
"modules": {
|
||||
"admin": [],
|
||||
"cms": [],
|
||||
"newsletter": [],
|
||||
"boilerplate": []
|
||||
},
|
||||
"objects": [],
|
||||
"apis": [],
|
||||
"default_template_controller":"Boilerplate_Template_Controller",
|
||||
"url_options":{
|
||||
"use_rewrite":true,
|
||||
"lowercase":true,
|
||||
"use_dash":true,
|
||||
"remove_punctuation":true
|
||||
},
|
||||
"debug":{
|
||||
"active":false
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"debug":{
|
||||
"active":true
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* config.php
|
||||
*/
|
||||
|
||||
// Error reporting
|
||||
error_reporting(E_ALL & ~E_STRICT);
|
||||
ini_set('display_errors', true);
|
||||
|
||||
|
||||
|
||||
// Main Charcoal include. This is where the Charcoal autoloader is defined.
|
||||
include __DIR__.'/../charcoal/charcoal.php';
|
||||
|
||||
// JSON Configuration
|
||||
Charcoal::add_config(__DIR__.'/config.json');
|
||||
$application_env = Charcoal::application_env();
|
||||
if(file_exists(__DIR__ . '/config.'.$application_env.'.json')) {
|
||||
Charcoal::add_config(__DIR__ . '/config.'.$application_env.'.json');
|
||||
}
|
||||
|
||||
// Environment defaults
|
||||
date_default_timezone_set('America/Montreal');
|
||||
|
||||
// Configuration overwrite
|
||||
Charcoal::$config['ROOT'] = realpath(__DIR__).'/../';
|
||||
if(isset($_SERVER['HTTP_HOST'])) {
|
||||
Charcoal::$config['URL'] = 'http://'.$_SERVER['HTTP_HOST'].'/';
|
||||
}
|
||||
else {
|
||||
Charcoal::$config['URL'] = 'http://localhost/';
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<!--[if lte IE 9]> <html lang="fr" class="ie9"> <![endif]-->
|
||||
<!--[if gt IE 9]><!--> <html lang="fr"> <!--<![endif]-->
|
||||
<head>
|
||||
<base href="/">
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="description" content="">
|
||||
@@ -9,16 +10,16 @@
|
||||
<meta name="theme-color" content="#f2f2f2">
|
||||
<title>Boilerplate</title>
|
||||
|
||||
<link rel="apple-touch-icon" href="modules/boilerplate/assets/images/apple-touch-icon.png">
|
||||
<link rel="icon" href="modules/boilerplate/assets/images/favicon.png">
|
||||
<link rel="apple-touch-icon" href="assets/images/apple-touch-icon.png">
|
||||
<link rel="icon" href="assets/images/favicon.png">
|
||||
|
||||
<link rel="stylesheet" href="modules/boilerplate/assets/styles/dist/main.css">
|
||||
<link rel="stylesheet" href="assets/styles/dist/main.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<script>window.jQuery || document.write('<script src="modules/boilerplate/assets/scripts/dist/jquery-1.11.3.min.js"><\/script>')</script>
|
||||
<script src="modules/boilerplate/assets/scripts/dist/vendors.js"></script>
|
||||
<script src="modules/boilerplate/assets/scripts/dist/app.js"></script>
|
||||
<script>window.jQuery || document.write('<script src="assets/scripts/dist/jquery-1.11.3.min.js"><\/script>')</script>
|
||||
<script src="assets/scripts/dist/vendors.js"></script>
|
||||
<script src="assets/scripts/dist/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Default front-end section controller
|
||||
* Simply delegates initiation to the Boilerplate Module.
|
||||
*/
|
||||
|
||||
// Project configuration and Charcoal instanciation
|
||||
include 'config/config.php';
|
||||
|
||||
// Charcoal init
|
||||
Charcoal::init();
|
||||
|
||||
// Project init (front-page controller)
|
||||
$opts = [
|
||||
'default_section' => Boilerplate_Config::get_latest()->default_section
|
||||
];
|
||||
Boilerplate_Module::init($opts);
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Boilerplate Action - Contact
|
||||
*
|
||||
* This action handles the "contact" form from the contact template
|
||||
*
|
||||
* It validates a CSRF token and create a CMS_Contact object from the POST data.
|
||||
*
|
||||
* ## Expected POST values:
|
||||
* - csrf-token, string - A CSRF token (Charcoal::token() with ident "boilerplate.contact")
|
||||
* - lastname
|
||||
* - firstname
|
||||
* - phone
|
||||
* - email
|
||||
* - subject
|
||||
* - message
|
||||
* - lang
|
||||
*
|
||||
* ## Optional POST values
|
||||
* - referer, string - The URL to go back to
|
||||
*
|
||||
* ## CMS_Contact
|
||||
* Contacts can be seen in the charcoal backend at url:
|
||||
* [/admin/object-list-dashboard?obj_type=CMS_Contact]
|
||||
*
|
||||
* ## CMS_Contact_Category
|
||||
* This action is bound to the CMS_Contact_Category object with id=1. This category:
|
||||
* - Send confirmation email automatically
|
||||
* - With email template boilerplate.contact-confirmation
|
||||
* - May have CC and BCC to administratotors
|
||||
*
|
||||
* This object can be seen int he charcoal backend at url:
|
||||
* [/admin/object-edit-dashboard?obj_type=CMS_Contact_Category&obj_id=1]
|
||||
*
|
||||
* ## TODOs
|
||||
* - Support ajax request / json response
|
||||
*
|
||||
* @category Boilerplate
|
||||
* @package Boilerplate.Action
|
||||
* @subpackage Actions
|
||||
*
|
||||
* @author Mathieu Ducharme <mat@locomotive.ca>
|
||||
* @copyright 2014 Locomotive
|
||||
* @version 2012-08-01
|
||||
* @link http://locomotive.ca
|
||||
* @since Version 2014-07-01
|
||||
*/
|
||||
|
||||
|
||||
// Get referer
|
||||
$referer = '';
|
||||
if(isset($_POST['referer'])) {
|
||||
$referer = filter_input(INPUT_POST, 'referer', FILTER_SANITIZE_STRING);
|
||||
}
|
||||
else if(isset($_SERVER['HTTP_REFERER'])) {
|
||||
$referer = $_SERVER['HTTP_REFERER'];
|
||||
}
|
||||
else {
|
||||
// None set: Use contact form
|
||||
$referer = Charcoal::obj('CMS_Section')->load_from('ident', 'contact')->url();
|
||||
}
|
||||
|
||||
function _header_error($msg='')
|
||||
{
|
||||
global $referer;
|
||||
|
||||
if(headers_sent()) {
|
||||
// Error, cant send headers. Should never happened
|
||||
die();
|
||||
}
|
||||
header('Location: '.$referer.'?contact-success=0&msg='.urlencode($msg));
|
||||
die();
|
||||
|
||||
}
|
||||
|
||||
function _header_success($msg='')
|
||||
{
|
||||
global $referer;
|
||||
|
||||
if(headers_sent()) {
|
||||
// Error, cant send headers. Should never happened
|
||||
die();
|
||||
}
|
||||
header('Location: '.$referer.'?contact-success=1&msg='.urlencode($msg));
|
||||
die();
|
||||
die();
|
||||
}
|
||||
|
||||
// Validate CSRF token
|
||||
$csrf_token = filter_input(INPUT_POST, 'csrf-token', FILTER_SANITIZE_STRING);
|
||||
if(!Charcoal::token_validate($csrf_token, 'boilerplate.contact')) {
|
||||
Charcoal::feedback('error', 'send_contact', _t("Your session has expired. Please try again"));
|
||||
_headers_error();
|
||||
}
|
||||
|
||||
// Create and save the Contact object
|
||||
$contact = Charcoal::obj('CMS_Contact');
|
||||
$contact->from_flat_data($_POST);
|
||||
// Hardcoded to the general contact category
|
||||
$contact->category = 1;
|
||||
|
||||
$validations = $contact->validate();
|
||||
if(!$validations){
|
||||
//pre($contact);
|
||||
// Saving the contact sends the email confirmatino automatically, according to the category
|
||||
$contact_id = $contact->save();
|
||||
if($contact_id) {
|
||||
_header_success()_t("Successful.");
|
||||
}
|
||||
else {
|
||||
_headers_error(_t("Error saving contact"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$msg = '';
|
||||
foreach($validations as $property=>$messages){
|
||||
foreach($messages as $m){
|
||||
$msg .= $m.'<br />';
|
||||
}
|
||||
}
|
||||
|
||||
_headers_error($msg);
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* @category Boilerplate
|
||||
* @package Boilerplate.Objects
|
||||
* @subpackage Objects
|
||||
*
|
||||
* @author Mathieu Ducharme <mat@locomotive.ca>
|
||||
* @copyright 2014 Locomotive
|
||||
* @version 2014-10-01
|
||||
* @link http://locomotive.ca
|
||||
* @since Version 2014-10-01
|
||||
*/
|
||||
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Contact form section
|
||||
*
|
||||
* @category Boilerplate
|
||||
* @package Boilerplate.Templates
|
||||
* @subpackage Templates
|
||||
*
|
||||
* @author Mathieu Ducharme <mat@locomotive.ca>
|
||||
* @copyright 2014 Locomotive
|
||||
* @version 2014-10-01
|
||||
* @link http://locomotive.ca
|
||||
* @since Version 2014-10-01
|
||||
*/
|
||||
|
||||
?>
|
||||
{{>boilerplate.inc.header}}
|
||||
|
||||
<section class="contact {{section.ident}}">
|
||||
|
||||
<h1>{{section.p.title}}</h1>
|
||||
<h2>{{section.p.subtitle}}</h2>
|
||||
|
||||
<div class="section-summary">
|
||||
{{section.p.summary.display}}
|
||||
</div>
|
||||
|
||||
<div class="section-description">
|
||||
{{section.p.content.display}}
|
||||
</div>
|
||||
|
||||
<form method="post">
|
||||
|
||||
</form>
|
||||
|
||||
</section>
|
||||
|
||||
{{>boilerplate.inc.footer}}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* @category Boilerplate
|
||||
* @package Boilerplate.Templates
|
||||
* @subpackage Templates
|
||||
*
|
||||
* @author Mathieu Ducharme <mat@locomotive.ca>
|
||||
* @copyright 2014 Locomotive
|
||||
* @version 2014-10-01
|
||||
* @link http://locomotive.ca
|
||||
* @since Version 2014-10-01
|
||||
*/
|
||||
|
||||
?>
|
||||
{{>boilerplate.inc.header}}
|
||||
|
||||
<section class="content {{section.ident}}">
|
||||
|
||||
<h1>{{section.p.title}}</h1>
|
||||
<h2>{{section.p.subtitle}}</h2>
|
||||
|
||||
<div class="section-summary">
|
||||
{{section.p.summary.display}}
|
||||
</div>
|
||||
|
||||
<div class="section-description">
|
||||
{{section.p.content.display}}
|
||||
</div>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
{{>boilerplate.inc.footer}}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* @category Boilerplate
|
||||
* @package Boilerplate.Templates
|
||||
* @subpackage Templates
|
||||
*
|
||||
* @author Mathieu Ducharme <mat@locomotive.ca>
|
||||
* @copyright 2014 Locomotive
|
||||
* @version 2014-10-01
|
||||
* @link http://locomotive.ca
|
||||
* @since Version 2014-10-01
|
||||
*/
|
||||
|
||||
|
||||
?>
|
||||
{{>boilerplate.inc.header}}
|
||||
|
||||
<section class="home {{section.ident}}">
|
||||
|
||||
<h1>{{section.p.title}}</h1>
|
||||
|
||||
</section>
|
||||
|
||||
{{>boilerplate.inc.footer}}
|
||||
@@ -1,6 +0,0 @@
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<script>window.jQuery || document.write('<script src="modules/{{module}}/assets/scripts/dist/jquery-1.11.3.min.js"><\/script>')</script>
|
||||
<script src="modules/{{module}}/assets/scripts/dist/vendors.js"></script>
|
||||
<script src="modules/{{module}}/assets/scripts/dist/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,37 +0,0 @@
|
||||
<!doctype html>
|
||||
<!--[if lte IE 9]> <html lang="{{lang}}" class="ie9"> <![endif]-->
|
||||
<!--[if gt IE 9]><!--> <html lang="{{lang}}"> <!--<![endif]-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<base href="{{URL}}">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#f2f2f2">
|
||||
<title>{{meta_title}}</title>
|
||||
|
||||
<link rel="apple-touch-icon" href="{{#assets.images}}apple-touch-icon.png{{/assets.images}}">
|
||||
<link rel="icon" href="{{#assets.images}}favicon.png{{/assets.images}}">
|
||||
|
||||
<link rel="stylesheet" href="{{#assets.styles}}dist/main.css{{/assets.styles}}">
|
||||
|
||||
<meta name="description" content="{{meta_description}}">
|
||||
{{opengraph_tags}}
|
||||
|
||||
{{! Only include analytics if it is set in the configuration}}
|
||||
{{#cfg.google_analytics}}
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', '{{cfg.google_analytics}}', 'auto');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
{{/cfg.google_analytics}}
|
||||
|
||||
{{!A final chance to have custom headers tags (like styles or scripts) in the controllers}}
|
||||
{{extra_header_content}}
|
||||
|
||||
</head>
|
||||
<body>
|
||||
@@ -1,181 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @category Boilerplate
|
||||
* @package Boilerplate.Objects
|
||||
* @subpackage Objects
|
||||
*
|
||||
* @author Mathieu Ducharme <mat@locomotive.ca>
|
||||
* @copyright 2014 Locomotive
|
||||
* @version 2014-10-01
|
||||
* @link http://locomotive.ca
|
||||
* @since Version 2014-10-01
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Boilerplate configuration
|
||||
*
|
||||
* The latest (current) object can always be used by calling:
|
||||
* ```php
|
||||
* $cfg = \Boilerplate\Config::get_latest();
|
||||
* ```
|
||||
*
|
||||
* @category Boilerplate
|
||||
* @package Boilerplate.Objects
|
||||
* @subpackage Objects
|
||||
*
|
||||
* @author Mathieu Ducharme <mat@locomotive.ca>
|
||||
* @copyright 2014 Locomotive
|
||||
* @version 2014-10-01
|
||||
* @link http://locomotive.ca
|
||||
* @since Version 2014-10-01
|
||||
*/
|
||||
class Boilerplate_Config extends \Charcoal_Object
|
||||
{
|
||||
/**
|
||||
* Google Analytics code
|
||||
* @var string $google_analytics
|
||||
* @see Property_String
|
||||
*/
|
||||
public $google_analytics;
|
||||
|
||||
/**
|
||||
* Default section
|
||||
* The section to load when reaching the default base URL.
|
||||
* Also, usually the section to load when clicking on the main link / logo
|
||||
* @var mixed $default_section
|
||||
* @see Property_Object
|
||||
* @see CMS_Section
|
||||
*/
|
||||
public $default_section;
|
||||
/**
|
||||
* Default lang
|
||||
* @var string $default_lang
|
||||
* @see Property_Lang
|
||||
*/
|
||||
public $default_lang;
|
||||
|
||||
/**
|
||||
* URL of the related facebook page
|
||||
* @var string $social_facebook_url
|
||||
* @see Property_Url
|
||||
*/
|
||||
public $social_facebook_url;
|
||||
/**
|
||||
* URL of the related twitter account
|
||||
* @var string $social_twitter_url
|
||||
* @see Property_Url
|
||||
*/
|
||||
public $social_twitter_url;
|
||||
/**
|
||||
* URL of the related google+ page
|
||||
* @var string $social_facebook_url
|
||||
* @see Property_Url
|
||||
*/
|
||||
public $social_google_url;
|
||||
/**
|
||||
* URL of the related instagram page
|
||||
* @var string $social_instagram_url
|
||||
* @see Property_Url
|
||||
*/
|
||||
public $social_instagram_url;
|
||||
/**
|
||||
* URL of the related flickr page
|
||||
* @var string $social_flickr_url
|
||||
* @see Property_Url
|
||||
*/
|
||||
public $social_flickr_url;
|
||||
/**
|
||||
* URL of the related youtube page
|
||||
* @var string $social_youtube_url
|
||||
* @see Property_Url
|
||||
*/
|
||||
public $social_youtube_url;
|
||||
|
||||
/**
|
||||
* Default title, if none is specified
|
||||
* - l10n: true
|
||||
* @var mixed $meta_default_title
|
||||
* @see Property_String
|
||||
*/
|
||||
public $meta_default_title;
|
||||
/**
|
||||
* Default title, if none is specified
|
||||
* - l10n: true
|
||||
* @var mixed $meta_default_prefix
|
||||
* @see Property_String
|
||||
*/
|
||||
public $meta_title_prefix;
|
||||
/**
|
||||
* Default title, if none is specified
|
||||
* - l10n: true
|
||||
* @var mixed $meta_default_suffix
|
||||
* @see Property_String
|
||||
*/
|
||||
public $meta_title_suffix;
|
||||
/**
|
||||
* Default title, if none is specified
|
||||
* - l10n: true
|
||||
* @var mixed $meta_default_description
|
||||
* @see Property_Text
|
||||
*/
|
||||
public $meta_default_description;
|
||||
/**
|
||||
* Default title, if none is specified
|
||||
* - l10n: true
|
||||
* - upload_path: "uploads/config/meta_image/"
|
||||
* @var mixed $meta_default_image
|
||||
* @see Property_Image
|
||||
*/
|
||||
public $meta_default_image;
|
||||
/**
|
||||
* Default meta-keywords, if none is specified
|
||||
* - l10n: true
|
||||
* - multiple: true
|
||||
* @var mixed $meta_default_keywords
|
||||
* @see Property_String
|
||||
*/
|
||||
public $meta_default_keywords;
|
||||
|
||||
/**
|
||||
* Static getter of the latest config
|
||||
*
|
||||
* This is the preferred way of loading the Configuration object.
|
||||
*
|
||||
* It will only be loaded 1 time from the configuration, otherwie, it will be stored
|
||||
* in a static variable.
|
||||
*
|
||||
* @return static Corim_Config
|
||||
* @todo Use APC instead of static, if available
|
||||
*/
|
||||
static public function get_latest()
|
||||
{
|
||||
static $_cached;
|
||||
|
||||
$cache_key = 'latest_boilerplate_config';
|
||||
|
||||
if($_cached instanceof self) {
|
||||
// Load from static if possible
|
||||
return $_cached;
|
||||
}
|
||||
else {
|
||||
// Load from DB otherwise
|
||||
$_cached = Charcoal::obj( __CLASS__ );
|
||||
$_cached->load_latest();
|
||||
return $_cached;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Corim_Config
|
||||
*/
|
||||
public function load_latest()
|
||||
{
|
||||
// Hardcoded to ID 1
|
||||
$this->load_key('id', 1);
|
||||
|
||||
// Chainable
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @category Boilerplate
|
||||
* @package Boilerplate.Objects
|
||||
* @subpackage Objects
|
||||
*
|
||||
* @author Mathieu Ducharme <mat@locomotive.ca>
|
||||
* @copyright 2014 Locomotive
|
||||
* @version 2014-10-01
|
||||
* @link http://locomotive.ca
|
||||
* @since Version 2014-10-01
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The Boilerplate Module class
|
||||
*
|
||||
* @category Boilerplate
|
||||
* @package Boilerplate.Objects
|
||||
* @subpackage Objects
|
||||
*
|
||||
* @author Mathieu Ducharme <mat@locomotive.ca>
|
||||
* @copyright 2014 Locomotive
|
||||
* @version 2014-10-01
|
||||
* @link http://locomotive.ca
|
||||
* @since Version 2014-10-01
|
||||
*/
|
||||
class Boilerplate_Module extends Charcoal_Module
|
||||
{
|
||||
/**
|
||||
* Module initialisation
|
||||
*
|
||||
* This function should act as both the initialization of the module and the front-page main controller.
|
||||
*
|
||||
* ## Options
|
||||
* - default_action
|
||||
* - default_section
|
||||
* - default_lang
|
||||
*
|
||||
* @param array $opts
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
static public function init($opts=null)
|
||||
{
|
||||
// Make sure a session is started at all time. For tokens, some cache, user data, etc.
|
||||
if (!session_id()) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
// Get the latest configuration
|
||||
$default_action = isset($opts['default_action']) ? $opts['default_action'] : '';
|
||||
$default_section_id = isset($opts['default_section']) ? $opts['default_section'] : 0;
|
||||
$default_lang = isset($opts['default_lang']) ? $opts['default_lang'] : 'fr';
|
||||
|
||||
// Load the action or section from the $_GET
|
||||
$action = isset($_GET['action']) ? filter_input(INPUT_GET, 'action', FILTER_SANITIZE_STRING) : $default_action;
|
||||
$section_id = isset($_GET['s']) ? filter_input(INPUT_GET, 's', FILTER_SANITIZE_STRING) : $default_section_id;
|
||||
|
||||
// Set up the language and the required CSV file
|
||||
$lang = isset($_GET['lang']) ? filter_input(INPUT_GET, 'lang', FILTER_SANITIZE_STRING) : $default_lang;
|
||||
$l = Charcoal_L10n::get();
|
||||
$l->set_lang($lang);
|
||||
$l->add_resource_csv('boilerplate', $lang);
|
||||
|
||||
if($section_id) {
|
||||
// By section
|
||||
$section_loader = new Charcoal_Object_Loader('CMS_Section');
|
||||
|
||||
$section = $section_loader->{$section_id};
|
||||
|
||||
if($section->template) {
|
||||
// What to do?
|
||||
}
|
||||
|
||||
$tpl = Charcoal_Template::get($section->template);
|
||||
|
||||
// Section is already loaded, let's tell the controller about it.
|
||||
$tpl->controller()->set_section( $section );
|
||||
echo $tpl->render();
|
||||
}
|
||||
else if($action) {
|
||||
// By action
|
||||
\Charcoal::exec($action, $_REQUEST);
|
||||
}
|
||||
else {
|
||||
// By nothing (404 page not found). This should never happen
|
||||
die('404');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,263 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @category Boilerplate
|
||||
* @package Boilerplate.Objects
|
||||
* @subpackage Objects
|
||||
*
|
||||
* @author Mathieu Ducharme <mat@locomotive.ca>
|
||||
* @copyright 2014 Locomotive
|
||||
* @version 2014-10-01
|
||||
* @link http://locomotive.ca
|
||||
* @since Version 2014-10-01
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @category Boilerplate
|
||||
* @package Boilerplate.Objects
|
||||
* @subpackage Objects
|
||||
*
|
||||
* @author Mathieu Ducharme <mat@locomotive.ca>
|
||||
* @copyright 2014 Locomotive
|
||||
* @version 2014-10-01
|
||||
* @link http://locomotive.ca
|
||||
* @since Version 2014-10-01
|
||||
*/
|
||||
class Boilerplate_Template_Controller extends Charcoal_Template_Controller
|
||||
{
|
||||
/**
|
||||
* Keep a copy of the current section
|
||||
*/
|
||||
private $_section;
|
||||
/**
|
||||
* Keep a copy of the Section Object loader
|
||||
* @var \Charcoal_Object_Loader
|
||||
*/
|
||||
private $_sections_loader;
|
||||
/**
|
||||
* Keep a copy of the Template loader
|
||||
* @var \Charcoal\Template_Loader
|
||||
*/
|
||||
private $_templates_loader;
|
||||
/**
|
||||
* Keep a copy of the Widget Loader
|
||||
* @var \Charcoal\Widget_Loader
|
||||
*/
|
||||
private $_widgets_loader;
|
||||
|
||||
/**
|
||||
* Get the current project's main module
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function module()
|
||||
{
|
||||
return 'boilerplate';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the section to something when there is
|
||||
* no "s" get parameter and we still wanna use this
|
||||
*
|
||||
* @see Cocqsac_module::init()
|
||||
* @param $section CMS_Section Object
|
||||
* @return this (chainable)
|
||||
*/
|
||||
public function set_section( $section )
|
||||
{
|
||||
$this->_section = $section;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the current
|
||||
* (Previously, this would have been `Charcoal::$vars['section']`)
|
||||
*
|
||||
* @return CMS_Section
|
||||
*/
|
||||
public function section()
|
||||
{
|
||||
if(isset($this->_section)) {
|
||||
return $this->_section;
|
||||
}
|
||||
|
||||
$section_id = isset($_GET['s']) ? filter_input(INPUT_GET, 's', FILTER_SANITIZE_STRING) : '';
|
||||
$section = \Charcoal::obj('CMS_Section');
|
||||
if($section_id) {
|
||||
$section->load($section_id);
|
||||
}
|
||||
$this->_section = $section;
|
||||
return $section;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a `CMS_Section` Object Loader
|
||||
*
|
||||
* - Use "ident" as a key, so it can be called with {{sections.ident}}
|
||||
* - Cache the result, so this almost never touches the DB.
|
||||
*
|
||||
* ## The `\Charcoal_Object_Loader` object
|
||||
* Read the documentation on `\Charcoal_Object_Loader` for more details.
|
||||
* In short, it allows to call the objects with `->texts()->ident;` // `{{sections.ident}}` to return (and load on-the-fly, if required)
|
||||
* the `CMS_Text` object with the `ident` "ident".
|
||||
*
|
||||
* @return \Charcoal\Object_Loader
|
||||
* @see CMS_Section
|
||||
*/
|
||||
public function sections()
|
||||
{
|
||||
if(!$this->_sections_loader) {
|
||||
// Load the object, if it was not.
|
||||
$this->_sections_loader = new \Charcoal_Object_Loader('CMS_Section', 'ident', 'cache');
|
||||
}
|
||||
|
||||
return $this->_sections_loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a "CMS_Text" Object Loader
|
||||
* - Use "ident" as a key, so it can be called with {{sections.ident}}
|
||||
* - Cache the result, so this almost never touches the DB.
|
||||
*
|
||||
* ## The `\Charcoal_Object_Loader` object
|
||||
* Read the documentation on `\Charcoal_Object_Loader` for more details.
|
||||
* In short, it allows to call the objects with `->sections()->ident;` to return (and load on-the-fly, if required)
|
||||
* the `CMS_Section` object with the `ident` "ident".
|
||||
*
|
||||
* @return \Charcoal\Object_Loader
|
||||
* @see CMS_Text
|
||||
*/
|
||||
public function texts()
|
||||
{
|
||||
if(!$this->_texts_loader) {
|
||||
// Load the (text loader) object, if it was not.
|
||||
$this->_texts_loader = new \Charcoal_Object_Loader('CMS_Text', 'ident', 'cache');
|
||||
}
|
||||
|
||||
return $this->_texts_loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest Config instance from DB / cache
|
||||
*
|
||||
* @return Config
|
||||
*/
|
||||
public function cfg()
|
||||
{
|
||||
return Boilerplate_Config::get_latest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base URL
|
||||
* Previously, this would have been `Charcoal::$config['URL']` (which still works)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function URL()
|
||||
{
|
||||
return \Charcoal::$config['URL'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current URL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function current_url()
|
||||
{
|
||||
return Charcoal::$config['HTTP_MODE'] . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test templating.
|
||||
*
|
||||
* Allow to hide content under dev_mode
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function dev_mode()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current language (2-character / ISO-639-1)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function lang()
|
||||
{
|
||||
return _l();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assets getters
|
||||
*
|
||||
* This method returns an array of lambda functions, which in turn takes the argument
|
||||
*
|
||||
* ## Using with mustache
|
||||
* In short, this allows to get an asset with the following mustache tag:
|
||||
* - `{{#assets.images}}test.png{{/assets.images}}
|
||||
*
|
||||
* ## Asset types
|
||||
* - images
|
||||
* - styles
|
||||
* - scripts
|
||||
* - fonts
|
||||
* - files
|
||||
* Read the documentation on \Charcoal\Asset for more details on how assets are loaded relative to the filesystem.
|
||||
*
|
||||
* @return array
|
||||
* @see \Charcoal\Asset
|
||||
*/
|
||||
public function assets($asset_mode='url')
|
||||
{
|
||||
$ret = [
|
||||
'images' => function($txt) use ($asset_mode) {
|
||||
return new \Charcoal\Asset('images', $txt, $asset_mode);
|
||||
},
|
||||
'styles' => function($txt) use ($asset_mode) {
|
||||
return new \Charcoal\Asset('styles', $txt, $asset_mode);
|
||||
},
|
||||
'scripts' => function($txt) use ($asset_mode) {
|
||||
return new \Charcoal\Asset('scripts', $txt, $asset_mode);
|
||||
},
|
||||
'fonts' => function($txt) use ($asset_mode) {
|
||||
return new \Charcoal\Asset('fonts', $txt, $asset_mode);
|
||||
},
|
||||
'files' => function($txt) use ($asset_mode) {
|
||||
return new \Charcoal\Asset('files', $txt, $asset_mode);
|
||||
}
|
||||
];
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the proper name of the template, usable for css class.
|
||||
*
|
||||
* (Replace invalid characters, such as a dot.)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function template_class()
|
||||
{
|
||||
$token = $this->section()->template;
|
||||
$search = ["boilerplate_"];
|
||||
$replace = [""];
|
||||
$token = str_replace(".", "_", $token);
|
||||
|
||||
if ( is_numeric($token) ) {
|
||||
$token = preg_replace('/\D+/', '', $token);
|
||||
}
|
||||
else {
|
||||
$token = str_replace($search, $replace,$token);
|
||||
$token = preg_replace('/[^\w-]/', '', strtolower($token));
|
||||
}
|
||||
|
||||
return $token;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @category Boilerplate
|
||||
* @package Boilerplate.Objects
|
||||
* @subpackage Controllers
|
||||
*
|
||||
* @author Mathieu Ducharme <mat@locomotive.ca>
|
||||
* @copyright 2014 Locomotive
|
||||
* @version 2014-10-01
|
||||
* @link http://locomotive.ca
|
||||
* @since Version 2014-10-01
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @category Boilerplate
|
||||
* @package Boilerplate.Objects
|
||||
* @subpackage Controllers
|
||||
*
|
||||
* @author Mathieu Ducharme <mat@locomotive.ca>
|
||||
* @copyright 2014 Locomotive
|
||||
* @version 2014-10-01
|
||||
* @link http://locomotive.ca
|
||||
* @since Version 2014-10-01
|
||||
*/
|
||||
class Template_Controller_Boilerplate_Contact extends Boilerplate_Template_Controller
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @category Boilerplate
|
||||
* @package Boilerplate.Objects
|
||||
* @subpackage Controllers
|
||||
*
|
||||
* @author Mathieu Ducharme <mat@locomotive.ca>
|
||||
* @copyright 2014 Locomotive
|
||||
* @version 2014-10-01
|
||||
* @link http://locomotive.ca
|
||||
* @since Version 2014-10-01
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @category Boilerplate
|
||||
* @package Boilerplate.Objects
|
||||
* @subpackage Controllers
|
||||
*
|
||||
* @author Mathieu Ducharme <mat@locomotive.ca>
|
||||
* @copyright 2014 Locomotive
|
||||
* @version 2014-10-01
|
||||
* @link http://locomotive.ca
|
||||
* @since Version 2014-10-01
|
||||
*/
|
||||
class Template_Controller_Boilerplate_Content extends Boilerplate_Template_Controller
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @category Boilerplate
|
||||
* @package Boilerplate.Objects
|
||||
* @subpackage Controllers
|
||||
*
|
||||
* @author Mathieu Ducharme <mat@locomotive.ca>
|
||||
* @copyright 2014 Locomotive
|
||||
* @version 2014-10-01
|
||||
* @link http://locomotive.ca
|
||||
* @since Version 2014-10-01
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @category Boilerplate
|
||||
* @package Boilerplate.Objects
|
||||
* @subpackage Controllers
|
||||
*
|
||||
* @author Mathieu Ducharme <mat@locomotive.ca>
|
||||
* @copyright 2014 Locomotive
|
||||
* @version 2014-10-01
|
||||
* @link http://locomotive.ca
|
||||
* @since Version 2014-10-01
|
||||
*/
|
||||
class Template_Controller_Boilerplate_Home extends Boilerplate_Template_Controller
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,350 +0,0 @@
|
||||
{
|
||||
"config_type":"object",
|
||||
"config_version":1,
|
||||
|
||||
"module":"boilerplate",
|
||||
|
||||
"name":{
|
||||
"en":"Configuration",
|
||||
"fr":"Configuration"
|
||||
},
|
||||
"description":{
|
||||
"en":"",
|
||||
"fr":""
|
||||
},
|
||||
"long_description":{
|
||||
"en":"",
|
||||
"fr":""
|
||||
},
|
||||
"notes":{
|
||||
"en":"",
|
||||
"fr":""
|
||||
},
|
||||
|
||||
"revision":true,
|
||||
|
||||
"properties":{
|
||||
"id":{
|
||||
"type":"id"
|
||||
},
|
||||
"google_analytics":{
|
||||
"type":"string",
|
||||
"label":{
|
||||
"fr":"ID Google Analytics",
|
||||
"en":"Google Analytics ID"
|
||||
},
|
||||
"notes":{
|
||||
"fr":"Ex: UA-XXXXXX-X",
|
||||
"en":"Ex: UA-XXXXXX-X"
|
||||
}
|
||||
},
|
||||
|
||||
"default_section":{
|
||||
"type":"object",
|
||||
"obj_type":"cms_section",
|
||||
"label":{
|
||||
"en":"Default section",
|
||||
"fr":"Section par défaut"
|
||||
},
|
||||
"description":{
|
||||
"en":"Default section is loaded when the default URL (without any section) is reached, or usually when the logo is clicked. Typically, this should be a \"Home\" section.",
|
||||
"fr":"La section par défaut est chargée lorsqu'un utilisateur atteint l'URL par défaut (sans paramètre de section). Est également, à l'habitude, la section qui est chargée lorsque le logo est cliqué. Typiquement, ce devrait être une section \"Accueil\"."
|
||||
},
|
||||
"input_type":"tree_select",
|
||||
"input_options":{
|
||||
"tree_select":{
|
||||
"tree_property":"master",
|
||||
"order_property":"position"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default_lang":{
|
||||
"type":"lang",
|
||||
"label":{
|
||||
"en":"Default language",
|
||||
"fr":"Langage par défaut"
|
||||
}
|
||||
},
|
||||
"contact_address":{
|
||||
"type":"string",
|
||||
"l10n":true
|
||||
},
|
||||
"contact_address2":{
|
||||
"type":"string",
|
||||
"l10n":true
|
||||
},
|
||||
"contact_city":{
|
||||
"type":"string",
|
||||
"l10n":true
|
||||
},
|
||||
"contact_postal_code":{
|
||||
"type":"string"
|
||||
},
|
||||
"contact_province":{
|
||||
"type":"string",
|
||||
"l10n":true
|
||||
},
|
||||
"contact_country":{
|
||||
"type":"string"
|
||||
},
|
||||
"contact_phone":{
|
||||
"type":"phone"
|
||||
},
|
||||
"contact_phone2":{
|
||||
"type":"phone"
|
||||
},
|
||||
"contact_fax":{
|
||||
"type":"phone"
|
||||
},
|
||||
"contact_email":{
|
||||
"type":"email"
|
||||
},
|
||||
"contact_lat":{
|
||||
"type":"float"
|
||||
},
|
||||
"contact_lon":{
|
||||
"type":"float"
|
||||
},
|
||||
|
||||
"social_facebook_url":{
|
||||
"type":"string"
|
||||
},
|
||||
"social_twitter_url":{
|
||||
"type":"string"
|
||||
},
|
||||
"social_google_url":{
|
||||
"type":"string"
|
||||
},
|
||||
"social_linkedin_url":{
|
||||
"type":"string"
|
||||
},
|
||||
"social_instagram_url":{
|
||||
"type":"string"
|
||||
},
|
||||
"social_flickr_url":{
|
||||
"type":"string"
|
||||
},
|
||||
"social_youtube_url":{
|
||||
"type":"string"
|
||||
},
|
||||
"meta_default_title":{
|
||||
"type":"string",
|
||||
"l10n":true
|
||||
},
|
||||
"meta_title_prefix":{
|
||||
"type":"string",
|
||||
"l10n":true
|
||||
},
|
||||
"meta_title_suffix":{
|
||||
"type":"string",
|
||||
"l10n":true
|
||||
},
|
||||
"meta_default_description":{
|
||||
"type":"text",
|
||||
"l10n":true
|
||||
},
|
||||
|
||||
"meta_default_image":{
|
||||
"type":"image",
|
||||
"upload_path":"uploads/cfg/meta_default_image/"
|
||||
},
|
||||
"meta_default_keywords":{
|
||||
"type":"string",
|
||||
"multiple":true,
|
||||
"l10n":true,
|
||||
"notes":{
|
||||
"en":"",
|
||||
"fr":"À moins d'avis professionnel disant le contraire, les mots-clés par défaut devraient être laissés vide."
|
||||
}
|
||||
},
|
||||
"signature_text":{
|
||||
"type":"string",
|
||||
"l10n":true,
|
||||
"label":{
|
||||
"en":"Signature text",
|
||||
"fr":"Texte de la signature"
|
||||
}
|
||||
},
|
||||
"signature_title":{
|
||||
"type":"string",
|
||||
"l10n":true,
|
||||
"label":{
|
||||
"en":"Signature title",
|
||||
"fr":"Titre de la signature"
|
||||
},
|
||||
"description":{
|
||||
"en":"This is mainly used for SEO purpose.",
|
||||
"fr":"Le titre est principalement utilisé à des fins de référencement / SEO."
|
||||
}
|
||||
},
|
||||
"signature_url":{
|
||||
"type":"url",
|
||||
"l10n":true,
|
||||
"label":{
|
||||
"en":"Signature URL",
|
||||
"fr":"Lien de la signature"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"data":{
|
||||
|
||||
},
|
||||
|
||||
"sources":{
|
||||
"default":{
|
||||
"table":"boilerplate_config"
|
||||
}
|
||||
},
|
||||
"default_source" : "default",
|
||||
|
||||
"lists":{
|
||||
"boilerplate_config":{
|
||||
"label":{
|
||||
"fr":"Liste des sections",
|
||||
"en":"Section list"
|
||||
},
|
||||
"description":{
|
||||
|
||||
},
|
||||
"properties":[
|
||||
|
||||
],
|
||||
"orders":{
|
||||
"position":{
|
||||
"property":"position",
|
||||
"mode":"asc"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"default_list":"boilerplate_config",
|
||||
|
||||
"forms":{
|
||||
"boilerplate_config":{
|
||||
"label":{
|
||||
"en":"Configuration",
|
||||
"fr":"Configuration"
|
||||
},
|
||||
"groups":{
|
||||
"analytics":{
|
||||
"label":{
|
||||
"en":"Analytics",
|
||||
"fr":"Outils d'analyse"
|
||||
},
|
||||
"properties":[
|
||||
"google_analytics"
|
||||
]
|
||||
},
|
||||
"content":{
|
||||
"label":{
|
||||
"en":"Default content settings",
|
||||
"fr":"Configuration de contenu par défaut"
|
||||
},
|
||||
"properties":[
|
||||
"default_section",
|
||||
"default_lang"
|
||||
]
|
||||
},
|
||||
"social":{
|
||||
"label":{
|
||||
"en":"Social Links",
|
||||
"fr":"Liens sociaux"
|
||||
},
|
||||
"properties":[
|
||||
"social_facebook_url",
|
||||
"social_twitter_url",
|
||||
"social_google_url",
|
||||
"|",
|
||||
"social_linkedin_url",
|
||||
"|",
|
||||
"social_instagram_url",
|
||||
"social_flickr_url",
|
||||
"|",
|
||||
"social_youtube_url"
|
||||
],
|
||||
"properties_options":{},
|
||||
"priority":30
|
||||
},
|
||||
"contact":{
|
||||
"label":{
|
||||
"en":"Meta-informations",
|
||||
"fr":"Informations méta"
|
||||
},
|
||||
"l10n":true,
|
||||
"l10n_options":{
|
||||
"mode":"loop_group"
|
||||
},
|
||||
"properties":[
|
||||
"contact_address",
|
||||
"contact_address2",
|
||||
"contact_city",
|
||||
"contact_postal_code",
|
||||
"contact_province",
|
||||
"contact_country",
|
||||
"|",
|
||||
"contact_phone",
|
||||
"contact_phone2",
|
||||
"contact_fax",
|
||||
"|",
|
||||
"contact_email"
|
||||
],
|
||||
"properties_options":{},
|
||||
"priority":40
|
||||
},
|
||||
"meta":{
|
||||
"label":{
|
||||
"en":"Meta-informations",
|
||||
"fr":"Informations méta"
|
||||
},
|
||||
"l10n":true,
|
||||
"l10n_options":{
|
||||
"mode":"loop_group"
|
||||
},
|
||||
"properties":[
|
||||
"meta_default_title",
|
||||
"meta_title_prefix",
|
||||
"meta_title_suffix",
|
||||
"meta_default_description",
|
||||
"meta_default_keywords",
|
||||
"meta_default_image"
|
||||
],
|
||||
"properties_options":{},
|
||||
"priority":50
|
||||
},
|
||||
"signature":{
|
||||
"label":{
|
||||
"en":"Signature",
|
||||
"fr":"Signature"
|
||||
},
|
||||
"l10n":true,
|
||||
"l10n_options":{
|
||||
"mode":"loop_group"
|
||||
},
|
||||
"properties":[
|
||||
"signature_text",
|
||||
"signature_url",
|
||||
"signature_title"
|
||||
|
||||
],
|
||||
"priority":60
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"default_form":"boilerplate_config",
|
||||
|
||||
"dashboards":{
|
||||
|
||||
},
|
||||
|
||||
"widgets": {
|
||||
|
||||
},
|
||||
|
||||
"patterns":{
|
||||
|
||||
},
|
||||
"default_pattern":"default"
|
||||
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"url_options":{
|
||||
"rewrite_pattern":{
|
||||
"fr":"fr/{{:id}}/{{title:url}}",
|
||||
"en":"en/{{:id}}/{{title:url}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user