├── .gitignore ├── .htaccess ├── LICENSE ├── README.md ├── applications ├── admin │ ├── admin.php │ ├── index.php │ └── routes.php ├── auth │ ├── auth.php │ ├── index.php │ └── routes.php ├── index.php └── todo │ ├── index.php │ ├── routes.php │ └── todo.php ├── assets └── js │ └── preview.js ├── cms_todo.sql ├── config.example.php ├── includes ├── Application.php ├── Base.php ├── TemplateFunctions.php ├── Widget.php └── index.php ├── index.php ├── libraries └── core │ ├── database │ ├── index.php │ └── mysql_database.php │ └── http │ ├── index.php │ └── routes.php ├── templates ├── default │ ├── 403.php │ ├── 404.php │ ├── 500.php │ ├── Screenshot.png │ ├── admin │ │ ├── index.php │ │ ├── themes.php │ │ ├── user_edit.php │ │ └── users_list.php │ ├── auth │ │ ├── auth.php │ │ ├── message.php │ │ └── resetpassword.php │ ├── css │ │ ├── bootstrap.min.css │ │ ├── style.css │ │ └── theme-list.css │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ └── glyphicons-halflings-regular.woff │ ├── footer.php │ ├── functions.php │ ├── header.php │ ├── index.php │ ├── js │ │ ├── bootstrap.min.js │ │ └── jquery-2.1.1.min.js │ ├── sidebar.php │ └── todo │ │ ├── edit.php │ │ ├── index.php │ │ ├── new.php │ │ └── show.php └── fixed_top │ ├── 400.php │ ├── 403.php │ ├── 404.php │ ├── 500.php │ ├── Screenshot.png │ ├── admin │ ├── index.php │ ├── themes.php │ ├── user_edit.php │ └── users_list.php │ ├── auth │ ├── auth.php │ ├── message.php │ └── resetpassword.php │ ├── css │ ├── bootstrap.min.css │ ├── style.css │ └── theme-list.css │ ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ └── glyphicons-halflings-regular.woff │ ├── footer.php │ ├── functions.php │ ├── header.php │ ├── index.php │ ├── js │ ├── bootstrap.min.js │ └── jquery-2.1.1.min.js │ ├── sidebar.php │ └── todo │ ├── edit.php │ ├── index.php │ ├── new.php │ └── show.php └── widgets ├── logo ├── index.php └── logo.php ├── nav ├── index.php └── nav.php ├── sidemenu ├── index.php └── sidemenu.php └── sidemenu2 ├── index.php └── sidemenu2.php /.gitignore: -------------------------------------------------------------------------------- 1 | config.php -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine on 2 | RewriteCond %{REQUEST_FILENAME} !-d 3 | RewriteCond %{REQUEST_FILENAME} !-f 4 | RewriteCond $1 !^(images|photos|css|js|robots\.txt) 5 | RewriteRule ^(.+)$ index.php/$1 [NC,L] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Harish Kumar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # todolist 2 | A truly free and open source self created cms demo by creating a todo app which you can contribute to the develop. Features include 3 | 4 | * Sleek, stylish, portable and well-distributed interface 5 | * Login, Log out and Register Users 6 | * A default to do application which add, edit and delete to do entries under different labels. Save a due date and calculate remaining time and mansion the progress of the work 7 | * Portability for modules and widgets 8 | * customizable themes ( new themes can be added) 9 | * Admin section 10 | * Privacy and Security 11 | * No Ads 12 | * No Spam 13 | 14 | Contact [Harish](https://www.facebook.com/profile.php?id=100003606204068) for more details. 15 | 16 | Installation 17 | ------- 18 | 19 | The frontend is developed [Bootstrap](http://getbootstrap.com/). 20 | If you wish to test it out, install xampp and fork the repository to `~\xampp\htdocs` for windows and `/var/www/html/` in linux. 21 | 22 | * Change config.example.php to config.php and set required config as mention in file. 23 | * Import sql file 24 | * Start apache and mysql services and go to `localhost\phpcms` . 25 | 26 | tutorials 27 | ------------ 28 | 29 | I am creating this cms as well as tutorial for this cms. The tutorials will be uploaded on my blogging webiste [Flowkl](https://www.flowkl.com/tutorial/web-development/learn-building-cms-from-scratch-with-todo-list-demo-in-php-and-mysql/) . 30 | 31 | Demo 32 | ------------ 33 | The simple demo of this project is live on [https://todo.flowkl.com](https://todo.flowkl.com). 34 | 35 | Contributing 36 | ------------ 37 | 38 | See [Contributing](CONTRIBUTING.md) 39 | 40 | -------------------------------------------------------------------------------- /applications/admin/admin.php: -------------------------------------------------------------------------------- 1 | update theme, update widgets, handle menues, handle users 10 | */ 11 | 12 | require_once('includes/Application.php'); 13 | require_once('includes/TemplateFunctions.php'); 14 | 15 | class AdminApplication extends Application 16 | { 17 | 18 | /** 19 | * login is required for accessing admin 20 | * NOTE: in production also restrict only for admin 21 | */ 22 | function __construct() 23 | { 24 | $this->login_required(); 25 | // uncomment this line for admin required 26 | // $this->admin_required(); 27 | } 28 | 29 | /** 30 | * restrict only for admin 31 | */ 32 | private function admin_required() 33 | { 34 | if ($_SESSION['user_session']['role'] !== 'admin') { 35 | $_SESSION['error'] = 'Only admin can access this page.'; 36 | $this->redirect($this->to_url('home')); 37 | } 38 | } 39 | 40 | /** 41 | * default display function for admin 42 | */ 43 | function display() 44 | { 45 | $this->index(); 46 | } 47 | 48 | /** 49 | * view admin dashboard 50 | */ 51 | function index() 52 | { 53 | require_once(TEMPLATE_PATH . '/admin/index.php'); 54 | } 55 | 56 | /** 57 | * show the list of all themes 58 | */ 59 | function theme_list() 60 | { 61 | $themes = scandir('templates'); 62 | require_once(TEMPLATE_PATH . '/admin/themes.php'); 63 | } 64 | 65 | /** 66 | * check if user is admin 67 | * @return string $theme 68 | */ 69 | private function theme_validator() 70 | { 71 | // this if statement is only because admin_required is not called in constructor 72 | // only for demo purpose 73 | if ($_SESSION['user_session']['role'] !== 'admin') { 74 | $_SESSION['error'] = 'Only admin can change the theme. You can use live preview'; 75 | $this->redirect($this->to_url('theme-settings')); 76 | } 77 | 78 | if (!isset($_GET['theme']) || empty($_GET['theme'])) { 79 | require TEMPLATE_PATH . '/400.php'; 80 | http_response_code(400); 81 | exit; 82 | } 83 | 84 | $theme = $_GET['theme']; 85 | $dir = 'templates/' . $theme; 86 | if (!is_dir($dir)) { 87 | require TEMPLATE_PATH . '/400.php'; 88 | http_response_code(400); 89 | exit; 90 | } 91 | 92 | return $theme; 93 | } 94 | 95 | /** 96 | * activate a new theme 97 | */ 98 | function theme_activate() 99 | { 100 | 101 | $theme = $this->theme_validator(); 102 | $db = $this->get_dbo(); 103 | $sql = "UPDATE `site_option` SET `option_value` = ? WHERE option_name = 'theme'"; 104 | if ($db->prepare($sql, array($theme))->rowCount()) { 105 | $_SESSION['success'] = 'theme is updated'; 106 | $this->redirect($this->to_url('theme-settings')); 107 | } 108 | $_SESSION['error'] = 'theme could not be updated'; 109 | $this->redirect($this->to_url('theme-settings')); 110 | } 111 | 112 | /** 113 | * live preview of theme 114 | */ 115 | function preview() 116 | { 117 | if (!isset($_GET['theme']) || empty($_GET['theme']) || !isset($_GET['url'])) { 118 | require TEMPLATE_PATH . '/400.php'; 119 | http_response_code(400); 120 | exit; 121 | } 122 | 123 | $theme = $_GET['theme']; 124 | $url = $_GET['url']; 125 | $this->redirect($url . '?preview=true&theme=' . $theme); 126 | } 127 | 128 | /** 129 | * display list of all users 130 | */ 131 | function admin_user_list() 132 | { 133 | $db = $this->get_dbo(); 134 | $sql = "SELECT * FROM `users`"; 135 | $users = $db->load_result($sql, array()); 136 | if ($users) { 137 | include(TEMPLATE_PATH . 'admin/users_list.php'); 138 | } else { 139 | $_SESSION['error'] = 'database connection error'; 140 | $this->redirect($this->to_url('admin-home')); 141 | } 142 | } 143 | 144 | /** 145 | * send edit user form 146 | * only admin restrict function 147 | */ 148 | function admin_edit_user($args) 149 | { 150 | $this->admin_required(); 151 | $id = $args['id']; 152 | $db = $this->get_dbo(); 153 | $sql = "SELECT * FROM `users` WHERE id= ?"; 154 | $user = $db->load_single_result($sql, array($id)); 155 | if ($user) { 156 | include(TEMPLATE_PATH . 'admin/user_edit.php'); 157 | } else { 158 | $_SESSION['error'] = 'database connection error'; 159 | $this->redirect($this->to_url('admin-home')); 160 | } 161 | } 162 | 163 | /** 164 | * if password is updated by admin 165 | */ 166 | private function handle_password($id, $password1, $password2) 167 | { 168 | if ($password2 != $password1) { 169 | $_SESSION['error'] = 'passwords do not match'; 170 | $this->redirect($this->to_url('admin-edit-user', ['id' => $id])); 171 | } 172 | 173 | $password = crypt($password1, sprintf('$6$rounds=%d$%s$', 10000, SECRET)); 174 | return $password; 175 | } 176 | 177 | /** 178 | * update an user 179 | */ 180 | function admin_update_user($args) 181 | { 182 | $this->admin_required(); 183 | $id = $args['id']; 184 | 185 | if (!isset($_POST['email']) || !isset($_POST['role'])) { 186 | $_SESSION['error'] = 'fill required fields'; 187 | $this->redirect($this->to_url('admin-edit-user', ['id' => $id])); 188 | } 189 | 190 | $email = $_POST['email']; 191 | if (!isset($_POST['is_active'])) 192 | $is_active = 1; 193 | else 194 | $is_active = 0; 195 | 196 | $role = $_POST['role']; 197 | $password = null; 198 | 199 | if (isset($_POST['password1']) || isset($_POST['password2'])) { 200 | $password = $this->handle_password($id, $_POST['password1'], $_POST['password2']); 201 | } 202 | 203 | if ($password) { 204 | $sql = "UPDATE `users` as user SET user.email=?,user.role=?,user.is_active=?,user.password=? WHERE user.id= ?"; 205 | $parms = [$email, $role, $is_active, $password, $id]; 206 | } else { 207 | $sql = "UPDATE `users` as user SET user.email=?,user.role=?,user.is_active=? WHERE user.id= ?"; 208 | $parms = [$email, $role, $is_active, $id]; 209 | } 210 | 211 | $db = $this->get_dbo(); 212 | $query = $db->prepare($sql, $parms); 213 | if ($query) { 214 | $_SESSION['success'] = 'User updated'; 215 | $this->redirect($this->to_url('admin-edit-user', ['id' => $id])); 216 | } else { 217 | $_SESSION['error'] = 'database connection error'; 218 | $this->redirect($this->to_url('admin-edit-user', ['id' => $id])); 219 | } 220 | } 221 | 222 | /** 223 | * delete an user 224 | */ 225 | function admin_delete_user($args) 226 | { 227 | $this->admin_required(); 228 | $id = $args['id']; 229 | $parms = [$id]; 230 | 231 | $db = $this->get_dbo(); 232 | $sql = "DELETE FROM `users` WHERE id=?"; 233 | $query = $db->prepare($sql, $parms); 234 | if ($query->rowCount !== 0) { 235 | $_SESSION['success'] = 'User deleted successfully'; 236 | $this->redirect($this->to_url('admin-user-list', ['id' => $id])); 237 | } else { 238 | $_SESSION['error'] = 'Database connection error'; 239 | $this->redirect($this->to_url('admin-user-list', ['id' => $id])); 240 | } 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /applications/admin/index.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/28harishkumar/phpcms/61b1e7afb41c24425352e7e70a5e2697026a0521/applications/admin/index.php -------------------------------------------------------------------------------- /applications/admin/routes.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'name' => 'admin-home', 6 | 'control' => 'admin@index', 7 | 'allow' => ['GET', 'POST'] 8 | ], 9 | 10 | 'admin/theme' => [ 11 | 'name' => 'theme-settings', 12 | 'control' => 'admin@theme_list', 13 | 'allow' => ['GET'] 14 | ], 15 | 16 | 'admin/theme/activate' => [ 17 | 'name' => 'theme-activate', 18 | 'control' => 'admin@theme_activate', 19 | 'allow' => ['POST'] 20 | ], 21 | 22 | 'admin/theme/preview' => [ 23 | 'name' => 'live-preview', 24 | 'control' => 'admin@preview', 25 | 'allow' => ['GET', 'POST'] 26 | ], 27 | /* 28 | these disable links are port for next versionq 29 | 30 | 'admin/widget' => [ 31 | 'name' => 'widget-settings', 32 | 'control' => 'admin@widgets_list', 33 | 'allow' => ['GET']], 34 | 35 | 'admin/widget/update' => [ 36 | 'name' => 'widgets-update', 37 | 'control' => 'admin@user_list', 38 | 'allow' => ['POST']], 39 | 40 | 'admin/menus' => [ 41 | 'name' => 'menu-list', 42 | 'control' =>'admin@menu_list', 43 | 'allow' => ['GET']], 44 | 45 | 'admin/menus/add' => [ 46 | 'name' => 'add-menu', 47 | 'control' =>'admin@add_menu', 48 | 'allow' => ['POST']], 49 | 50 | 'admin/menus/{id}[0-9]+' => [ 51 | 'name' => 'edit-menu', 52 | 'control' =>'admin@edit_menu', 53 | 'allow' => ['GET']], 54 | 55 | 'admin/menus/{id}[0-9]+/delete' => [ 56 | 'name' => 'delete-menu', 57 | 'control' =>'admin@delete_menu', 58 | 'allow' => ['POST']], 59 | 60 | 'admin/menus/manage' => [ 61 | 'name' => 'manage-menu-list', 62 | 'control' =>'admin@manage_menu_list', 63 | 'allow' => ['GET']], 64 | 65 | 'admin/menus/manage/update' => [ 66 | 'name' => 'manage-menu', 67 | 'control' =>'admin@manage_menu', 68 | 'allow' => ['POST']], 69 | 70 | 'admin/users/new' => [ 71 | 'name' => 'admin-new-user', 72 | 'control' =>'admin@admin_new_user', 73 | 'allow' => ['GET']], 74 | 75 | 'admin/users/add' => [ 76 | 'name' => 'admin-add-user', 77 | 'control' =>'admin@admin_add_user', 78 | 'allow' => ['POST']], 79 | 80 | */ 81 | 82 | 'admin/users' => [ 83 | 'name' => 'admin-user-list', 84 | 'control' => 'admin@admin_user_list', 85 | 'allow' => ['GET'] 86 | ], 87 | 88 | 'admin/user/{id}[0-9]+/edit' => [ 89 | 'name' => 'admin-edit-user', 90 | 'control' => 'admin@admin_edit_user', 91 | 'allow' => ['GET'] 92 | ], 93 | 94 | 'admin/user/{id}[0-9]+/update' => [ 95 | 'name' => 'admin-update-user', 96 | 'control' => 'admin@admin_update_user', 97 | 'allow' => ['POST'] 98 | ], 99 | 100 | 'admin/user/{id}[0-9]+/delete' => [ 101 | 'name' => 'admin-delete-user', 102 | 'control' => 'admin@admin_delete_user', 103 | 'allow' => ['POST'] 104 | ], 105 | ]; 106 | -------------------------------------------------------------------------------- /applications/auth/auth.php: -------------------------------------------------------------------------------- 1 | login, logout, register, reset-password, send verification email 10 | */ 11 | 12 | require_once('includes/Application.php'); 13 | 14 | class AuthApplication extends Application 15 | { 16 | 17 | /** 18 | * default function that will run if no operation is choosen 19 | */ 20 | function display() 21 | { 22 | //check if any session exists otherwise login 23 | $this->check_login($this->to_url('login-form')); 24 | } 25 | 26 | /** 27 | * verify if any session exists 28 | * @param string $url 29 | */ 30 | private function check_login($url = null) 31 | { 32 | if (isset($_SESSION['user_session'])) { 33 | $this->redirect(); 34 | } 35 | if ($url !== null) { 36 | $this->redirect($url); 37 | } 38 | } 39 | 40 | /** 41 | * return authentication form 42 | */ 43 | function login_form() 44 | { 45 | $this->check_login(); 46 | require_once(TEMPLATE_PATH . 'auth/auth.php'); 47 | } 48 | 49 | /** 50 | * login user 51 | * @param string $email 52 | * @param string $password 53 | * @return redirect 54 | */ 55 | private function login($email, $password) 56 | { 57 | $db = $this->get_dbo(); 58 | $email = $db->quote($email); 59 | $password = crypt($password, sprintf('$6$rounds=%d$%s$', 10000, SECRET)); 60 | 61 | $sql = "SELECT * FROM `users` WHERE email=? AND password=? AND is_active = 1"; 62 | $query = $db->load_single_result($sql, array($email, $password)); 63 | 64 | if (isset($query['id'])) { 65 | $_SESSION['user_session'] = $query; 66 | 67 | if (isset($_SESSION['user_session'])) { 68 | $this->redirect(); 69 | } else { 70 | $_SESSION['l_error'] = 'Email and password do not match'; 71 | $this->redirect($this->to_url('login-form')); 72 | } 73 | } else { 74 | $_SESSION['l_error'] = 'Email and password do not match'; 75 | $this->redirect($this->to_url('login-form')); 76 | } 77 | 78 | $this->redirect(); 79 | } 80 | 81 | /** 82 | * take login credentials from user 83 | * pass credentials to login function 84 | */ 85 | function login_user() 86 | { 87 | $this->check_login(); 88 | $email = $_POST['login-email']; 89 | $password = $_POST['password']; 90 | $this->login($email, $password); 91 | } 92 | 93 | /** 94 | * logout the user 95 | */ 96 | private function logout() 97 | { 98 | if (isset($_SESSION['user_session']) && $_SESSION['user_session']) { 99 | session_destroy(); 100 | } 101 | $this->redirect($this->to_url('login-form')); 102 | } 103 | 104 | /** 105 | * logout a user 106 | */ 107 | function logout_user() 108 | { 109 | $this->logout(); 110 | } 111 | 112 | /** 113 | * returns user information 114 | * @param string $email 115 | * @return query $query 116 | */ 117 | private function get_user_info($email) 118 | { 119 | $db = $this->get_dbo(); 120 | $query = $db->load_single_result("SELECT * FROM users WHERE email = ?", array($email)); 121 | return $query; 122 | } 123 | 124 | /** 125 | * send error if any exists during registeration 126 | * @param staring $error_code 127 | * @return redirect 128 | */ 129 | private function error_info($error_code = null) 130 | { 131 | switch ($error_code) { 132 | case 'incomplete': 133 | $error = 'All fields are required'; 134 | break; 135 | case 'passmismatch': 136 | $error = 'Passwords do not match'; 137 | break; 138 | case 'alreadyexist': 139 | $error = 'Email already exists'; 140 | break; 141 | case 'loginfail': 142 | $error = 'Email and password do not match'; 143 | break; 144 | case 'min_lenght_error': 145 | $error = 'minimum 8 character password required'; 146 | break; 147 | default: 148 | $error = 'Some error occurred'; 149 | break; 150 | } 151 | 152 | $_SESSION['error'] = $error; 153 | $url = $this->to_url('signup-form'); 154 | $this->redirect($url); 155 | } 156 | 157 | /** 158 | * register new user 159 | * @param string $email 160 | * @param string $password 161 | * @return int $count 162 | */ 163 | private function register($email, $password) 164 | { 165 | $db = $this->get_dbo(); 166 | $eml = $db->quote($email); 167 | if ($this->get_user_info($eml)) { 168 | $this->error_info('alreadyexist'); 169 | } 170 | $password = crypt($password, sprintf('$6$rounds=%d$%s$', 10000, SECRET)); 171 | $code = hash('sha512', 'register' . $email . '' . time()); 172 | $created_at = new DateTime(); 173 | $created_at = $created_at->format('Y-m-d H:i:s'); 174 | $updated_at = new DateTime(); 175 | $updated_at = $updated_at->format('Y-m-d H:i:s'); 176 | 177 | $sql = "INSERT INTO `users` (email,password,confirm_code,created_at,updated_at) VALUES(?,?,?,?,?)"; 178 | $query = $db->prepare($sql, array($eml, $password, $code, $created_at, $updated_at)); 179 | $count = $query->rowCount(); 180 | if ($count) { 181 | $this->send_register_email($email, $code); 182 | } 183 | return $count; 184 | } 185 | 186 | /** 187 | * prepare verification email for registering user 188 | * @param string $title 189 | * @param string $link 190 | * @param string $message 191 | * @return string(html) $body 192 | */ 193 | private function email_message($title, $link, $message) 194 | { 195 | return " 196 | 197 |

" . $title . "

198 |

Click on the link " . $message . ">

199 |

Go Back to Home page

200 |




201 | It is auto generated message. Don't reply for this message. Only click on the links. 202 | 203 | "; 204 | } 205 | 206 | /** 207 | * send email to registered user 208 | * config your init.php for working this function 209 | * @param string $email 210 | * @param string $code 211 | */ 212 | private function send_register_email($email, $code) 213 | { 214 | $subject = "My to do email register"; 215 | //put domain name instead of localhost 216 | $link = $this->to_url('verify-email', ['code' => $code, 'email' => $email]); 217 | $title = 'Confirm email for registeration'; 218 | $message = 'Confirm Email'; 219 | $txt = $this->email_message($title, $link, $message); 220 | $headers = "MIME-Version: 1.0" . "\r\n"; 221 | $headers .= "Content-type:text/html;charset=UTF-8" . "\r\n"; 222 | // $headers .= "From: webmaster@example.com"; 223 | 224 | mail($email, $subject, $txt, $headers); 225 | } 226 | 227 | /** 228 | * take registeration credentials from user 229 | */ 230 | function register_user() 231 | { 232 | $this->check_login(); 233 | $email = $_POST['email']; 234 | $pass1 = $_POST['password1']; 235 | $pass2 = $_POST['password2']; 236 | if (!isset($email) or !isset($pass1) or !isset($pass2)) { 237 | $this->error_info('incomplete'); 238 | } 239 | 240 | if ($pass1 !== $pass2) { 241 | $this->error_info('passmismatch'); 242 | } 243 | 244 | if (strlen($pass1) < 8) { 245 | $this->error_info('min_lenght_error'); 246 | } 247 | 248 | if ($this->register($email, $pass1)) { 249 | $message = 'You have register succesfully. Now open your email id and click on the confirmation link'; 250 | $heading = 'Success'; 251 | require(TEMPLATE_PATH . 'auth/message.php'); 252 | } else { 253 | $this->error_info(); 254 | } 255 | } 256 | 257 | /** 258 | * match the confirmation code in link for verifying registered email 259 | * @param array $args 260 | * @param string $args['code'] 261 | * @param staring $args['email'] 262 | */ 263 | function verify_email($args) 264 | { 265 | $this->check_login(); 266 | if (!isset($args['code']) or !isset($args['email'])) { 267 | $this->redirect(); 268 | } 269 | 270 | $code = $args['code']; 271 | $email = $args['email']; 272 | $db = $this->get_dbo(); 273 | $email = $db->quote($email); 274 | $data = $this->get_user_info($email); 275 | $query = null; 276 | if ($data['confirm_code'] == $code && $code != '0') { 277 | $updated_at = new DateTime(); 278 | $updated_at = $updated_at->format('Y-m-d H:i:s'); 279 | $sql = "UPDATE `users` as user SET user.is_active='1', user.confirm_code='0', user.updated_at=? WHERE user.email= ?"; 280 | $query = $db->prepare($sql, array($updated_at, $email)); 281 | } else { 282 | $this->redirect(); 283 | } 284 | 285 | if ($query->rowCount()) { 286 | $_SESSION['user_session'] = $data; 287 | } 288 | $this->redirect(); 289 | } 290 | 291 | /** 292 | * return reset password form 293 | * @return HTMLResponse 294 | */ 295 | function forget_password() 296 | { 297 | $this->check_login(); 298 | if (!isset($_POST['forget-email'])) { 299 | $this->redirect(); 300 | } 301 | 302 | $email = $_POST['forget-email']; 303 | $code = hash('sha512', 'forget$kfsdgf8dsfds' . $email . '' . time()); 304 | $db = $this->get_dbo(); 305 | $eml = $db->quote($email); 306 | $updated_at = new DateTime(); 307 | $updated_at = $updated_at->format('Y-m-d H:i:s'); 308 | $sql = "UPDATE `users` SET confirm_code= '$code', updated_at=? WHERE email= ?"; 309 | $query = $db->prepare($sql, array($updated_at, $eml)); 310 | if ($query->rowCount()) { 311 | $this->send_reset_email($code, $email); 312 | $message = 'Your reset password information has been sent to your email address.'; 313 | $heading = 'Success'; 314 | } else { 315 | $message = 'You have provide invalid email address'; 316 | $heading = 'Error'; 317 | } 318 | require(TEMPLATE_PATH . 'auth/message.php'); 319 | } 320 | 321 | /** 322 | * emails reset password link 323 | * @param string $code 324 | * @param string $email 325 | */ 326 | private function send_reset_email($code, $email) 327 | { 328 | $subject = "My to do password reset"; 329 | //put domain name instead of localhost 330 | $link = $this->to_url('reset-password', ['code' => $code, 'email' => $email]); 331 | $title = 'Reset Password'; 332 | $message = "confirm reset Password"; 333 | $txt = $this->email_message($title, $link, $message); 334 | $headers = "From: webmaster@example.com" . "\r\n" . 335 | "CC: somebodyelse@example.com"; 336 | 337 | mail($email, $subject, $txt, $headers); 338 | } 339 | 340 | /** 341 | * send reset password form 342 | * @param array $args 343 | * @param string $args['code'] 344 | * @param string $args['email'] 345 | */ 346 | function reset_password_form($args) 347 | { 348 | $this->check_login(); 349 | if (!isset($args['code']) or !isset($args['email'])) { 350 | $this->redirect(); 351 | } 352 | 353 | $code = $args['code']; 354 | $email = $args['email']; 355 | $db = $this->get_dbo(); 356 | $email = $db->quote($email); 357 | $data = $this->get_user_info($email); 358 | 359 | if ($data['confirm_code'] !== $code || $code == '0') { 360 | $this->redirect(); 361 | } 362 | 363 | require(TEMPLATE_PATH . 'auth/resetpassword.php'); 364 | } 365 | 366 | /** 367 | * reset user password 368 | * @return HTMLResponse 369 | */ 370 | function reset_password() 371 | { 372 | $this->check_login(); 373 | if (!isset($_POST['i']) or !isset($_POST['e']) or !isset($_POST['pass1']) or !isset($_POST['pass2'])) { 374 | header('HTTP/1.1 403 Forbidden'); 375 | $heading = 'forbidden request!'; 376 | $message = 'all fields are required. Try again by clicking on link in email.'; 377 | require(TEMPLATE_PATH . 'auth/message.php'); 378 | exit(); 379 | } 380 | 381 | $pass1 = $_POST['pass1']; 382 | $pass2 = $_POST['pass2']; 383 | $email = $_POST['e']; 384 | $code = $_POST['i']; 385 | 386 | if ($pass2 !== $pass1) { 387 | $error = 'password mismatch'; 388 | require(TEMPLATE_PATH . 'auth/resetpassword.php'); 389 | exit(); 390 | } 391 | 392 | $db = $this->get_dbo(); 393 | $eml = $db->quote($email); 394 | $data = $this->get_user_info($eml); 395 | $query = null; 396 | 397 | if ($data['confirm_code'] == $code && $code != '0') { 398 | $updated_at = new DateTime(); 399 | $updated_at = $updated_at->format('Y-m-d H:i:s'); 400 | $sql = "UPDATE `users` as user SET user.confirm_code='0', user.updated_at=? WHERE user.email= ?"; 401 | $query = $db->prepare($sql, array($updated_at, $eml)); 402 | } else { 403 | header('HTTP/1.1 403 Forbidden'); 404 | $heading = 'forbidden request!'; 405 | $message = 'Validation error. Try again by clicking on link in email.'; 406 | require(TEMPLATE_PATH . 'auth/message.php'); 407 | exit(); 408 | } 409 | 410 | if ($query and $query->rowCount()) { 411 | $pass1 = crypt($pass1, sprintf('$6$rounds=%d$%s$', 10000, SECRET)); 412 | $db = $this->get_dbo(); 413 | $eml = $db->quote($email); 414 | $updated_at = new DateTime(); 415 | $updated_at = $updated_at->format('Y-m-d H:i:s'); 416 | $sql = "UPDATE `users` SET confirm_code= '0', password = ?, updated_at=? WHERE email= ?"; 417 | $query = $db->prepare($sql, array($pass1, $eml, $updated_at)); 418 | if ($query->rowCount()) { 419 | $message = 'Your reset password has been reseted.'; 420 | $heading = 'Success'; 421 | } else { 422 | $message = 'You have provide invalid data'; 423 | $heading = 'Error'; 424 | } 425 | } else { 426 | $message = 'You have provide invalid data'; 427 | $heading = 'Error'; 428 | } 429 | require(TEMPLATE_PATH . 'auth/message.php'); 430 | } 431 | } 432 | -------------------------------------------------------------------------------- /applications/auth/index.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/28harishkumar/phpcms/61b1e7afb41c24425352e7e70a5e2697026a0521/applications/auth/index.php -------------------------------------------------------------------------------- /applications/auth/routes.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'name' => 'login-form', 6 | 'control' => 'auth@login_form', 7 | 'allow' => ['GET', 'POST'] 8 | ], 9 | 10 | 'auth/login-form\#signup' => [ 11 | 'name' => 'signup-form', 12 | 'control' => 'auth@login_form', 13 | 'allow' => ['GET', 'POST'] 14 | ], 15 | 16 | 'auth/login' => [ 17 | 'name' => 'login', 18 | 'control' => 'auth@login_user', 19 | 'allow' => ['POST'] 20 | ], 21 | 22 | 'auth/register' => [ 23 | 'name' => 'register', 24 | 'control' => 'auth@register_user', 25 | 'allow' => ['POST'] 26 | ], 27 | 28 | 'auth/verify-email/{code}[0-9a-z]+/{email}[0-9a-zA-Z\.@]+' => [ 29 | 'name' => 'verify-email', 30 | 'control' => 'auth@verify_email', 31 | 'allow' => ['GET'] 32 | ], 33 | 34 | 'auth/forget-password' => [ 35 | 'name' => 'forget-password', 36 | 'control' => 'auth@forget_password', 37 | 'allow' => ['POST'] 38 | ], 39 | 40 | 'auth/reset' => [ 41 | 'name' => 'reset', 42 | 'control' => 'auth@reset_password', 43 | 'allow' => ['POST'] 44 | ], 45 | 46 | 'auth/reset-password/{code}[0-9a-z]+/{email}[0-9a-zA-Z\.@]+' => [ 47 | 'name' => 'reset-password', 48 | 'control' => 'auth@reset_password_form', 49 | 'allow' => ['GET'] 50 | ], 51 | 52 | 'auth/logout' => [ 53 | 'name' => 'logout', 54 | 'control' => 'auth@logout_user', 55 | 'allow' => ['GET'] 56 | ], 57 | ]; 58 | -------------------------------------------------------------------------------- /applications/index.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/28harishkumar/phpcms/61b1e7afb41c24425352e7e70a5e2697026a0521/applications/index.php -------------------------------------------------------------------------------- /applications/todo/index.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/28harishkumar/phpcms/61b1e7afb41c24425352e7e70a5e2697026a0521/applications/todo/index.php -------------------------------------------------------------------------------- /applications/todo/routes.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'name' => 'home', 6 | 'control' => 'todo@index', 7 | 'allow' => ['GET',] 8 | ], 9 | 'todo' => [ 10 | 'name' => 'todo-home', 11 | 'control' => 'todo@index', 12 | 'allow' => ['GET',] 13 | ], 14 | 15 | 'todo/new' => [ 16 | 'name' => 'new-todo', 17 | 'control' => 'todo@add', 18 | 'allow' => ['GET',] 19 | ], 20 | 21 | 'todo/add' => [ 22 | 'name' => 'add-todo', 23 | 'control' => 'todo@create', 24 | 'allow' => ['POST'] 25 | ], 26 | 27 | 'todo/edit/{id}[0-9]+' => [ 28 | 'name' => 'edit-todo', 29 | 'control' => 'todo@edit', 30 | 'allow' => ['GET'] 31 | ], 32 | 33 | 'todo/update' => [ 34 | 'name' => 'update-todo', 35 | 'control' => 'todo@update', 36 | 'allow' => ['POST'] 37 | ], 38 | 39 | 'todo/delete/{id}[0-9]+' => [ 40 | 'name' => 'delete-todo', 41 | 'control' => 'todo@destroy', 42 | 'allow' => ['POST'] 43 | ], 44 | 45 | 'todo/list' => [ 46 | 'name' => 'todo-list', 47 | 'control' => 'todo@index', 48 | 'allow' => ['GET'] 49 | ], 50 | 51 | 'todo/list/{label}[a-z]+' => [ 52 | 'name' => 'todo-label', 53 | 'control' => 'todo@index', 54 | 'allow' => ['GET'] 55 | ], 56 | 57 | 'todo/show/{id}[0-9]+' => [ 58 | 'name' => 'show-todo', 59 | 'control' => 'todo@show', 60 | 'allow' => ['GET'] 61 | ], 62 | ]; 63 | -------------------------------------------------------------------------------- /applications/todo/todo.php: -------------------------------------------------------------------------------- 1 | login_required(); 19 | } 20 | 21 | /** 22 | * display list of all todos 23 | */ 24 | function display() 25 | { 26 | $this->index(); 27 | } 28 | 29 | /** 30 | * calculate time left for listed todo tasks 31 | * @param date $end_date 32 | * @return string $time_left 33 | */ 34 | private function time_left($end_date) 35 | { 36 | $today = strtotime("now"); 37 | $due_date = strtotime($end_date); 38 | if($due_date>$today) 39 | { 40 | $hours = $due_date - $today; 41 | $hours = $hours/3600; 42 | $time_left = $hours/24; 43 | 44 | if($time_left < 1) 45 | { 46 | $time_left = 'Less than 1 day'; 47 | } 48 | else 49 | { 50 | $time_left = round($time_left).' days'; 51 | } 52 | } 53 | else 54 | { 55 | $time_left = 'Expired'; 56 | } 57 | 58 | return $time_left; 59 | } 60 | 61 | /** 62 | * show the list of listed todos 63 | * @param array $args 64 | * @param string $args['label'] 65 | * @return HttpResponse 66 | */ 67 | function index($args= null) 68 | { 69 | $label = isset($args['label']) ? $args['label']:'all'; 70 | $user_id = $_SESSION['user_session']['id']; 71 | $db=$this->get_dbo(); 72 | if($label == 'all') 73 | { 74 | $sql="SELECT * FROM `todolist` WHERE user_id=?"; 75 | $args = array($user_id); 76 | } 77 | else 78 | { 79 | $sql="SELECT * FROM `todolist` WHERE label=? AND user_id=? "; 80 | $args = array($label,$user_id); 81 | } 82 | $rows=$db->load_result($sql,$args); 83 | // include view todo list 84 | include_once(TEMPLATE_PATH.'/todo/index.php'); 85 | } 86 | 87 | /** 88 | * form for adding a new todo 89 | * @return HttpResponse 90 | */ 91 | function add() 92 | { 93 | include_once(TEMPLATE_PATH.'/todo/new.php'); 94 | } 95 | 96 | /** 97 | * add a new todo task 98 | * @return redirect 99 | */ 100 | function create() 101 | { 102 | 103 | $title= filter_input(INPUT_POST, 'title', FILTER_SANITIZE_SPECIAL_CHARS); 104 | $desc= filter_input(INPUT_POST, 'desc', FILTER_SANITIZE_SPECIAL_CHARS); 105 | $end_date= filter_input(INPUT_POST, 'end_date', FILTER_SANITIZE_SPECIAL_CHARS); 106 | $label= filter_input(INPUT_POST, 'label', FILTER_SANITIZE_SPECIAL_CHARS); 107 | $start_date = date("Y-m-d"); 108 | $sql="INSERT INTO `todolist` VALUES(?,?,?,?,?,?,?,?)"; 109 | $user_id = $_SESSION['user_session']['id']; 110 | $args = array(NULL,$title,$desc,0,$start_date,$end_date,$label,$user_id); 111 | $db=$this->get_dbo(); 112 | if($db->prepare($sql,$args)) 113 | { 114 | $this->redirect($this->to_url('todo-home')); 115 | } 116 | else 117 | { 118 | $this->redirect(); 119 | } 120 | 121 | } 122 | 123 | /** 124 | * form for editing a todo entry 125 | * @param array $args 126 | * @param string $args['id'] 127 | * @return HttpResponse 128 | */ 129 | function edit($args) 130 | { 131 | $id=$args['id']; 132 | $user_id = $_SESSION['user_session']['id']; 133 | $sql="SELECT * FROM `todolist` WHERE id=? AND user_id=?"; 134 | $db=$this->get_dbo(); 135 | $row=$db->load_single_result($sql,array($id,$user_id)); 136 | include_once(TEMPLATE_PATH.'/todo/edit.php'); 137 | } 138 | 139 | /** 140 | * edit an existing todo 141 | * @return redirect 142 | */ 143 | function update() 144 | { 145 | $id= filter_input(INPUT_POST, 'id', FILTER_SANITIZE_SPECIAL_CHARS); 146 | $title= filter_input(INPUT_POST, 'title', FILTER_SANITIZE_SPECIAL_CHARS); 147 | $desc= filter_input(INPUT_POST, 'desc', FILTER_SANITIZE_SPECIAL_CHARS); 148 | $end_date= filter_input(INPUT_POST, 'end_date', FILTER_SANITIZE_SPECIAL_CHARS); 149 | $label= filter_input(INPUT_POST, 'label', FILTER_SANITIZE_SPECIAL_CHARS); 150 | $progress = $_POST['progress']; 151 | $user_id = $_SESSION['user_session']['id']; 152 | $sql="UPDATE `todolist` as tasks SET tasks.title=?,tasks.desc=?, tasks.progress=?, tasks.end_date=?, tasks.label=? WHERE id=? AND user_id =?"; 153 | $db=$this->get_dbo(); 154 | if($db->prepare($sql,array($title,$desc,$progress,$end_date,$label,$id,$user_id))) 155 | { 156 | $this->redirect($this->to_url('todo-home')); 157 | } 158 | else 159 | { 160 | $this->redirect(); 161 | } 162 | } 163 | 164 | /** 165 | * show discription of todo 166 | * @param array $args 167 | * @param string $args['id'] 168 | * @return HttpResponse 169 | */ 170 | function show($args = null) 171 | { 172 | $id = $args['id']; 173 | $user_id = $_SESSION['user_session']['id']; 174 | $sql="SELECT * FROM `todolist` WHERE id=? AND user_id=?"; 175 | $args = array($id,$user_id); 176 | $db=$this->get_dbo(); 177 | $row=$db->load_single_result($sql,$args); 178 | // include view todo list 179 | include_once(TEMPLATE_PATH.'/todo/show.php'); 180 | } 181 | 182 | /** 183 | * delete an existing task 184 | * @param array $args 185 | * @param string $args['id'] 186 | * @return redirect 187 | */ 188 | function destroy($args) 189 | { 190 | $id=$args['id']; 191 | $user_id = $_SESSION['user_session']['id']; 192 | $db=$this->get_dbo(); 193 | $sql="DELETE FROM `todolist` WHERE id=? AND user_id =?"; 194 | if($db->prepare($sql,array($id,$user_id))->rowCount()!==0) 195 | { 196 | $_SESSION['success'] = 'deleted successfully'.$id; 197 | $this->redirect($this->to_url('todo-home')); 198 | } 199 | $_SESSION['error'] = 'could not deleted successfully'; 200 | $this->redirect($this->to_url('todo-home')); 201 | } 202 | 203 | 204 | } 205 | -------------------------------------------------------------------------------- /assets/js/preview.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | var links = $('body a[href]'); 3 | $.each(links,function preview_function(key,link){ 4 | console.log(link); 5 | if(link.href.indexOf('?') > -1) 6 | { 7 | link.href = link.href+"&preview=true&theme=default"; 8 | } 9 | else 10 | link.href = link.href+"?preview=true&theme=default"; 11 | }); 12 | }); -------------------------------------------------------------------------------- /cms_todo.sql: -------------------------------------------------------------------------------- 1 | -- phpMyAdmin SQL Dump 2 | -- version 4.2.12deb2 3 | -- http://www.phpmyadmin.net 4 | -- 5 | -- Host: localhost 6 | -- Generation Time: Jul 10, 2015 at 07:42 PM 7 | -- Server version: 5.5.43-0+deb7u1 8 | -- PHP Version: 5.6.7-1 9 | 10 | SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; 11 | SET time_zone = "+00:00"; 12 | 13 | 14 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 15 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 16 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 17 | /*!40101 SET NAMES utf8 */; 18 | 19 | -- 20 | -- Database: `cms_todo` 21 | -- 22 | 23 | -- -------------------------------------------------------- 24 | 25 | -- 26 | -- Table structure for table `site_option` 27 | -- 28 | 29 | CREATE TABLE IF NOT EXISTS `site_option` ( 30 | `id` int(11) NOT NULL, 31 | `option_name` varchar(250) NOT NULL, 32 | `option_value` varchar(250) NOT NULL 33 | ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; 34 | 35 | -- 36 | -- Dumping data for table `site_option` 37 | -- 38 | 39 | INSERT INTO `site_option` (`id`, `option_name`, `option_value`) VALUES 40 | (1, 'theme', 'fixed_top'); 41 | 42 | -- -------------------------------------------------------- 43 | 44 | -- 45 | -- Table structure for table `todolist` 46 | -- 47 | 48 | CREATE TABLE IF NOT EXISTS `todolist` ( 49 | `id` int(11) NOT NULL, 50 | `title` varchar(255) NOT NULL, 51 | `desc` text NOT NULL, 52 | `progress` smallint(3) NOT NULL DEFAULT '0', 53 | `start_date` date NOT NULL, 54 | `end_date` date NOT NULL, 55 | `label` varchar(50) NOT NULL, 56 | `user_id` bigint(20) NOT NULL 57 | ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; 58 | 59 | 60 | -- -------------------------------------------------------- 61 | 62 | -- 63 | -- Table structure for table `users` 64 | -- 65 | 66 | CREATE TABLE IF NOT EXISTS `users` ( 67 | `id` bigint(20) NOT NULL, 68 | `email` varchar(60) NOT NULL, 69 | `password` varchar(256) NOT NULL, 70 | `confirm_code` varchar(256) NOT NULL DEFAULT '0', 71 | `is_active` tinyint(1) NOT NULL DEFAULT '0', 72 | `role` enum('admin','demo_checker','user') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT 'demo_checker', 73 | `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 74 | `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' 75 | ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; 76 | 77 | -- 78 | -- Indexes for dumped tables 79 | -- 80 | 81 | -- 82 | -- Indexes for table `option` 83 | -- 84 | ALTER TABLE `site_option` 85 | ADD PRIMARY KEY (`id`); 86 | 87 | -- 88 | -- Indexes for table `todolist` 89 | -- 90 | ALTER TABLE `todolist` 91 | ADD PRIMARY KEY (`id`); 92 | 93 | -- 94 | -- Indexes for table `users` 95 | -- 96 | ALTER TABLE `users` 97 | ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `email` (`email`); 98 | 99 | -- 100 | -- AUTO_INCREMENT for dumped tables 101 | -- 102 | 103 | -- 104 | -- AUTO_INCREMENT for table `option` 105 | -- 106 | ALTER TABLE `site_option` 107 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=1; 108 | -- 109 | -- AUTO_INCREMENT for table `todolist` 110 | -- 111 | ALTER TABLE `todolist` 112 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=1; 113 | -- 114 | -- AUTO_INCREMENT for table `users` 115 | -- 116 | ALTER TABLE `users` 117 | MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=1; 118 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 119 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 120 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 121 | -------------------------------------------------------------------------------- /config.example.php: -------------------------------------------------------------------------------- 1 | 'mysql', 8 | 9 | // config database connections 10 | 'connection' => [ 11 | 'mysql' => [ 12 | 'driver' => 'mysql', 13 | 'host' => 'your host', 14 | 'database' => 'your database name', 15 | 'username' => 'your username', 16 | 'password' => 'your password', 17 | ], 18 | ], 19 | 20 | // set the location of application withour trailing slash 21 | 'root' => '', // example 'http://localhost/todolist' or http://demo.findalltogeher.com 22 | 23 | // register apps 24 | 'apps' => [ 25 | 'auth', 26 | 'todo', 27 | 'admin', 28 | ], 29 | 30 | // secret string for encreption 31 | 'secret' => 'this_is_secret_string', // example 'fa&k+j@sdf!has^dh-iu!d#dh$sd' 32 | 33 | ]; 34 | -------------------------------------------------------------------------------- /includes/Application.php: -------------------------------------------------------------------------------- 1 | $method($args); 23 | } else { 24 | $this->$method(); 25 | } 26 | } 27 | 28 | /** 29 | * default response to user for any request 30 | * 31 | */ 32 | abstract function display(); 33 | 34 | /** 35 | * redirect function for application 36 | */ 37 | protected function redirect($url = null, $msg = null) 38 | { 39 | if (empty($url)) { 40 | header('Location:' . ROOT); 41 | } else { 42 | header('Location:' . $url); 43 | } 44 | exit(0); 45 | } 46 | 47 | /** 48 | * protect application with logged in required layer 49 | */ 50 | protected function login_required() 51 | { 52 | if (!isset($_SESSION['user_session'])) { 53 | $this->redirect($this->to_url('login-form')); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /includes/Base.php: -------------------------------------------------------------------------------- 1 | load_routes(); 60 | } 61 | return $routes; 62 | } 63 | 64 | /** 65 | * it is used for named urls 66 | * @param string $name 67 | * @param array $args 68 | * @return string url 69 | */ 70 | protected function to_url($name, $args = null) 71 | { 72 | $r = $this->get_routes(); 73 | if ($args !== null) 74 | return $r->to_route($name, $args); 75 | else 76 | return $r->to_route($name); 77 | } 78 | 79 | /** 80 | * abatract function run for executing applicaiton 81 | */ 82 | abstract function run($arg = null, $param = null); 83 | } 84 | -------------------------------------------------------------------------------- /includes/TemplateFunctions.php: -------------------------------------------------------------------------------- 1 | template_name == null) { 28 | $this->template_name = $this->get_current_template(); 29 | } 30 | } 31 | 32 | /** 33 | * run whole CMS and render generated html page 34 | */ 35 | function run($arg = null, $param = null) 36 | { 37 | require_once(TEMPLATE_PATH . 'functions.php'); 38 | require_once(TEMPLATE_PATH . 'index.php'); 39 | } 40 | 41 | /** 42 | * set a template 43 | */ 44 | function set_template($template_name) 45 | { 46 | $this->template_name = $template_name; 47 | } 48 | 49 | /** 50 | * get currently active template 51 | */ 52 | private function get_current_template() 53 | { 54 | if (isset($_GET['preview']) && isset($_GET['theme']) && $_SESSION['user_session']['role'] !== 'user') { 55 | define('PREVIEW', true); 56 | return $_GET['theme']; 57 | } 58 | 59 | $db = $this->get_dbo(); 60 | $sql = "SELECT `option_value` FROM `site_option` WHERE option_name = ?"; 61 | $template_name = $db->load_single_result($sql, array('theme')); 62 | 63 | if ($template_name) { 64 | return $template_name['option_value']; 65 | } 66 | 67 | return 'default'; 68 | } 69 | 70 | /** 71 | * return current theme name 72 | * @return string $this->template_name 73 | */ 74 | function get_current_theme() 75 | { 76 | return $this->template_name; 77 | } 78 | 79 | /** 80 | * return currently active template path 81 | * it is relative path to root index.php 82 | * @return string template_path 83 | */ 84 | function get_current_template_path() 85 | { 86 | return 'templates/' . $this->template_name . '/'; 87 | } 88 | 89 | /** 90 | * return static media path in template path 91 | * it is absolute path 92 | * @return string template_path 93 | */ 94 | function get_static_path() 95 | { 96 | return ROOT . '/' . TEMPLATE_PATH; 97 | } 98 | 99 | /** 100 | * action for app output 101 | * resoulve app name and requested function from url 102 | * then run application class for generating output 103 | */ 104 | function app_output() 105 | { 106 | // Route class instance 107 | $routes = $this->get_routes(); 108 | // fetch app and function name 109 | $destination = $routes->get_destination(); 110 | 111 | $app_name = explode('@', $destination['control']); 112 | 113 | require_once('applications/' . $app_name[0] . '/' . $app_name[0] . '.php'); 114 | $application = ucfirst($app_name[0]) . 'Application'; 115 | $app = new $application(); 116 | $app->run($app_name[1], $destination['args']); 117 | } 118 | 119 | /** 120 | * take output from widget 121 | */ 122 | function widget_output($position = 'default') 123 | { 124 | if (!empty($this->widget_positions[$position])) { 125 | //gets all widgets in given 126 | $widgets = $this->widget_positions[$position]; 127 | 128 | //display each widget 129 | foreach ($widgets as $widget_object) { 130 | $widget_name = $widget_object->name; 131 | $widget_parameters = $widget_object->parameters; 132 | require_once('widgets/' . $widget_name . '/' . $widget_name . '.php'); 133 | $widget_class = ucfirst($widget_name) . 'Widget'; 134 | $widget = new $widget_class(); 135 | $widget->run($widget_name, $widget_parameters); 136 | } 137 | } 138 | } 139 | 140 | /** 141 | * regiseter widgets for theme 142 | */ 143 | function set_widget($position, $widget_name, $params = array()) 144 | { 145 | $widget = new StdClass; 146 | $widget->name = $widget_name; 147 | $widget->parameters = $params; 148 | //if there is no widget in position then create a new array 149 | if (empty($this->widget_positions[$position])) { 150 | $this->widget_positions[$position] = array($widget); 151 | } 152 | //if there is already a widget present in that position then just push new widget in array 153 | else { 154 | array_push($this->widget_positions[$position], $widget); 155 | } 156 | } 157 | 158 | /** 159 | * return header.php file from current template 160 | */ 161 | function get_header() 162 | { 163 | require_once(TEMPLATE_PATH . 'header.php'); 164 | } 165 | 166 | /** 167 | * return footer.php file from current template 168 | */ 169 | function get_footer() 170 | { 171 | require_once(TEMPLATE_PATH . 'footer.php'); 172 | } 173 | 174 | /** 175 | * return sidebar.php file from current template 176 | */ 177 | function get_sidebar() 178 | { 179 | require_once(TEMPLATE_PATH . 'sidebar.php'); 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /includes/Widget.php: -------------------------------------------------------------------------------- 1 | widget_path = 'widgets/' . $widget_name . '/'; 23 | $this->widget_name = $widget_name; 24 | } 25 | 26 | function get_widget_path() 27 | { 28 | return $this->widget_path; 29 | } 30 | 31 | abstract function display(); 32 | 33 | function run($widget_name = null, $params = null) // this function will be called by template function class to display widget 34 | { 35 | $this->parameters = $params; 36 | $this->set_widget_path($widget_name); 37 | $this->display(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /includes/index.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/28harishkumar/phpcms/61b1e7afb41c24425352e7e70a5e2697026a0521/includes/index.php -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | get_current_template_path()); 55 | define('STATIC_PATH', $tmpl->get_static_path()); 56 | define('THEME', $tmpl->get_current_theme()); 57 | 58 | $tmpl->run(); 59 | -------------------------------------------------------------------------------- /libraries/core/database/index.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/28harishkumar/phpcms/61b1e7afb41c24425352e7e70a5e2697026a0521/libraries/core/database/index.php -------------------------------------------------------------------------------- /libraries/core/database/mysql_database.php: -------------------------------------------------------------------------------- 1 | db_server = $server; 40 | $this->db_name = $db; 41 | $this->db_user = $user; 42 | $this->db_pass = $pass; 43 | } 44 | 45 | /** 46 | * connecting with a mysql database 47 | */ 48 | private function connect() 49 | { 50 | $info = 'mysql:host=' . $this->db_server . ';dbname=' . $this->db_name; 51 | try { 52 | $this->con = new PDO($info, $this->db_user, $this->db_pass); //data server connection 53 | } catch (PDOException $Exception) { 54 | header('HTTP/1.1 500 Database Error'); 55 | exit; 56 | } 57 | 58 | 59 | if (!$this->con) { 60 | die('Could not connect: ' . mysql_error()); 61 | } 62 | } 63 | 64 | /** 65 | * disconnecting database connection 66 | */ 67 | private function disconnect() 68 | { 69 | $this->con = null; 70 | } 71 | 72 | /** 73 | * quoting string 74 | * @param string $args 75 | * @return sting $args 76 | */ 77 | function quote($arg) 78 | { 79 | $this->connect(); 80 | $arg = $this->con->quote($arg); 81 | $this->disconnect(); 82 | return $arg; 83 | } 84 | 85 | /** 86 | * prepare statement for single fetch 87 | * @param string $sql 88 | * @param array $args 89 | * @return query $q 90 | */ 91 | function prepare($sql, $args) 92 | { 93 | $this->connect(); 94 | $q = $this->con->prepare($sql); 95 | $q->execute($args); 96 | $this->disconnect(); 97 | return $q; 98 | } 99 | 100 | /** 101 | * Return array of results 102 | * @param string $sql 103 | * @param array $args 104 | * @return query array $rows 105 | */ 106 | function load_result($sql, $args) 107 | { 108 | $this->connect(); 109 | $q = $this->con->prepare($sql); 110 | $q->execute($args); 111 | $rows = $q->fetchAll(); 112 | $this->disconnect(); 113 | return $rows; 114 | } 115 | 116 | /** 117 | * Return single result 118 | * @param string $sql 119 | * @param array $args 120 | * @return query $row 121 | */ 122 | function load_single_result($sql, $args) 123 | { 124 | $this->connect(); 125 | $q = $this->con->prepare($sql); 126 | $q->execute($args); 127 | $row = $q->fetch(); 128 | $this->disconnect(); 129 | return $row; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /libraries/core/http/index.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/28harishkumar/phpcms/61b1e7afb41c24425352e7e70a5e2697026a0521/libraries/core/http/index.php -------------------------------------------------------------------------------- /libraries/core/http/routes.php: -------------------------------------------------------------------------------- 1 | $control) { 30 | $this->routes[$regex] = $control; 31 | } 32 | } 33 | } 34 | 35 | /** 36 | * get requested url 37 | * @return string $url 38 | */ 39 | private function get_url() 40 | { 41 | $trimed = trim(explode('\?', $_SERVER['REQUEST_URI'])[0], '/'); 42 | $url = explode('/', $trimed); 43 | 44 | $number_of_folders = count(explode('/', ROOT)) - 3; 45 | for ($i = 0; $i < $number_of_folders; $i++) { 46 | array_shift($url); 47 | } 48 | 49 | $url = join("/", $url); 50 | return $url; 51 | } 52 | 53 | /** 54 | * filter parameters from url's regex 55 | * @param string $regex 56 | * @return array (string $regex) (array $args) (array $arg_pos) 57 | */ 58 | private function filter_regex($regex) 59 | { 60 | $args = array(); 61 | $arg_pos = array(); 62 | $regex_array = explode('/', $regex); 63 | 64 | foreach ($regex_array as $pos => $r) { 65 | // if there is a dynamic parameter in url 66 | if (strpos($r, '{') !== false) { 67 | $perm = substr($r, strpos($r, '{') + 1, strpos($r, '}') - strpos($r, '{') - 1); 68 | array_push($args, $perm); 69 | array_push($arg_pos, $pos); 70 | $regex_array[$pos] = str_replace('{' . $perm . '}', '', $r); 71 | } 72 | } 73 | $regex = join('/', $regex_array); 74 | return ['regex' => $regex, 'args' => $args, 'arg_pos' => $arg_pos]; 75 | } 76 | 77 | /** 78 | * match current url with registered url regexes 79 | */ 80 | private function check_regex() 81 | { 82 | $url = $this->get_url(); 83 | foreach ($this->routes as $route => $url_meta) { 84 | // filter the regex string 85 | $filtered_regex = $this->filter_regex($route); 86 | $url_location = explode('?', $url)[0]; 87 | 88 | // matich regex 89 | preg_match('#^' . $filtered_regex['regex'] . '$#', $url_location, $matches, PREG_OFFSET_CAPTURE); 90 | if (!empty($matches)) { 91 | if (is_array($url_meta)) { 92 | $control = $url_meta['control']; 93 | if (array_search($_SERVER['REQUEST_METHOD'], $url_meta['allow']) === false) { 94 | return false; 95 | } 96 | } else { 97 | $control = $url_meta; 98 | } 99 | 100 | $args = array(); 101 | if (!empty($filtered_regex['args'])) { 102 | $url_split = explode('/', $url); 103 | $pos = 0; 104 | foreach ($filtered_regex['args'] as $arg) { 105 | $args[$arg] = $url_split[$filtered_regex['arg_pos'][$pos++]]; 106 | } 107 | } 108 | 109 | return ['control' => $control, 'args' => $args]; 110 | } 111 | } 112 | return false; 113 | } 114 | 115 | /** 116 | * find right app class and its funciton 117 | * @return array $destination 118 | */ 119 | function get_destination() 120 | { 121 | $destination = $this->check_regex(); 122 | if ($destination !== false) { 123 | return $destination; 124 | } 125 | header('HTTP/1.1 404 Page not found'); 126 | exit; 127 | } 128 | 129 | /** 130 | * map values to parameters in url regex 131 | */ 132 | private function map_url($regex, $args) 133 | { 134 | $regex_array = explode('/', $regex); 135 | foreach ($args as $k => $v) { 136 | $pos = 0; 137 | foreach ($regex_array as $r) { 138 | if (strpos($r, '{' . $k . '}') !== false) { 139 | $regex_array[$pos] = $v; 140 | } 141 | $pos++; 142 | } 143 | } 144 | return join($regex_array, '/'); 145 | } 146 | 147 | /** 148 | * return a named url 149 | * @return string url 150 | */ 151 | public function to_route($name, $args = null) 152 | { 153 | foreach ($this->routes as $regex => $meta) { 154 | if (is_array($meta)) { 155 | if ($name === $meta['name']) { 156 | if ($args !== null) { 157 | return ROOT . '/' . $this->map_url($regex, $args); 158 | } else { 159 | return ROOT . '/' . $regex; 160 | } 161 | } 162 | } 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /templates/default/403.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/28harishkumar/phpcms/61b1e7afb41c24425352e7e70a5e2697026a0521/templates/default/403.php -------------------------------------------------------------------------------- /templates/default/404.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/28harishkumar/phpcms/61b1e7afb41c24425352e7e70a5e2697026a0521/templates/default/404.php -------------------------------------------------------------------------------- /templates/default/500.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/28harishkumar/phpcms/61b1e7afb41c24425352e7e70a5e2697026a0521/templates/default/500.php -------------------------------------------------------------------------------- /templates/default/Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/28harishkumar/phpcms/61b1e7afb41c24425352e7e70a5e2697026a0521/templates/default/Screenshot.png -------------------------------------------------------------------------------- /templates/default/admin/index.php: -------------------------------------------------------------------------------- 1 | 5 |
6 | 12 |
-------------------------------------------------------------------------------- /templates/default/admin/themes.php: -------------------------------------------------------------------------------- 1 | 2 | 7 |

Currently active theme

8 |
9 |
10 |
11 | 12 |
13 | Theme Details 14 |

15 |
16 | Activated 17 |
18 |
19 |
20 | 21 |
22 |

All themes in store

23 | 26 |
27 |
28 | 29 |
30 |
31 | Theme Details 32 |

33 |
34 | 35 |
36 | 37 | 38 |
39 |
40 | 41 | 42 |
43 | 44 | Activated 45 | 46 |
47 |
48 |
49 | 52 |
-------------------------------------------------------------------------------- /templates/default/admin/user_edit.php: -------------------------------------------------------------------------------- 1 | 6 |
7 |
8 | 9 |
10 | 11 |
12 |
13 | 14 | 15 |
16 |
17 | 18 | 19 |
20 |
21 | 22 | 33 |
34 |
35 | 36 | > 39 |
40 |
41 | 42 |
43 |
44 |
-------------------------------------------------------------------------------- /templates/default/admin/users_list.php: -------------------------------------------------------------------------------- 1 | 7 |
8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | 25 | 30 | 37 | 38 | 40 | 41 |
EmailRoleIs ActiveActions
31 |
Edit
32 |
33 | 34 | Delete 35 |
36 |
42 |
43 |
-------------------------------------------------------------------------------- /templates/default/auth/auth.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
Log In
5 |
Forgot password?
6 |
7 | 8 |
9 | 10 |
11 |

Error:

12 | 14 |
15 | 16 |
17 | 18 |
19 | 20 | 21 |
22 | 23 |
24 | 25 | 26 |
27 | 28 |
29 | 30 |
31 | 32 |
33 |
34 |
35 |
36 |
37 | Don't have an account! 38 | 39 | Sign Up Here 40 | 41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | 96 | 97 | 128 | -------------------------------------------------------------------------------- /templates/default/auth/message.php: -------------------------------------------------------------------------------- 1 |
2 |

3 |

4 |

Go Back to home

5 |
-------------------------------------------------------------------------------- /templates/default/auth/resetpassword.php: -------------------------------------------------------------------------------- 1 | 7 |
8 |
9 |
10 |
Reset Password
11 |
12 |
13 |
14 | 15 |
16 |

Error:

17 | 18 |
19 | 20 | > 21 | > 22 | 23 |
24 | 25 |
26 | 27 |
28 |
29 | 30 |
31 | 32 |
33 | 34 |
35 |
36 | 37 |
38 | 39 |
40 | 41 |
42 |
43 |
44 |
45 |
46 |
-------------------------------------------------------------------------------- /templates/default/css/style.css: -------------------------------------------------------------------------------- 1 | *{margin:0;padding:0;} 2 | 3 | body{ 4 | 5 | } 6 | 7 | .right{ 8 | float: right; 9 | } 10 | 11 | .left{ 12 | float: left; 13 | } 14 | 15 | .clear{ 16 | padding: 10px 0; 17 | width:100%; 18 | } 19 | 20 | .delete-form{ 21 | float: left; 22 | } 23 | 24 | .header, .header a{ 25 | background-color:#345234; 26 | color:white; 27 | font-weight:bold; 28 | font-size:55px; 29 | padding:15px 10px; 30 | font-family: cursive; 31 | text-decoration: none; 32 | } 33 | 34 | .content{ 35 | float: right; 36 | padding: 5px; 37 | min-height: 500px; 38 | } 39 | 40 | .sidebar{ 41 | float:left; 42 | min-width: 179px; 43 | box-shadow: 5px 5px 5px #523454; 44 | overflow:hidden; 45 | } 46 | 47 | .footer{ 48 | text-align: center; 49 | background: #345234; 50 | color: white; 51 | padding: 21px 3px; 52 | } 53 | .clear{clear:both;} 54 | 55 | .credit-link{ 56 | color:#FFF; 57 | font-size:20px; 58 | } 59 | 60 | 61 | /** 62 | * css for responsive table 63 | * 64 | */ 65 | 66 | @media only screen and (max-width: 800px) { 67 | 68 | 69 | /* Force table to not be like tables anymore */ 70 | #no-more-tables table, 71 | #no-more-tables thead, 72 | #no-more-tables tbody, 73 | #no-more-tables th, 74 | #no-more-tables td, 75 | #no-more-tables tr { 76 | display: block; 77 | } 78 | 79 | /* Hide table headers (but not display: none;, for accessibility) */ 80 | #no-more-tables thead tr { 81 | position: absolute; 82 | top: -9999px; 83 | left: -9999px; 84 | } 85 | 86 | #no-more-tables tr { border: 1px solid #ccc; overflow: hidden;} 87 | 88 | #no-more-tables td { 89 | /* Behave like a "row" */ 90 | border: none; 91 | border-bottom: 1px solid #eee; 92 | position: relative; 93 | padding-left: 50%; 94 | white-space: normal; 95 | text-align:left; 96 | } 97 | 98 | #no-more-tables td:before { 99 | /* Now like a table header */ 100 | position: absolute; 101 | /* Top/left values mimic padding */ 102 | top: 6px; 103 | left: 6px; 104 | width: 45%; 105 | padding-right: 10px; 106 | white-space: nowrap; 107 | text-align:left; 108 | font-weight: bold; 109 | } 110 | 111 | /* 112 | Label the data 113 | */ 114 | #no-more-tables td:before { content: attr(data-title); } 115 | } 116 | 117 | @media only screen and (max-width: 768px) { 118 | .sidebar{ 119 | float: none; 120 | } 121 | } -------------------------------------------------------------------------------- /templates/default/css/theme-list.css: -------------------------------------------------------------------------------- 1 | .left{ 2 | float: left; 3 | } 4 | .themes{ 5 | border: none; 6 | } 7 | 8 | .theme{ 9 | cursor: pointer; 10 | position: relative; 11 | } 12 | 13 | .theme .theme-screenshot { 14 | display: block; 15 | overflow: hidden; 16 | position: relative; 17 | } 18 | 19 | .theme .more-details { 20 | -ms-filter: "alpha(Opacity=0)"; 21 | opacity: 0; 22 | position: absolute; 23 | top: 35%; 24 | right: 25%; 25 | left: 25%; 26 | background: #222; 27 | background: rgba(0,0,0,.7); 28 | color: #fff; 29 | font-size: 15px; 30 | text-shadow: 0 1px 0 rgba(0,0,0,.6); 31 | -webkit-font-smoothing: antialiased; 32 | font-weight: 600; 33 | padding: 15px 12px; 34 | text-align: center; 35 | -webkit-border-radius: 3px; 36 | border-radius: 3px; 37 | -webkit-transition: opacity .1s ease-in-out; 38 | transition: opacity .1s ease-in-out; 39 | } 40 | 41 | .theme .theme-author { 42 | background: #222; 43 | color: #eee; 44 | display: none; 45 | font-size: 14px; 46 | margin: 0 10px; 47 | padding: 5px 10px; 48 | position: absolute; 49 | bottom: 56px; 50 | } 51 | 52 | .theme .theme-name { 53 | font-size: 15px; 54 | font-weight: 600; 55 | margin: 0; 56 | padding: 15px; 57 | float: left; 58 | -webkit-box-shadow: inset 0 1px 0 rgba(0,0,0,.1); 59 | box-shadow: inset 0 1px 0 rgba(0,0,0,.1); 60 | overflow: hidden; 61 | white-space: nowrap; 62 | text-overflow: ellipsis; 63 | background: #fff; 64 | background: rgba(255,255,255,.65); 65 | } 66 | 67 | .theme .theme-actions { 68 | -ms-filter: "alpha(Opacity=0)"; 69 | opacity: 0; 70 | -webkit-transition: opacity .1s ease-in-out; 71 | transition: opacity .1s ease-in-out; 72 | float: right; 73 | padding: 10px; 74 | background: rgba(244,244,244,.7); 75 | border-left: 1px solid rgba(0,0,0,.05); 76 | } 77 | 78 | .theme .theme-actions form{ 79 | float: left; 80 | padding: 0 5px; 81 | } 82 | 83 | .theme:hover .theme-screenshot{ 84 | opacity: 0.5; 85 | } 86 | 87 | .theme:hover .more-details{ 88 | opacity: 1; 89 | } 90 | 91 | .theme:hover .theme-author{ 92 | display: block; 93 | } 94 | 95 | .theme:hover .theme-actions{ 96 | opacity: 1; 97 | } 98 | 99 | @media screen and (max-width: 768px) { 100 | 101 | .theme:hover .theme-screenshot{ 102 | opacity: 1; 103 | } 104 | 105 | .theme:focus .theme-screenshot{ 106 | opacity: 1; 107 | } 108 | 109 | .theme:focus .theme-screenshot{ 110 | opacity: 0.5; 111 | } 112 | 113 | .theme .more-details{ 114 | font-size: 12px; 115 | display: none; 116 | } 117 | 118 | .theme:hover .more-details{ 119 | opacity: 0; 120 | } 121 | 122 | .theme:focus .more-details{ 123 | display: block; 124 | opacity: 1; 125 | } 126 | 127 | .theme-actions{ 128 | display: none; 129 | float: left; 130 | } 131 | 132 | .theme:hover .theme-actions{ 133 | opacity: 0; 134 | } 135 | 136 | .theme:focus .theme-actions{ 137 | display: block; 138 | opacity: 1; 139 | float: left; 140 | } 141 | } -------------------------------------------------------------------------------- /templates/default/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/28harishkumar/phpcms/61b1e7afb41c24425352e7e70a5e2697026a0521/templates/default/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /templates/default/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/28harishkumar/phpcms/61b1e7afb41c24425352e7e70a5e2697026a0521/templates/default/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /templates/default/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/28harishkumar/phpcms/61b1e7afb41c24425352e7e70a5e2697026a0521/templates/default/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /templates/default/footer.php: -------------------------------------------------------------------------------- 1 | 4 | 5 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /templates/default/functions.php: -------------------------------------------------------------------------------- 1 | set_widget('logo_position', 'logo'); 13 | $this->set_widget('sidebar_position', 'sidemenu'); 14 | $this->set_widget('sidebar_position', 'sidemenu2'); 15 | -------------------------------------------------------------------------------- /templates/default/header.php: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 16 | 17 | MyCMS from screech 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 33 |
-------------------------------------------------------------------------------- /templates/default/index.php: -------------------------------------------------------------------------------- 1 | get_header(); ?> 2 |
3 | app_output(); ?> 4 |
5 | 6 |
7 |
8 | get_footer(); ?> -------------------------------------------------------------------------------- /templates/default/js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.2.0 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.2.0",d.prototype.close=function(b){function c(){f.detach().trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",c).emulateTransitionEnd(150):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.2.0",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),d[e](null==f[b]?this.options[b]:f[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b).on("keydown.bs.carousel",a.proxy(this.keydown,this)),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.2.0",c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},c.prototype.keydown=function(a){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.to=function(b){var c=this,d=this.getItemIndex(this.$active=this.$element.find(".item.active"));return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=e[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:g});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,f&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(e)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:g});return a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one("bsTransitionEnd",function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger(m)),f&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b);!e&&f.toggle&&"show"==b&&(b=!b),e||d.data("bs.collapse",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};c.VERSION="3.2.0",c.DEFAULTS={toggle:!0},c.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},c.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var c=a.Event("show.bs.collapse");if(this.$element.trigger(c),!c.isDefaultPrevented()){var d=this.$parent&&this.$parent.find("> .panel > .in");if(d&&d.length){var e=d.data("bs.collapse");if(e&&e.transitioning)return;b.call(d,"hide"),e||d.data("bs.collapse",null)}var f=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[f](0),this.transitioning=1;var g=function(){this.$element.removeClass("collapsing").addClass("collapse in")[f](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return g.call(this);var h=a.camelCase(["scroll",f].join("-"));this.$element.one("bsTransitionEnd",a.proxy(g,this)).emulateTransitionEnd(350)[f](this.$element[0][h])}}},c.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},c.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var d=a.fn.collapse;a.fn.collapse=b,a.fn.collapse.Constructor=c,a.fn.collapse.noConflict=function(){return a.fn.collapse=d,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(c){var d,e=a(this),f=e.attr("data-target")||c.preventDefault()||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),g=a(f),h=g.data("bs.collapse"),i=h?"toggle":e.data(),j=e.attr("data-parent"),k=j&&a(j);h&&h.transitioning||(k&&k.find('[data-toggle="collapse"][data-parent="'+j+'"]').not(e).addClass("collapsed"),e[g.hasClass("in")?"addClass":"removeClass"]("collapsed")),b.call(g,i)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.2.0",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(' 5 | 6 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /templates/fixed_top/functions.php: -------------------------------------------------------------------------------- 1 | set_widget('nav_position', 'nav'); 13 | $this->set_widget('logo_position', 'logo'); 14 | -------------------------------------------------------------------------------- /templates/fixed_top/header.php: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 16 | 17 | MyCMS from screech 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 50 |
51 |
-------------------------------------------------------------------------------- /templates/fixed_top/index.php: -------------------------------------------------------------------------------- 1 | get_header(); 2 | if (isset($_SESSION['error'])) { 3 | echo ""; 4 | unset($_SESSION['error']); 5 | } 6 | if (isset($_SESSION['message'])) { 7 | echo ""; 8 | unset($_SESSION['message']); 9 | } 10 | if (isset($_SESSION['success'])) { 11 | echo ""; 12 | unset($_SESSION['success']); 13 | } 14 | ?> 15 |
16 | app_output(); ?> 17 |
18 |
19 |
20 | get_footer(); ?> -------------------------------------------------------------------------------- /templates/fixed_top/js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.2.0 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.2.0",d.prototype.close=function(b){function c(){f.detach().trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",c).emulateTransitionEnd(150):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.2.0",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),d[e](null==f[b]?this.options[b]:f[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b).on("keydown.bs.carousel",a.proxy(this.keydown,this)),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.2.0",c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},c.prototype.keydown=function(a){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.to=function(b){var c=this,d=this.getItemIndex(this.$active=this.$element.find(".item.active"));return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=e[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:g});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,f&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(e)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:g});return a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one("bsTransitionEnd",function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger(m)),f&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b);!e&&f.toggle&&"show"==b&&(b=!b),e||d.data("bs.collapse",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};c.VERSION="3.2.0",c.DEFAULTS={toggle:!0},c.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},c.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var c=a.Event("show.bs.collapse");if(this.$element.trigger(c),!c.isDefaultPrevented()){var d=this.$parent&&this.$parent.find("> .panel > .in");if(d&&d.length){var e=d.data("bs.collapse");if(e&&e.transitioning)return;b.call(d,"hide"),e||d.data("bs.collapse",null)}var f=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[f](0),this.transitioning=1;var g=function(){this.$element.removeClass("collapsing").addClass("collapse in")[f](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return g.call(this);var h=a.camelCase(["scroll",f].join("-"));this.$element.one("bsTransitionEnd",a.proxy(g,this)).emulateTransitionEnd(350)[f](this.$element[0][h])}}},c.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},c.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var d=a.fn.collapse;a.fn.collapse=b,a.fn.collapse.Constructor=c,a.fn.collapse.noConflict=function(){return a.fn.collapse=d,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(c){var d,e=a(this),f=e.attr("data-target")||c.preventDefault()||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),g=a(f),h=g.data("bs.collapse"),i=h?"toggle":e.data(),j=e.attr("data-parent"),k=j&&a(j);h&&h.transitioning||(k&&k.find('[data-toggle="collapse"][data-parent="'+j+'"]').not(e).addClass("collapsed"),e[g.hasClass("in")?"addClass":"removeClass"]("collapsed")),b.call(g,i)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.2.0",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('