├── content └── index.php ├── install ├── config │ ├── database.php │ ├── error.php │ ├── session.php │ ├── app.php │ ├── aliases.php │ └── strings.php ├── .htaccess ├── views │ ├── assets │ │ └── img │ │ │ └── logo.png │ ├── partials │ │ ├── footer.php │ │ └── header.php │ ├── halt.php │ ├── complete.php │ ├── error │ │ ├── 404.php │ │ └── 500.php │ ├── account.php │ ├── start.php │ ├── database.php │ └── metadata.php ├── readme.md ├── storage │ ├── application.distro.php │ ├── session.distro.php │ ├── database.distro.php │ └── htaccess.distro ├── libraries │ ├── layout.php │ └── braces.php └── index.php ├── anchor ├── language │ └── en_GB │ │ ├── menu.php │ │ ├── categories.php │ │ ├── comments.php │ │ ├── pages.php │ │ ├── posts.php │ │ ├── metadata.php │ │ ├── global.php │ │ ├── users.php │ │ └── extend.php ├── config │ ├── error.php │ ├── migrations.php │ └── aliases.php ├── views │ ├── assets │ │ ├── img │ │ │ ├── cloud.png │ │ │ ├── cross.gif │ │ │ ├── icons.png │ │ │ ├── logo.png │ │ │ ├── piggy.gif │ │ │ ├── tick.gif │ │ │ ├── tick.png │ │ │ ├── favicon.ico │ │ │ └── statuses.png │ │ ├── js │ │ │ ├── page-name.js │ │ │ ├── upload-fields.js │ │ │ ├── custom-fields.js │ │ │ ├── redirect.js │ │ │ ├── text-resize.js │ │ │ ├── slug.js │ │ │ ├── focus-mode.js │ │ │ ├── sortable.js │ │ │ └── dragdrop.js │ │ └── css │ │ │ ├── reset.css │ │ │ ├── small.css │ │ │ ├── login.css │ │ │ └── notifications.css │ ├── posts │ │ ├── add.php │ │ ├── edit.php │ │ └── index.php │ ├── extend │ │ ├── plugins │ │ │ └── index.php │ │ ├── variables │ │ │ ├── index.php │ │ │ ├── add.php │ │ │ └── edit.php │ │ ├── fields │ │ │ ├── index.php │ │ │ └── add.php │ │ └── index.php │ ├── partials │ │ ├── editor.php │ │ ├── footer.php │ │ └── header.php │ ├── profile.php │ ├── users │ │ ├── reset.php │ │ ├── amnesia.php │ │ ├── index.php │ │ ├── login.php │ │ ├── add.php │ │ └── edit.php │ ├── categories │ │ ├── index.php │ │ ├── add.php │ │ └── edit.php │ ├── menu │ │ └── index.php │ ├── error │ │ ├── 404.php │ │ └── 500.php │ ├── comments │ │ ├── index.php │ │ └── edit.php │ ├── upgrade.php │ ├── intro.php │ └── pages │ │ └── index.php ├── functions │ ├── metadata.php │ ├── config.php │ ├── users.php │ ├── pages.php │ ├── categories.php │ ├── posts.php │ ├── helpers.php │ ├── menus.php │ ├── search.php │ └── comments.php ├── migrations │ ├── 80_drop_sessions_ip.php │ ├── 81_drop_sessions_ua.php │ ├── 120_add_page_parent.php │ ├── 140_add_page_menu_order.php │ ├── 21_alter_comments_date.php │ ├── 60_drop_posts_custom_fields.php │ ├── 130_pages_show_in_menu.php │ ├── 110_alter_session_date.php │ ├── 62_add_posts_category.php │ ├── 61_alter_posts_created.php │ ├── 90_alter_users_password.php │ ├── 20_alter_comments_status.php │ ├── 10_add_comment_notifications.php │ ├── 11_add_comment_moderation_keys.php │ ├── 71_insert_default_categories.php │ ├── 70_create_categories_table.php │ ├── 40_create_page_meta_table.php │ ├── 50_create_post_meta_table.php │ └── 30_create_extend_table.php ├── libraries │ ├── response.php │ ├── csrf.php │ ├── registry.php │ ├── date.php │ ├── items.php │ ├── hash.php │ ├── template.php │ ├── auth.php │ ├── events.php │ ├── json.php │ ├── migration.php │ ├── notify.php │ ├── language.php │ ├── html.php │ ├── migrations.php │ ├── themes.php │ ├── update.php │ ├── paginator.php │ ├── rss.php │ └── validator.php ├── routes │ ├── plugins.php │ ├── menu.php │ └── metadata.php ├── models │ ├── base.php │ ├── user.php │ ├── category.php │ ├── page.php │ ├── post.php │ └── comment.php ├── run.php └── helpers.php ├── themes └── default │ ├── img │ ├── favicon.png │ ├── og_image.gif │ ├── search.png │ └── categories.png │ ├── about.txt │ ├── page.php │ ├── 404.php │ ├── css │ ├── small.css │ └── reset.css │ ├── footer.php │ ├── search.php │ ├── posts.php │ ├── functions.php │ ├── js │ └── main.js │ └── article.php ├── composer.json ├── system ├── session │ ├── drivers │ │ ├── runtime.php │ │ ├── memcache.php │ │ ├── memcached.php │ │ ├── cookie.php │ │ └── database.php │ └── driver.php ├── start.php ├── request.php ├── database │ ├── connectors │ │ ├── sqlite.php │ │ └── mysql.php │ └── connector.php ├── request │ └── server.php ├── autoloader.php ├── cookie.php ├── boot.php ├── view.php ├── database.php ├── input.php ├── config.php ├── session.php ├── arr.php └── error.php ├── .gitignore ├── index.php └── readme.md /content/index.php: -------------------------------------------------------------------------------- 1 | 2 | SetEnv HTTP_MOD_REWRITE On 3 | -------------------------------------------------------------------------------- /anchor/language/en_GB/menu.php: -------------------------------------------------------------------------------- 1 | 'Menu', 6 | 7 | ); -------------------------------------------------------------------------------- /themes/default/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drFabio/anchor-cms/master/themes/default/img/favicon.png -------------------------------------------------------------------------------- /themes/default/img/og_image.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drFabio/anchor-cms/master/themes/default/img/og_image.gif -------------------------------------------------------------------------------- /themes/default/img/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drFabio/anchor-cms/master/themes/default/img/search.png -------------------------------------------------------------------------------- /anchor/config/error.php: -------------------------------------------------------------------------------- 1 | true, 5 | 'logger' => function($exception) {} 6 | ); -------------------------------------------------------------------------------- /anchor/views/assets/img/cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drFabio/anchor-cms/master/anchor/views/assets/img/cloud.png -------------------------------------------------------------------------------- /anchor/views/assets/img/cross.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drFabio/anchor-cms/master/anchor/views/assets/img/cross.gif -------------------------------------------------------------------------------- /anchor/views/assets/img/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drFabio/anchor-cms/master/anchor/views/assets/img/icons.png -------------------------------------------------------------------------------- /anchor/views/assets/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drFabio/anchor-cms/master/anchor/views/assets/img/logo.png -------------------------------------------------------------------------------- /anchor/views/assets/img/piggy.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drFabio/anchor-cms/master/anchor/views/assets/img/piggy.gif -------------------------------------------------------------------------------- /anchor/views/assets/img/tick.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drFabio/anchor-cms/master/anchor/views/assets/img/tick.gif -------------------------------------------------------------------------------- /anchor/views/assets/img/tick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drFabio/anchor-cms/master/anchor/views/assets/img/tick.png -------------------------------------------------------------------------------- /install/config/error.php: -------------------------------------------------------------------------------- 1 | true, 5 | 'logger' => function($exception) {} 6 | ); -------------------------------------------------------------------------------- /install/views/assets/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drFabio/anchor-cms/master/install/views/assets/img/logo.png -------------------------------------------------------------------------------- /themes/default/img/categories.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drFabio/anchor-cms/master/themes/default/img/categories.png -------------------------------------------------------------------------------- /anchor/config/migrations.php: -------------------------------------------------------------------------------- 1 | 140 8 | ); -------------------------------------------------------------------------------- /anchor/views/assets/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drFabio/anchor-cms/master/anchor/views/assets/img/favicon.ico -------------------------------------------------------------------------------- /anchor/views/assets/img/statuses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drFabio/anchor-cms/master/anchor/views/assets/img/statuses.png -------------------------------------------------------------------------------- /install/readme.md: -------------------------------------------------------------------------------- 1 | ## Installing Anchor CMS 2 | 3 | [It's on our site!](http://anchorcms.com/docs/getting-started/installing). -------------------------------------------------------------------------------- /anchor/views/posts/add.php: -------------------------------------------------------------------------------- 1 | vars; 3 | $vars['uri']= Uri::to('admin/posts/add'); 4 | echo View::create('posts/_form',$vars)->render(); 5 | ?> -------------------------------------------------------------------------------- /anchor/views/posts/edit.php: -------------------------------------------------------------------------------- 1 | vars; 3 | $vars['uri']= Uri::to('admin/posts/edit/' . $article->id); 4 | $vars['isEdit']=true; 5 | echo View::create('posts/_form',$vars)->render(); 6 | ?> -------------------------------------------------------------------------------- /install/views/partials/footer.php: -------------------------------------------------------------------------------- 1 | 2 | You’re installing Anchor version . 3 | Need help? 4 | 5 | 6 | -------------------------------------------------------------------------------- /themes/default/about.txt: -------------------------------------------------------------------------------- 1 | Theme name: Default 2 | Description: This is the default, shiny theme for Anchor CMS. 3 | Author name: Visual Idiot 4 | Author site: http://visualidiot.com 5 | License: http://licence.visualidiot.com -------------------------------------------------------------------------------- /themes/default/page.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

5 | 6 | 7 |
8 | 9 | -------------------------------------------------------------------------------- /install/storage/application.distro.php: -------------------------------------------------------------------------------- 1 | '{{url}}', 5 | 'index' => '{{index}}', 6 | 'timezone' => '{{timezone}}', 7 | 'key' => '{{key}}', 8 | 'language' => '{{language}}', 9 | 'encoding' => 'UTF-8' 10 | ); -------------------------------------------------------------------------------- /install/config/session.php: -------------------------------------------------------------------------------- 1 | 'cookie', 5 | 'cookie' => 'anchorcms-install', 6 | 'table' => 'sessions', 7 | 'lifetime' => 14400, 8 | 'expire_on_close' => true, 9 | 'path' => '/', 10 | 'domain' => '', 11 | 'secure' => false 12 | ); -------------------------------------------------------------------------------- /install/config/app.php: -------------------------------------------------------------------------------- 1 | dirname($_SERVER['SCRIPT_NAME']), 5 | 'index' => 'index.php?route=', 6 | 'timezone' => 'UTC', 7 | 'key' => hash('md5', 'Anchor Installer ' . VERSION), 8 | 'language' => 'en_GB', 9 | 'encoding' => 'UTF-8' 10 | ); -------------------------------------------------------------------------------- /install/storage/session.distro.php: -------------------------------------------------------------------------------- 1 | 'database', 5 | 'cookie' => 'anchorcms', 6 | 'table' => '{{table}}', 7 | 'lifetime' => 86400, 8 | 'expire_on_close' => false, 9 | 'path' => '/', 10 | 'domain' => '', 11 | 'secure' => false 12 | ); -------------------------------------------------------------------------------- /install/libraries/layout.php: -------------------------------------------------------------------------------- 1 | partial('header', 'partials/header', $vars) 8 | ->partial('footer', 'partials/footer', $vars); 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /anchor/views/extend/plugins/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

Plugins

5 |
6 | 7 |
8 | 9 | 10 |

11 | Soon. 12 |

13 |
14 | 15 | -------------------------------------------------------------------------------- /anchor/views/partials/editor.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /anchor/functions/metadata.php: -------------------------------------------------------------------------------- 1 | has_table_column($table, 'ip')) { 9 | $sql = 'ALTER TABLE `' . $table . '` DROP `ip`'; 10 | DB::ask($sql); 11 | } 12 | } 13 | 14 | public function down() {} 15 | 16 | } -------------------------------------------------------------------------------- /anchor/migrations/81_drop_sessions_ua.php: -------------------------------------------------------------------------------- 1 | has_table_column($table, 'ua')) { 9 | $sql = 'ALTER TABLE `' . $table . '` DROP `ua`'; 10 | DB::ask($sql); 11 | } 12 | } 13 | 14 | public function down() {} 15 | 16 | } -------------------------------------------------------------------------------- /anchor/views/profile.php: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 | 6 |

7 | 8 | 9 |

10 |

11 |
12 | -------------------------------------------------------------------------------- /anchor/libraries/response.php: -------------------------------------------------------------------------------- 1 | DB::profile()))->render(); 8 | 9 | $this->output = preg_replace('##', $profile . '', $this->output); 10 | } 11 | 12 | return parent::send(); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "anchorcms/anchor-cms", 3 | "authors": [ 4 | { 5 | "name": "Idiot", 6 | "email": "iam@visualidiot.com" 7 | }, 8 | { 9 | "name": "Kieron", 10 | "email": "rwarasaurus@gmail.com" 11 | } 12 | ], 13 | "require": { 14 | "php": ">=5.3.6" 15 | }, 16 | "extra": { 17 | "installer-paths": { 18 | "anchor/vendor/{$name}": ["vendor/package"] 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /anchor/migrations/120_add_page_parent.php: -------------------------------------------------------------------------------- 1 | has_table_column($table, 'parent')) { 9 | $sql = 'ALTER TABLE `' . $table . '` ADD `parent` int(6) NOT NULL AFTER `id`'; 10 | DB::ask($sql); 11 | } 12 | } 13 | 14 | public function down() {} 15 | 16 | } -------------------------------------------------------------------------------- /anchor/migrations/140_add_page_menu_order.php: -------------------------------------------------------------------------------- 1 | has_table_column($table, 'menu_order')) { 9 | $sql = 'ALTER TABLE `' . $table . '` ADD `menu_order` int(4) NOT NULL'; 10 | DB::ask($sql); 11 | } 12 | } 13 | 14 | public function down() {} 15 | 16 | } -------------------------------------------------------------------------------- /anchor/migrations/21_alter_comments_date.php: -------------------------------------------------------------------------------- 1 | has_table($table)) { 9 | $sql = 'ALTER TABLE `' . $table . '` CHANGE `date` `date` datetime NOT NULL AFTER `status`'; 10 | DB::ask($sql); 11 | } 12 | } 13 | 14 | public function down() {} 15 | 16 | } -------------------------------------------------------------------------------- /anchor/migrations/60_drop_posts_custom_fields.php: -------------------------------------------------------------------------------- 1 | has_table_column($table, 'custom_fields')) { 9 | $sql = 'ALTER TABLE `' . $table . '` DROP `custom_fields`'; 10 | DB::ask($sql); 11 | } 12 | } 13 | 14 | public function down() {} 15 | 16 | } -------------------------------------------------------------------------------- /anchor/migrations/130_pages_show_in_menu.php: -------------------------------------------------------------------------------- 1 | has_table_column($table, 'show_in_menu')) { 9 | $sql = 'ALTER TABLE `' . $table . '` ADD `show_in_menu` tinyint(1) NOT NULL'; 10 | DB::ask($sql); 11 | } 12 | } 13 | 14 | public function down() {} 15 | 16 | } -------------------------------------------------------------------------------- /anchor/migrations/110_alter_session_date.php: -------------------------------------------------------------------------------- 1 | has_table_column($table, 'date')) { 9 | $sql = 'ALTER TABLE `' . $table . '` CHANGE `date` `expire` int(10) NOT NULL AFTER `id`'; 10 | DB::ask($sql); 11 | } 12 | } 13 | 14 | public function down() {} 15 | 16 | } -------------------------------------------------------------------------------- /anchor/migrations/62_add_posts_category.php: -------------------------------------------------------------------------------- 1 | has_table_column($table, 'category')) { 9 | $sql = 'ALTER TABLE `' . $table . '` ADD `category` int(6) NOT NULL AFTER `author`'; 10 | DB::query($sql); 11 | } 12 | } 13 | 14 | public function down() {} 15 | 16 | } -------------------------------------------------------------------------------- /install/storage/database.distro.php: -------------------------------------------------------------------------------- 1 | 'mysql', 5 | 'prefix' => '{{prefix}}', 6 | 'connections' => array( 7 | 'mysql' => array( 8 | 'driver' => 'mysql', 9 | 'hostname' => '{{hostname}}', 10 | 'port' => {{port}}, 11 | 'username' => '{{username}}', 12 | 'password' => '{{password}}', 13 | 'database' => '{{database}}', 14 | 'charset' => 'utf8' 15 | ) 16 | ) 17 | ); -------------------------------------------------------------------------------- /anchor/migrations/61_alter_posts_created.php: -------------------------------------------------------------------------------- 1 | has_table_column($table, 'created')) { 9 | $sql = 'ALTER TABLE `' . $table . '` CHANGE `created` `created` datetime NOT NULL AFTER `js`'; 10 | DB::ask($sql); 11 | } 12 | } 13 | 14 | public function down() {} 15 | 16 | } -------------------------------------------------------------------------------- /anchor/migrations/90_alter_users_password.php: -------------------------------------------------------------------------------- 1 | has_table_column($table, 'password')) { 9 | $sql = 'ALTER TABLE `' . $table . '` CHANGE `password` `password` text NOT NULL AFTER `username`'; 10 | DB::ask($sql); 11 | } 12 | } 13 | 14 | public function down() {} 15 | 16 | } -------------------------------------------------------------------------------- /system/session/drivers/runtime.php: -------------------------------------------------------------------------------- 1 | has_table($table)) { 9 | $sql = 'ALTER TABLE `' . $table . '` CHANGE `status` `status` enum(\'pending\',\'approved\',\'spam\') NOT NULL AFTER `post`'; 10 | DB::ask($sql); 11 | } 12 | } 13 | 14 | public function down() {} 15 | 16 | } -------------------------------------------------------------------------------- /anchor/views/assets/js/upload-fields.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Populate placeholder when user selects a file to upload 3 | */ 4 | $(function() { 5 | var basename = function(path) { 6 | return path.replace(/\\/g,'/').replace(/.*\//, ''); 7 | }; 8 | 9 | $('input[type=file]').bind('change', function() { 10 | var input = $(this), placeholder = input.parent().parent().find('.current-file'); 11 | 12 | placeholder.html(basename(input.val())); 13 | }); 14 | }); -------------------------------------------------------------------------------- /anchor/routes/plugins.php: -------------------------------------------------------------------------------- 1 | 'auth,csrf'), function() { 4 | 5 | /* 6 | List all plugins 7 | */ 8 | Route::get('admin/extend/plugins', function($page = 1) { 9 | $vars['messages'] = Notify::read(); 10 | $vars['token'] = Csrf::token(); 11 | 12 | return View::create('extend/plugins/index', $vars) 13 | ->partial('header', 'partials/header') 14 | ->partial('footer', 'partials/footer'); 15 | }); 16 | 17 | }); -------------------------------------------------------------------------------- /themes/default/404.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

Page not found

5 | 6 |

Unfortunately, the page / could not be found. Your best bet is either to try the homepage, try searching, or go and cry in a corner (although I don’t recommend the latter).

7 |
8 | 9 | -------------------------------------------------------------------------------- /anchor/views/partials/footer.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /install/storage/htaccess.distro: -------------------------------------------------------------------------------- 1 | Options -indexes 2 | 3 | 4 | RewriteEngine On 5 | RewriteBase {{base}} 6 | 7 | # Allow any files or directories that exist to be displayed directly 8 | RewriteCond %{REQUEST_FILENAME} !-f 9 | RewriteCond %{REQUEST_FILENAME} !-d 10 | 11 | # Rewrite all other URLs to index.php/URL 12 | RewriteRule ^(.*)$ {{index}} [L] 13 | 14 | 15 | 16 | ErrorDocument 404 index.php 17 | 18 | -------------------------------------------------------------------------------- /anchor/views/assets/css/reset.css: -------------------------------------------------------------------------------- 1 | 2 | * { 3 | margin: 0; 4 | padding: 0; 5 | 6 | -webkit-font-smoothing: antialiased; 7 | 8 | -webkit-box-sizing: border-box; 9 | -moz-box-sizing: border-box; 10 | box-sizing: border-box; 11 | } 12 | 13 | ::selection { 14 | background: #606d80; 15 | color: #fff; 16 | } 17 | 18 | ::-webkit-input-placeholder { 19 | color: #bec8d4; 20 | } 21 | 22 | ::-moz-placeholder { 23 | color: #bec8d4; 24 | } 25 | 26 | ::placeholder { 27 | color: #bec8d4; 28 | } 29 | -------------------------------------------------------------------------------- /anchor/migrations/10_add_comment_notifications.php: -------------------------------------------------------------------------------- 1 | has_table($table)) { 9 | if( ! Query::table($table)->where('key', '=', 'comment_notifications')->count()) { 10 | Query::table($table)->insert(array( 11 | 'key' => 'comment_notifications', 12 | 'value' => 0 13 | )); 14 | } 15 | } 16 | } 17 | 18 | public function down() {} 19 | 20 | } -------------------------------------------------------------------------------- /anchor/views/assets/js/custom-fields.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Extend attribute selection 3 | * 4 | * Show/hide fields depending on type 5 | */ 6 | $(function() { 7 | var select = $('#field'), attrs = $('.hide'); 8 | 9 | var update = function() { 10 | var value = select.val(); 11 | 12 | attrs.hide(); 13 | 14 | if(value == 'image') { 15 | attrs.show(); 16 | } 17 | else if(value == 'file') { 18 | $('.attributes_type').show(); 19 | } 20 | }; 21 | 22 | select.bind('change', update); 23 | 24 | update(); 25 | }); -------------------------------------------------------------------------------- /anchor/migrations/11_add_comment_moderation_keys.php: -------------------------------------------------------------------------------- 1 | has_table($table)) { 9 | if( ! Query::table($table)->where('key', '=', 'comment_moderation_keys')->count()) { 10 | Query::table($table)->insert(array( 11 | 'key' => 'comment_moderation_keys', 12 | 'value' => '' 13 | )); 14 | } 15 | } 16 | } 17 | 18 | public function down() {} 19 | 20 | } -------------------------------------------------------------------------------- /anchor/functions/config.php: -------------------------------------------------------------------------------- 1 | $value); 9 | } 10 | 11 | // existsing options 12 | $current = Config::get('theme', array()); 13 | 14 | // merge theme config 15 | Config::set('theme', array_merge($current, $options)); 16 | } 17 | 18 | function theme_option($option, $default = '') { 19 | return Config::get('theme.' . $option, $default); 20 | } 21 | -------------------------------------------------------------------------------- /anchor/migrations/71_insert_default_categories.php: -------------------------------------------------------------------------------- 1 | has_table($table)) { 9 | if( ! Query::table($table)->count()) { 10 | Query::table($table)->insert(array( 11 | 'title' => 'Uncategorised', 12 | 'slug' => 'uncategorised', 13 | 'description' => 'Ain\'t no category here.' 14 | )); 15 | } 16 | } 17 | } 18 | 19 | public function down() {} 20 | 21 | } -------------------------------------------------------------------------------- /anchor/views/assets/css/small.css: -------------------------------------------------------------------------------- 1 | body, html { 2 | width: 100%; 3 | } 4 | 5 | .wrap { 6 | width: 90%; 7 | } 8 | 9 | .top nav { 10 | float: none; 11 | overflow: hidden; 12 | } 13 | 14 | .top .btn { 15 | display: none; 16 | } 17 | 18 | .list, .list li { 19 | width: 100%; 20 | } 21 | 22 | .list li { 23 | float: none; 24 | margin-right: 0; 25 | } 26 | 27 | .list li p { 28 | display: none; 29 | } 30 | 31 | hgroup h1 { 32 | line-height: 80px; 33 | margin: 0; 34 | float: none; 35 | } 36 | 37 | hgroup nav { 38 | float: none; 39 | line-height: 80px; 40 | } -------------------------------------------------------------------------------- /install/views/halt.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |

Woops!

6 | 7 | 1): ?> 8 | 13 | 14 |

15 | 16 | 17 |

18 | Let's try that again. 19 |

20 |
21 |
22 | 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # os/app generated files 2 | Thumbs.db 3 | .DS_Store 4 | *.esproj 5 | *.log 6 | *.gz 7 | 8 | # env 9 | /anchor/config/dev 10 | 11 | # generated config 12 | /anchor/config/app.php 13 | /anchor/config/db.php 14 | /anchor/config/session.php 15 | 16 | # user mod_rewrite 17 | /.htaccess 18 | 19 | # debug and custom themes 20 | /themes/* 21 | !/themes/default 22 | 23 | # uploaded content 24 | /content/* 25 | !/content/index.php 26 | 27 | # plugins 28 | /plugins/* 29 | 30 | # phpunit tests 31 | /tests 32 | 33 | # We all love Sublime Text and its awesome plugins, don't we? 34 | sftp-config.json -------------------------------------------------------------------------------- /anchor/migrations/70_create_categories_table.php: -------------------------------------------------------------------------------- 1 | has_table($table)) { 9 | $sql = 'CREATE TABLE IF NOT EXISTS `' . $table . '` ( 10 | `id` int(6) NOT NULL AUTO_INCREMENT, 11 | `title` varchar(150) NOT NULL, 12 | `slug` varchar(40) NOT NULL, 13 | `description` text NOT NULL, 14 | PRIMARY KEY (`id`) 15 | ) ENGINE=InnoDB'; 16 | 17 | DB::query($sql); 18 | } 19 | } 20 | 21 | public function down() {} 22 | 23 | } -------------------------------------------------------------------------------- /anchor/models/base.php: -------------------------------------------------------------------------------- 1 | apply(get_called_class()); 17 | 18 | if(method_exists($obj, $method)) { 19 | return call_user_func_array(array($obj, $method), $arguments); 20 | } 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /anchor/config/aliases.php: -------------------------------------------------------------------------------- 1 | 'System\\Arr', 5 | 'Autoloader' => 'System\\Autoloader', 6 | 'Config' => 'System\\Config', 7 | 'Cookie' => 'System\\Cookie', 8 | 'DB' => 'System\\Database', 9 | 'Error' => 'System\\Error', 10 | 'Input' => 'System\\Input', 11 | 'Query' => 'System\\Database\\Query', 12 | 'Record' => 'System\\Database\\Record', 13 | 'Request' => 'System\\Request', 14 | //'Response' => 'System\\Response', 15 | 'Route' => 'System\\Route', 16 | 'Router' => 'System\\Router', 17 | 'Session' => 'System\\Session', 18 | 'Uri' => 'System\\Uri', 19 | 'View' => 'System\\View' 20 | ); -------------------------------------------------------------------------------- /install/config/aliases.php: -------------------------------------------------------------------------------- 1 | 'System\\Arr', 5 | 'Autoloader' => 'System\\Autoloader', 6 | 'Config' => 'System\\Config', 7 | 'Cookie' => 'System\\Cookie', 8 | 'DB' => 'System\\Database', 9 | 'Error' => 'System\\Error', 10 | 'Input' => 'System\\Input', 11 | 'Query' => 'System\\Database\\Query', 12 | 'Record' => 'System\\Database\\Record', 13 | 'Request' => 'System\\Request', 14 | 'Response' => 'System\\Response', 15 | 'Route' => 'System\\Route', 16 | 'Router' => 'System\\Router', 17 | 'Session' => 'System\\Session', 18 | 'Uri' => 'System\\Uri', 19 | 'View' => 'System\\View' 20 | ); -------------------------------------------------------------------------------- /anchor/libraries/csrf.php: -------------------------------------------------------------------------------- 1 | id; 12 | } 13 | 14 | function user_authed_name() { 15 | if($user = Auth::user()) return $user->username; 16 | } 17 | 18 | function user_authed_email() { 19 | if($user = Auth::user()) return $user->email; 20 | } 21 | 22 | function user_authed_role() { 23 | if($user = Auth::user()) return $user->role; 24 | } 25 | 26 | function user_authed_real_name() { 27 | if($user = Auth::user()) return $user->real_name; 28 | } -------------------------------------------------------------------------------- /anchor/migrations/40_create_page_meta_table.php: -------------------------------------------------------------------------------- 1 | has_table($table)) { 9 | $sql = "CREATE TABLE IF NOT EXISTS `' . $table . '` ( 10 | `id` int(6) NOT NULL AUTO_INCREMENT, 11 | `page` int(6) NOT NULL, 12 | `extend` int(6) NOT NULL, 13 | `data` text NOT NULL, 14 | PRIMARY KEY (`id`), 15 | KEY `page` (`page`), 16 | KEY `extend` (`extend`) 17 | ) ENGINE=InnoDB"; 18 | 19 | DB::ask($sql); 20 | } 21 | } 22 | 23 | public function down() {} 24 | 25 | } -------------------------------------------------------------------------------- /anchor/migrations/50_create_post_meta_table.php: -------------------------------------------------------------------------------- 1 | has_table($table)) { 9 | $sql = "CREATE TABLE IF NOT EXISTS `' . $table . '` ( 10 | `id` int(6) NOT NULL AUTO_INCREMENT, 11 | `post` int(6) NOT NULL, 12 | `extend` int(6) NOT NULL, 13 | `data` text NOT NULL, 14 | PRIMARY KEY (`id`), 15 | KEY `item` (`post`), 16 | KEY `extend` (`extend`) 17 | ) ENGINE=InnoDB"; 18 | 19 | DB::ask($sql); 20 | } 21 | } 22 | 23 | public function down() {} 24 | 25 | } -------------------------------------------------------------------------------- /anchor/views/assets/js/redirect.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Toggles the redirect field in pages 3 | */ 4 | $(function() { 5 | var fieldset = $('fieldset.redirect'), 6 | input = $('input[name=redirect]'), 7 | btn = $('button.secondary'); 8 | 9 | var toggle = function() { 10 | fieldset.toggleClass('show'); 11 | return false; 12 | }; 13 | 14 | btn.bind('click', toggle); 15 | 16 | // Hide the input if you get rid of the content within. 17 | input.change(function(){ 18 | if(input.val() === '') fieldset.removeClass('show'); 19 | }); 20 | 21 | // Show the redirect field if it isn't empty. 22 | if(input.val() !== '') fieldset.addClass('show'); 23 | }); -------------------------------------------------------------------------------- /install/libraries/braces.php: -------------------------------------------------------------------------------- 1 | render($vars); 9 | } 10 | 11 | public function __construct($path) { 12 | $this->path = $path; 13 | } 14 | 15 | public function render($vars = array()) { 16 | $content = file_get_contents($this->path); 17 | 18 | $keys = array_map(array($this, 'key'), array_keys($vars)); 19 | $values = array_values($vars); 20 | 21 | return str_replace($keys, $values, $content); 22 | } 23 | 24 | public function key($var) { 25 | return '{{' . $var . '}}'; 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /anchor/libraries/registry.php: -------------------------------------------------------------------------------- 1 | {$key}; 18 | } 19 | 20 | return $default; 21 | } 22 | 23 | public static function set($key, $value) { 24 | static::$data[$key] = $value; 25 | } 26 | 27 | public static function has($key) { 28 | return isset(static::$data[$key]); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /anchor/views/users/reset.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 |
7 | 8 | 9 | 10 |
11 |

12 |

13 | 14 |

15 |

16 |
17 |
18 |
19 | 20 | -------------------------------------------------------------------------------- /anchor/migrations/30_create_extend_table.php: -------------------------------------------------------------------------------- 1 | has_table($table)) { 9 | $sql = "CREATE TABLE IF NOT EXISTS `' . $table . '` ( 10 | `id` int(6) NOT NULL AUTO_INCREMENT, 11 | `type` enum('post','page') NOT NULL, 12 | `field` enum('text','html','image','file') NOT NULL, 13 | `key` varchar(160) NOT NULL, 14 | `label` varchar(160) NOT NULL, 15 | `attributes` text NOT NULL, 16 | PRIMARY KEY (`id`) 17 | ) ENGINE=InnoDB"; 18 | 19 | DB::ask($sql); 20 | } 21 | } 22 | 23 | public function down() {} 24 | 25 | } -------------------------------------------------------------------------------- /anchor/views/assets/js/text-resize.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Textarea auto resize 3 | */ 4 | $(function() { 5 | var $text = $('textarea').first(); 6 | 7 | function resize(e) { 8 | var bodyScrollPos = $('body').prop('scrollTop'); 9 | $text.height('auto'); 10 | $text.height($text.prop('scrollHeight') + 'px'); 11 | $('body').prop('scrollTop', bodyScrollPos); 12 | } 13 | 14 | /* 0-timeout to get the already changed text */ 15 | function delayedResize (e) { 16 | window.setTimeout(function(){ 17 | resize(e); 18 | }, 0); 19 | } 20 | 21 | $text.on('change', resize); 22 | $text.on('cut paste drop keydown', delayedResize); 23 | 24 | $text.focus(); 25 | $text.select(); 26 | resize(); 27 | }); -------------------------------------------------------------------------------- /anchor/models/user.php: -------------------------------------------------------------------------------- 1 | $value) { 11 | $query->where($key, '=', $value); 12 | } 13 | 14 | return $query->fetch(); 15 | } 16 | 17 | public static function paginate($page = 1, $perpage = 10) { 18 | $query = Query::table(static::table()); 19 | 20 | $count = $query->count(); 21 | 22 | $results = $query->take($perpage)->skip(($page - 1) * $perpage)->sort('real_name', 'desc')->get(); 23 | 24 | return new Paginator($results, $count, $page, $perpage, Uri::to('users')); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /anchor/libraries/date.php: -------------------------------------------------------------------------------- 1 | setTimezone(new DateTimeZone(Config::app('timezone'))); 16 | 17 | return $date->format($format); 18 | } 19 | 20 | /* 21 | * All database dates are stored as GMT 22 | */ 23 | public static function mysql($date) { 24 | $date = new DateTime($date, new DateTimeZone('GMT')); 25 | 26 | return $date->format('Y-m-d H:i:s'); 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /anchor/libraries/items.php: -------------------------------------------------------------------------------- 1 | position = 0; 9 | $this->array = $items; 10 | } 11 | 12 | public function rewind() { 13 | $this->position = 0; 14 | } 15 | 16 | public function current() { 17 | return $this->array[$this->position]; 18 | } 19 | 20 | public function key() { 21 | return $this->position; 22 | } 23 | 24 | public function next() { 25 | ++$this->position; 26 | } 27 | 28 | public function valid() { 29 | return isset($this->array[$this->position]); 30 | } 31 | 32 | public function length() { 33 | return count($this->array); 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /install/views/complete.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

Install complete!

5 | 6 | 7 |

We could not write the htaccess file for you, copy 8 | the contents below and create a .htaccess in your Anchor root folder. 9 |

10 | 11 | 12 | 13 | 14 |
15 | Visit your admin panel 16 | Visit your new site 17 |
18 |
19 | 20 | -------------------------------------------------------------------------------- /anchor/libraries/hash.php: -------------------------------------------------------------------------------- 1 | 31 or $rounds < 4) { 8 | throw new OutOfRangeException('Blowfish iteration count must be between 4 and 31'); 9 | } 10 | 11 | $rounds = sprintf('%02d', $rounds); 12 | 13 | // blowfish salt is 22 characters from the alphabet "./0-9A-Za-z". 14 | $pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; 15 | $salt = substr(str_shuffle(str_repeat($pool, 5)), 0, 22); 16 | 17 | return crypt($value, '$2a$' . $rounds . '$' . $salt); 18 | } 19 | 20 | public static function check($value, $hash) { 21 | return crypt($value, $hash) === $hash; 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /system/start.php: -------------------------------------------------------------------------------- 1 | dispatch(); 37 | 38 | /** 39 | * Update session 40 | */ 41 | Session::write(); 42 | 43 | /** 44 | * Output stuff 45 | */ 46 | $response->send(); 47 | -------------------------------------------------------------------------------- /anchor/models/category.php: -------------------------------------------------------------------------------- 1 | id] = $item->title; 12 | } 13 | 14 | return $items; 15 | } 16 | 17 | public static function slug($slug) { 18 | return static::where('slug', 'like', $slug)->fetch(); 19 | } 20 | 21 | public static function paginate($page = 1, $perpage = 10) { 22 | $query = Query::table(static::table()); 23 | 24 | $count = $query->count(); 25 | 26 | $results = $query->take($perpage)->skip(($page - 1) * $perpage)->sort('title')->get(); 27 | 28 | return new Paginator($results, $count, $page, $perpage, Uri::to('categories')); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /anchor/routes/menu.php: -------------------------------------------------------------------------------- 1 | 'auth,csrf'), function() { 4 | 5 | /* 6 | List Menu Items 7 | */ 8 | Route::get('admin/menu', function() { 9 | $vars['messages'] = Notify::read(); 10 | $vars['pages'] = Page::where('show_in_menu', '=', 1)->sort('menu_order')->get(); 11 | 12 | return View::create('menu/index', $vars) 13 | ->partial('header', 'partials/header') 14 | ->partial('footer', 'partials/footer'); 15 | }); 16 | 17 | /* 18 | Update order 19 | */ 20 | Route::post('admin/menu/update', function() { 21 | $sort = Input::get('sort'); 22 | 23 | foreach($sort as $index => $id) { 24 | Page::where('id', '=', $id)->update(array('menu_order' => $index)); 25 | } 26 | 27 | return Response::json(array('result' => true)); 28 | }); 29 | 30 | }); -------------------------------------------------------------------------------- /anchor/language/en_GB/categories.php: -------------------------------------------------------------------------------- 1 | 'Category', 6 | 'categories' => 'Categories', 7 | 8 | 'create_category' => 'Create a new category', 9 | 'edit_category' => 'Editing “%s”', 10 | 11 | // form fields 12 | 'title' => 'Title', 13 | 'title_explain' => 'Your category title.', 14 | 'title_missing' => 'Please enter a title', 15 | 16 | 'slug' => 'Slug', 17 | 'slug_explain' => 'The slug for your category.', 18 | 19 | 'description' => 'Description', 20 | 'description_explain' => 'What your category is about.', 21 | 22 | // messages 23 | 'created' => 'Your new category has been added.', 24 | 'updated' => 'Your category has been updated.', 25 | 'deleted' => 'Your category has been deleted.', 26 | 'delete_error' => 'You must have at least one category.', 27 | 28 | ); -------------------------------------------------------------------------------- /system/session/driver.php: -------------------------------------------------------------------------------- 1 | config = $config; 29 | } 30 | 31 | /** 32 | * The session read prototype 33 | */ 34 | abstract public function read($id); 35 | 36 | /** 37 | * The session write prototype 38 | * 39 | * @param int 40 | * @param object 41 | */ 42 | abstract public function write($id, $cargo); 43 | 44 | } -------------------------------------------------------------------------------- /anchor/views/categories/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

5 | 6 | 9 |
10 | 11 |
12 | 13 | 14 | 25 | 26 | 27 |
28 | 29 | -------------------------------------------------------------------------------- /themes/default/css/small.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Small device CSS, mostly to fix alignment 3 | */ 4 | 5 | #top { 6 | position: relative; 7 | } 8 | #top .tray { 9 | position: absolute; 10 | right: 10px; 11 | top: 10px; 12 | } 13 | #top #logo, #top ul { 14 | float: none; 15 | } 16 | #top ul li { 17 | padding: 10px 15px 0 0; 18 | } 19 | 20 | .slidey form, .slidey aside { 21 | float: none; 22 | width: 100%; 23 | } 24 | .slidey form { 25 | margin-bottom: 25px; 26 | } 27 | 28 | #comment p, .footnote { 29 | float: none; 30 | width: 100%; 31 | 32 | white-space: normal; 33 | } 34 | 35 | #bottom { 36 | padding: 20px 0; 37 | } 38 | #bottom small { 39 | display: block; 40 | } 41 | #bottom ul { 42 | overflow: hidden; 43 | float: none; 44 | margin-bottom: 15px; 45 | } 46 | #bottom li { 47 | padding: 15px 15px 0 0; 48 | } -------------------------------------------------------------------------------- /themes/default/footer.php: -------------------------------------------------------------------------------- 1 |
2 | 16 | 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /anchor/libraries/template.php: -------------------------------------------------------------------------------- 1 | slug . EXT)) { 13 | $template .= '-' . $item->slug; 14 | } elseif (is_readable($base . $template . 's/' . $template . '-' . $item->slug . EXT)) { 15 | $template .= 's/' . $template . '-' . $item->slug; 16 | } 17 | } 18 | } 19 | 20 | $this->path = $base . $template . EXT; 21 | $this->vars = array_merge($this->vars, $vars); 22 | } 23 | 24 | public function __toString() { 25 | return $this->render(); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | where('status', '=', 'active')->fetch()) { 19 | // found a valid user now check the password 20 | if(Hash::check($password, $user->password)) { 21 | // store user ID in the session 22 | Session::put(static::$session, $user->id); 23 | 24 | return true; 25 | } 26 | } 27 | 28 | return false; 29 | } 30 | 31 | public static function logout() { 32 | Session::erase(static::$session); 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /anchor/views/users/amnesia.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 |
8 | 9 | 10 |
11 |

12 | 'email', 14 | 'autocapitalize' => 'off', 15 | 'autofocus' => 'true', 16 | 'placeholder' => __('users.email') 17 | )); ?>

18 | 19 |

20 | 21 | 22 |

23 |
24 |
25 | 26 |
27 | 28 | -------------------------------------------------------------------------------- /install/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

5 | 6 | 9 |
10 | 11 |
12 | 13 | 14 | 26 | 27 | 28 |
29 | 30 | -------------------------------------------------------------------------------- /anchor/libraries/events.php: -------------------------------------------------------------------------------- 1 | slug][$name]) ? static::$stack[$page->slug][$name] : false) { 35 | return is_callable($func) ? $func() : ''; 36 | } 37 | 38 | return ''; 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /anchor/views/extend/variables/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

5 | 6 | 9 |
10 | 11 |
12 | 13 | 14 | 15 | 25 | 26 |

27 | 28 |

29 | 30 |
31 | 32 | -------------------------------------------------------------------------------- /anchor/views/assets/js/slug.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Format title into a slug value after each keypress 3 | * Disabled if the slug is manually changed 4 | */ 5 | $(function() { 6 | var input = $('input[name=title]'), output = $('input[name=slug]'); 7 | var changed = false; 8 | 9 | var slugify = function(str) { 10 | str = str.replace(/^\s+|\s+$/g, '').toLowerCase(); 11 | 12 | // remove accents 13 | var from = "àáäâèéëêìíïîòóöôùúüûñç·/_,:;", to = "aaaaeeeeiiiioooouuuunc------"; 14 | 15 | for(var i = 0, l = from.length; i < l; i++) { 16 | str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i)); 17 | } 18 | 19 | return str.replace(/[^a-z0-9 -]/g, '') // remove invalid chars 20 | .replace(/\s+/g, '-') // collapse whitespace and replace by - 21 | .replace(/-+/g, '-'); // collapse dashes 22 | } 23 | 24 | output.bind('keyup', function() { 25 | changed = true; 26 | }); 27 | 28 | input.bind('keyup', function() { 29 | if( ! changed) output.val(slugify(input.val())); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /anchor/libraries/json.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

5 | 6 | 9 |
10 | 11 |
12 | 13 | 14 | results)): ?> 15 | 25 | 26 | 27 | 28 |

29 | 30 |

31 | 32 |
33 | 34 | -------------------------------------------------------------------------------- /themes/default/search.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |

You searched for “”.

4 | 5 | 6 | 17 | 18 | 19 | 25 | 26 | 27 | 28 |

Unfortunately, there's no results for “”. Did you spell everything correctly?

29 | 30 | 31 | -------------------------------------------------------------------------------- /anchor/libraries/migration.php: -------------------------------------------------------------------------------- 1 | setFetchMode(PDO::FETCH_NUM); 14 | 15 | $tables = array(); 16 | 17 | foreach($statement->fetchAll() as $row) { 18 | $tables[] = $row[0]; 19 | } 20 | 21 | return in_array($table, $tables); 22 | } 23 | 24 | public function has_table_column($table, $column) { 25 | if($this->has_table($table)) { 26 | $sql = 'SHOW COLUMNS FROM `' . $table . '`'; 27 | list($result, $statement) = DB::ask($sql); 28 | $statement->setFetchMode(PDO::FETCH_OBJ); 29 | 30 | $columns = array(); 31 | 32 | foreach($statement->fetchAll() as $row) { 33 | $columns[] = $row->Field; 34 | } 35 | 36 | return in_array($column, $columns); 37 | } 38 | else return false; 39 | } 40 | } -------------------------------------------------------------------------------- /anchor/views/extend/variables/add.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

5 |
6 | 7 |
8 | 9 | 10 |
11 | 12 | 13 | 14 |
15 |

16 | 17 | 18 | 19 |

20 | 21 |

22 | 23 | 20)); ?> 24 | 25 |

26 |
27 | 28 | 31 |
32 |
33 | 34 | -------------------------------------------------------------------------------- /anchor/functions/pages.php: -------------------------------------------------------------------------------- 1 | uri(); 13 | } 14 | } 15 | 16 | function page_slug() { 17 | return Registry::prop('page', 'slug'); 18 | } 19 | 20 | function page_name() { 21 | return Registry::prop('page', 'name'); 22 | } 23 | 24 | function page_title($default = '') { 25 | if($title = Registry::prop('article', 'title')) { 26 | return $title; 27 | } 28 | 29 | if($title = Registry::prop('page', 'title')) { 30 | return $title; 31 | } 32 | 33 | return $default; 34 | } 35 | 36 | function page_content() { 37 | return parse(Registry::prop('page', 'content')); 38 | } 39 | 40 | function page_status() { 41 | return Registry::prop('page', 'status'); 42 | } 43 | 44 | function page_custom_field($key, $default = '') { 45 | $id = Registry::prop('page', 'id'); 46 | 47 | if($extend = Extend::field('page', $key, $id)) { 48 | return Extend::value($extend, $default); 49 | } 50 | 51 | return $default; 52 | } -------------------------------------------------------------------------------- /anchor/views/assets/css/login.css: -------------------------------------------------------------------------------- 1 | /* 2 | Login 3 | */ 4 | body.login { 5 | position: absolute; 6 | top: 25%; 7 | left: 50%; 8 | margin-left: -150px; 9 | background: #444f5f; 10 | } 11 | 12 | .login .wrap, .login .content { 13 | width: 300px; 14 | } 15 | .login h1 { 16 | padding-bottom: 25px; 17 | 18 | font-size: 25px; 19 | line-height: 60px; 20 | font-weight: lighter; 21 | color: #fff; 22 | } 23 | 24 | .login label { 25 | display: none; 26 | } 27 | 28 | .login fieldset { 29 | border: none; 30 | } 31 | 32 | .login input { 33 | width: 300px; 34 | margin-bottom: 20px; 35 | 36 | padding: 14px 16px; 37 | } 38 | 39 | .login .buttons a { 40 | float: right; 41 | font-size: 13px; 42 | line-height: 38px; 43 | } 44 | 45 | .login .buttons button { 46 | float: left; 47 | } 48 | 49 | .login a { 50 | color: #8491a5; 51 | } 52 | 53 | .login a:hover { 54 | color: #fff; 55 | } 56 | 57 | .login button { 58 | background: #2f3744; 59 | color: #96a4bb; 60 | font-size: 13px; 61 | font-weight: 500; 62 | } 63 | 64 | .login .notification { 65 | width: 300px; 66 | } 67 | 68 | -------------------------------------------------------------------------------- /install/views/partials/header.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Installin' Anchor CMS 6 | 7 | 8 | 9 | 10 | 11 | 12 | 23 | 24 | -------------------------------------------------------------------------------- /anchor/libraries/notify.php: -------------------------------------------------------------------------------- 1 | %s'; 7 | public static $mwrap = '

%s

'; 8 | 9 | public static function add($type, $message) { 10 | if(in_array($type, static::$types)) { 11 | $messages = array_merge((array) Session::get('messages.' . $type), (array) $message); 12 | 13 | Session::put('messages.' . $type, $messages); 14 | } 15 | } 16 | 17 | public static function read() { 18 | $types = Session::get('messages'); 19 | 20 | // no messages no problem 21 | if(is_null($types)) return ''; 22 | 23 | $html = ''; 24 | 25 | foreach($types as $type => $messages) { 26 | foreach($messages as $message) { 27 | $html .= sprintf(static::$mwrap, $type, implode('
', (array) $message)); 28 | } 29 | } 30 | 31 | Session::erase('messages'); 32 | 33 | return sprintf(static::$wrap, $html); 34 | } 35 | 36 | public static function __callStatic($method, $paramaters = array()) { 37 | static::add($method, array_shift($paramaters)); 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /anchor/views/extend/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

5 |
6 | 7 |
8 | 9 | 10 | 36 |
37 | 38 | -------------------------------------------------------------------------------- /anchor/language/en_GB/comments.php: -------------------------------------------------------------------------------- 1 | 'Comments', 6 | 'nocomments_desc' => 'No comments yet.', 7 | 'editing_comment' => 'Editing comment', 8 | 'view_comment' => 'View comment', 9 | 10 | // form fields 11 | 'name' => 'Name', 12 | 'name_explain' => 'Author name', 13 | 'name_missing' => 'Please enter a name', 14 | 15 | 'email' => 'Email address', 16 | 'email_explain' => 'Author email', 17 | 'email_missing' => 'Please enter a valid email address', // frontend message (appears on your site!) 18 | 19 | 'text' => 'Comment', 20 | 'text_explain' => '', 21 | 'text_missing' => 'Please enter comment text', // frontend message (appears on your site!) 22 | 23 | 'status' => 'Status', 24 | 'status_explain' => '', 25 | 26 | // messages 27 | 'created' => 'Your comment has been added', // frontend message (appears on your site!) 28 | 'updated' => 'Your comment has been updated', 29 | 'deleted' => 'Your comment has been deleted', 30 | 31 | // email notification 32 | 'notify_subject' => 'New comment has been added', 33 | 'nofity_heading' => 'A new comment has been submitted to your site.' 34 | 35 | ); 36 | -------------------------------------------------------------------------------- /system/request.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 |
13 |

14 | 'user', 16 | 'autocapitalize' => 'off', 17 | 'autofocus' => 'true', 18 | 'placeholder' => __('users.username') 19 | )); ?>

20 | 21 |

22 | 'pass', 24 | 'placeholder' => __('users.password') 25 | )); ?>

26 | 27 |

28 |

29 |
30 |
31 | 32 |
33 | 34 | -------------------------------------------------------------------------------- /anchor/views/menu/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

5 |
6 | 7 |
8 | 9 | 10 | 11 | 18 | 19 |

20 | 21 | No menu items yet. 22 |

23 | 24 |
25 | 26 | 27 | 45 | 46 | -------------------------------------------------------------------------------- /system/database/connectors/sqlite.php: -------------------------------------------------------------------------------- 1 | pdo = new PDO($dns); 49 | $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 50 | } 51 | 52 | /** 53 | * Return the pdo instance 54 | * 55 | * @param object PDO Object 56 | */ 57 | public function instance() { 58 | return $this->pdo; 59 | } 60 | 61 | } -------------------------------------------------------------------------------- /anchor/views/assets/css/notifications.css: -------------------------------------------------------------------------------- 1 | 2 | .notifications { 3 | margin-bottom: 10px; 4 | } 5 | 6 | .notifications .notice, .notifications .error, .notifications .success { 7 | padding: 10px 18px; 8 | margin-bottom: 20px; 9 | 10 | font-size: 13px; 11 | line-height: 21px; 12 | font-weight: 500; 13 | 14 | border-radius: 5px; 15 | } 16 | 17 | .notifications .notice { 18 | color: #fff; 19 | background: #578cd9; 20 | } 21 | 22 | .notifications .error { 23 | color: #fff; 24 | background: #d34937; 25 | } 26 | 27 | .notifications .success { 28 | color: #fff; 29 | background: #64a524; 30 | } 31 | 32 | 33 | .header .notifications { 34 | position: absolute; 35 | left: 55%; 36 | top: 82px; 37 | z-index: 1200; 38 | width: 320px; 39 | } 40 | .header .page .notifications { 41 | left: 48%; 42 | } 43 | .header .notifications div:after { 44 | content: ''; 45 | position: absolute; 46 | display: block; 47 | top: -6px; 48 | right: 50px; 49 | 50 | border-bottom: 6px solid #64a524; 51 | border-left: 6px solid transparent; 52 | border-right: 6px solid transparent; 53 | } 54 | 55 | .header .notifications .error:after { 56 | border-bottom-color: #d34937; 57 | } -------------------------------------------------------------------------------- /system/session/drivers/memcache.php: -------------------------------------------------------------------------------- 1 | config = $config; 25 | $this->key = Config::app('key'); 26 | 27 | // setup the memcache server 28 | extract(Config::cache('memcache')); 29 | 30 | $this->server = new M; 31 | $this->server->addServer($host, $port); 32 | } 33 | 34 | public function read($id) { 35 | if($data = $this->server->get($this->key . '_' . $id)) { 36 | return unserialize($data); 37 | } 38 | } 39 | 40 | public function write($id, $cargo) { 41 | extract($this->config); 42 | 43 | // if the session is set to never expire 44 | // we will set it to 1 year 45 | if($lifetime == 0) { 46 | $lifetime = (3600 * 24 * 365); 47 | } 48 | 49 | $this->server->set($this->key . '_' . $id, serialize($cargo), 0, $lifetime); 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /system/session/drivers/memcached.php: -------------------------------------------------------------------------------- 1 | config = $config; 25 | $this->key = Config::app('key'); 26 | 27 | // setup the memcache server 28 | extract(Config::cache('memcached')); 29 | 30 | $this->server = new M; 31 | $this->server->addServer($host, $port); 32 | } 33 | 34 | public function read($id) { 35 | if($data = $this->server->get($this->key . '_' . $id)) { 36 | return unserialize($data); 37 | } 38 | } 39 | 40 | public function write($id, $cargo) { 41 | extract($this->config); 42 | 43 | // if the session is set to never expire 44 | // we will set it to 1 year 45 | if($lifetime == 0) { 46 | $lifetime = (3600 * 24 * 365); 47 | } 48 | 49 | $this->server->set($this->key . '_' . $id, serialize($cargo), $lifetime); 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /anchor/libraries/language.php: -------------------------------------------------------------------------------- 1 | 1) { 23 | $file = array_shift($parts); 24 | $line = array_shift($parts); 25 | } 26 | 27 | if(count($parts) == 1) { 28 | $file = 'global'; 29 | $line = array_shift($parts); 30 | } 31 | 32 | if( ! isset(static::$lines[$file])) { 33 | static::load($file); 34 | } 35 | 36 | if(isset(static::$lines[$file][$line])) { 37 | $text = static::$lines[$file][$line]; 38 | } 39 | else if($default) { 40 | $text = $default; 41 | } 42 | else { 43 | $text = $key; 44 | } 45 | 46 | if(count($args)) { 47 | return call_user_func_array('sprintf', array_merge(array($text), $args)); 48 | } 49 | 50 | return $text; 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /anchor/views/error/404.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 404 6 | 7 | 13 | 14 | 31 | 32 | 33 | 34 |

404

35 | 36 |

The page was not found.

37 | 38 |

Try the homepage

39 | 40 | 41 | -------------------------------------------------------------------------------- /install/views/error/404.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 404 6 | 7 | 13 | 14 | 31 | 32 | 33 | 34 |

404

35 | 36 |

The page was not found.

37 | 38 |

Try the homepage

39 | 40 | 41 | -------------------------------------------------------------------------------- /anchor/language/en_GB/pages.php: -------------------------------------------------------------------------------- 1 | 'Pages', 6 | 7 | 'create_page' => 'Create a new page', 8 | 'nopages_desc' => 'You don’t have any pages.', 9 | 'redirect' => 'Redirect', 10 | 11 | // form fields 12 | 'redirect_url' => 'Redirect Url', 13 | 'redirect_missing' => 'Please enter a valid url', 14 | 15 | 'title' => 'Page title', 16 | 'title_explain' => '', 17 | 'title_missing' => 'Please enter a page title', 18 | 19 | 'content' => 'Content', 20 | 'content_explain' => 'Your page’s content. Uses Markdown.', 21 | 22 | 'show_in_menu' => 'Show In Menu', 23 | 'show_in_menu_explain' => '', 24 | 25 | 'name' => 'Name', 26 | 'name_explain' => '', 27 | 28 | 'slug' => 'Slug', 29 | 'slug_explain' => 'Slug uri to identify your page, should only contain ascii characters', 30 | 'slug_missing' => 'Please enter a slug uri, slugs can only contain ascii characters', 31 | 'slug_duplicate' => 'Slug already exists', 32 | 'slug_invalid' => 'Slug must contain letters', 33 | 34 | 'status' => 'Status', 35 | 'status_explain' => '', 36 | 37 | 'parent' => 'Parent', 38 | 'parent_explain' => '', 39 | 40 | // messages 41 | 'updated' => 'Your page was updated.', 42 | 'created' => 'Your page was created.', 43 | 'deleted' => 'Your page was deleted.' 44 | 45 | ); -------------------------------------------------------------------------------- /anchor/views/assets/js/focus-mode.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Focus mode for post and page main textarea 3 | */ 4 | $(function() { 5 | var doc = $(document), html = $('html'), body = html.children('body'); 6 | 7 | var Focus = { 8 | // Our element to focus 9 | target: $('textarea[name=html], textarea[name=content]'), 10 | exitSpan: '#exit-focus', 11 | 12 | enter: function() { 13 | html.addClass('focus'); 14 | 15 | if( ! body.children(Focus.exitSpan).length) { 16 | body.append('Exit focus mode (ESC)'); 17 | } 18 | 19 | body.children(Focus.exitSpan).css('opacity', 0).animate({opacity: 1}, 250); 20 | 21 | // Set titles and placeholders 22 | Focus.target.placeholder = (Focus.target.placeholder || '').split('.')[0] + '.'; 23 | }, 24 | 25 | exit: function() { 26 | body.children(Focus.exitSpan).animate({opacity: 0}, 250); 27 | html.removeClass('focus'); 28 | } 29 | }; 30 | 31 | // Bind textarea events 32 | Focus.target.focus(Focus.enter).blur(Focus.exit); 33 | 34 | // Bind key events 35 | doc.on('keyup', function(event) { 36 | // Pressing the "f" key 37 | if(event.keyCode == 70) { 38 | Focus.enter(); 39 | } 40 | 41 | // Pressing the Escape key 42 | if(event.keyCode == 27) { 43 | Focus.exit(); 44 | } 45 | }); 46 | }); -------------------------------------------------------------------------------- /anchor/language/en_GB/posts.php: -------------------------------------------------------------------------------- 1 | 'Posts', 6 | 7 | 'create_post' => 'Create a new post', 8 | 'noposts_desc' => 'You don’t have any posts!', 9 | 10 | // form fields 11 | 'title' => 'Post title', 12 | 'title_explain' => '', 13 | 'title_missing' => 'Please enter a title', 14 | 15 | 'content' => 'Post Content', 16 | 'content_explain' => 'Just write.', 17 | 18 | 'slug' => 'Slug', 19 | 'slug_explain' => 'Slug uri to identify your post, should only contain ascii characters', 20 | 'slug_missing' => 'Please enter a slug uri, slugs can only contain ascii characters', 21 | 'slug_duplicate' => 'Slug already exists', 22 | 'slug_invalid' => 'Slug must contain letters', 23 | 24 | 'description' => 'Description', 25 | 'description_explain' => '', 26 | 27 | 'status' => 'Status', 28 | 'status_explain' => '', 29 | 30 | 'category' => 'Category', 31 | 'category_explain' => '', 32 | 33 | 'allow_comments' => 'Allow Comments', 34 | 'allow_comments_explain' => '', 35 | 36 | 'custom_css' => 'Custom CSS', 37 | 'custom_css_explain' => '', 38 | 39 | 'custom_js' => 'Custom JS', 40 | 'custom_js_explain' => '', 41 | 42 | // messages 43 | 'updated' => 'Your article has been updated', 44 | 'created' => 'Your new article was created', 45 | 'deleted' => 'Your article have been deleted' 46 | 47 | ); -------------------------------------------------------------------------------- /anchor/views/comments/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

5 |
6 | 7 |
8 | 9 | 10 | 17 | 18 | count): ?> 19 | 30 | 31 | 32 | 33 | 34 |

35 | 36 | 37 |

38 | 39 |
40 | 41 | -------------------------------------------------------------------------------- /anchor/language/en_GB/metadata.php: -------------------------------------------------------------------------------- 1 | 'Site Metadata', 6 | 'metadata_desc' => 'Manage your site data', 7 | 8 | 'comment_settings' => 'Comments', 9 | 'theme_settings' => 'Apperance', 10 | 11 | // form fields 12 | 'sitename' => 'Site name', 13 | 'sitename_explain' => '', 14 | 'sitename_missing' => 'Your site needs a name!', 15 | 16 | 'sitedescription' => 'Site description', 17 | 'sitedescription_explain' => '', 18 | 'sitedescription_missing' => 'Your site needs a description!', 19 | 20 | 'homepage' => 'Home Page', 21 | 'homepage_explain' => '', 22 | 23 | 'postspage' => 'Posts Page', 24 | 'postspage_explain' => '', 25 | 26 | 'posts_per_page' => 'Posts per page', 27 | 'posts_per_page_explain' => '', 28 | 29 | 'auto_publish_comments' => 'Auto-allow comments', 30 | 'auto_publish_comments_explain' => '', 31 | 32 | 'comment_notifications' => 'Email notification for new comments', 33 | 'comment_notifications_explain' => '', 34 | 35 | 'comment_moderation_keys' => 'Spam keywords', 36 | 'comment_moderation_keys_explain' => 'Comma separated list of keywords to blacklist against. 37 | Comments will automatically be set as spam.', 38 | 39 | 'current_theme' => 'Current theme', 40 | 'current_theme_explain' => '', 41 | 42 | // messages 43 | 'updated' => 'Metadata updated', 44 | 45 | ); -------------------------------------------------------------------------------- /anchor/run.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 500 - Internal Server Error 6 | 7 | 23 | 24 | 41 | 42 | 43 |

Internal Server Error

44 | 45 |

An error occured while we were processing your request.

46 | 47 | -------------------------------------------------------------------------------- /install/views/error/500.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 500 - Internal Server Error 6 | 7 | 23 | 24 | 41 | 42 | 43 |

Internal Server Error

44 | 45 |

An error occured while we were processing your request.

46 | 47 | -------------------------------------------------------------------------------- /system/request/server.php: -------------------------------------------------------------------------------- 1 | data = $array; 29 | } 30 | 31 | /** 32 | * Get a server array item 33 | * 34 | * @param string 35 | */ 36 | public function get($key, $fallback = null) { 37 | if(array_key_exists($key, $this->data)) { 38 | return $this->data[$key]; 39 | } 40 | 41 | return $fallback; 42 | } 43 | 44 | /** 45 | * Set a server array item 46 | * 47 | * @param string 48 | * @param string 49 | */ 50 | public function set($key, $value) { 51 | $this->data[$key] = $value; 52 | } 53 | 54 | /** 55 | * Check if a server array item exists 56 | * 57 | * @param string 58 | */ 59 | public function has($key) { 60 | return array_key_exists($key, $this->data); 61 | } 62 | 63 | /** 64 | * Remove a server array item 65 | * 66 | * @param string 67 | */ 68 | public function erase($key) { 69 | if($this->has($key)) { 70 | unset($this->data[$key]); 71 | } 72 | } 73 | 74 | } -------------------------------------------------------------------------------- /anchor/views/extend/variables/edit.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

user_key); ?>

5 |
6 | 7 |
8 | 9 | 10 |
11 | 12 | 13 | 14 |
15 |

16 | 17 | user_key)); ?> 18 | 19 |

20 | 21 |

22 | 23 | value), array('cols' => 20)); ?> 24 | 25 |

user_key); ?> 26 |

27 |
28 | 29 | 34 |
35 |
36 | 37 | -------------------------------------------------------------------------------- /anchor/functions/categories.php: -------------------------------------------------------------------------------- 1 | length(); 17 | } 18 | 19 | // loop categories 20 | function categories() { 21 | if( ! total_categories()) return false; 22 | 23 | $items = Registry::get('categories'); 24 | 25 | if($result = $items->valid()) { 26 | // register single category 27 | Registry::set('category', $items->current()); 28 | 29 | // move to next 30 | $items->next(); 31 | } 32 | 33 | return $result; 34 | } 35 | 36 | // single categories 37 | function category_id() { 38 | return Registry::prop('category', 'id'); 39 | } 40 | 41 | function category_title() { 42 | return Registry::prop('category', 'title'); 43 | } 44 | 45 | function category_slug() { 46 | return Registry::prop('category', 'slug'); 47 | } 48 | 49 | function category_description() { 50 | return Registry::prop('category', 'description'); 51 | } 52 | 53 | function category_url() { 54 | return base_url('category/' . category_slug()); 55 | } 56 | 57 | function category_count() { 58 | return Query::table(Base::table('posts')) 59 | ->where('category', '=', category_id()) 60 | ->where('status', '=', 'published')->count(); 61 | } -------------------------------------------------------------------------------- /install/views/account.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
6 |

Your first account

7 | 8 |

Oh, we're so tantalisingly close! All we need now is a username and password to log in to the admin area with.

9 |
10 | 11 |
12 | 13 | 14 |
15 |

16 | 17 | You use this to log in. 18 | 19 |

20 | 21 |

22 | 23 | Needed if you can’t log in. 24 | 25 | 26 |

27 | 28 |

29 | 30 | Make sure to pick a secure password. 31 | 32 |

33 |
34 | 35 |
36 | « Back 37 | 38 |
39 |
40 |
41 | 42 | -------------------------------------------------------------------------------- /anchor/helpers.php: -------------------------------------------------------------------------------- 1 | $key) { 34 | $replace[$index] = Config::meta($key); 35 | } 36 | 37 | $str = str_replace($search, $replace, $str); 38 | } 39 | 40 | $str = html_entity_decode($str, ENT_NOQUOTES, System\Config::app('encoding')); 41 | 42 | // Parse Markdown as well? 43 | if($markdown === true) { 44 | $md = new Markdown; 45 | $str = $md->transform($str); 46 | } 47 | 48 | return $str; 49 | } 50 | 51 | function readable_size($size) { 52 | $unit = array('b','kb','mb','gb','tb','pb'); 53 | 54 | return round($size / pow(1024, ($i = floor(log($size, 1024)))), 2) . ' ' . $unit[$i]; 55 | } -------------------------------------------------------------------------------- /system/session/drivers/cookie.php: -------------------------------------------------------------------------------- 1 | config); 21 | 22 | // check if the cookie exists 23 | if($encoded = C::read($cookie . '_payload')) { 24 | // try decoding first 25 | if($decoded = base64_decode($encoded)) { 26 | // verify signature 27 | $sign = substr($decoded, 0, 32); 28 | $serialized = substr($decoded, 32); 29 | 30 | if(hash('md5', $serialized) == $sign) { 31 | return unserialize($serialized); 32 | } 33 | } 34 | } 35 | } 36 | 37 | public function write($id, $cargo) { 38 | extract($this->config); 39 | 40 | // if the session is set to never expire 41 | // we will set it to 1 year 42 | if($lifetime == 0) { 43 | $lifetime = (3600 * 24 * 365); 44 | } 45 | 46 | // serialize data into a srting 47 | $serialized = serialize($cargo); 48 | 49 | // create a signature to verify content when unpacking 50 | $sign = hash('md5', $serialized); 51 | 52 | // encode all the data 53 | $data = base64_encode($sign . $serialized); 54 | 55 | C::write($cookie . '_payload', $data, $lifetime, $path, $domain, $secure); 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /anchor/views/upgrade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <?php echo __('global.upgrade'); ?> 7 | 8 | 41 | 42 | 43 |
44 | Anchor logo 45 | 46 |

47 |

48 | 49 | 50 | 51 |
52 | 53 | 54 | -------------------------------------------------------------------------------- /system/session/drivers/database.php: -------------------------------------------------------------------------------- 1 | config); 22 | 23 | // run garbage collection 24 | if(mt_rand(0, 100) > 90) { 25 | Query::table($table)->where('expire', '<', time())->delete(); 26 | } 27 | 28 | // find session 29 | $query = Query::table($table)->where('id', '=', $id)->where('expire', '>', time()); 30 | 31 | if($result = $query->fetch(array('data'))) { 32 | $this->exists = true; 33 | 34 | if($data = @unserialize($result->data)) { 35 | return $data; 36 | } 37 | } 38 | } 39 | 40 | public function write($id, $cargo) { 41 | extract($this->config); 42 | 43 | // if the session is set to never expire 44 | // we will set it to 1 year 45 | if($lifetime == 0) { 46 | $lifetime = (3600 * 24 * 365); 47 | } 48 | 49 | $expire = time() + $lifetime; 50 | $data = serialize($cargo); 51 | 52 | if($this->exists) { 53 | Query::table($table)->where('id', '=', $id)->update(array('expire' => $expire, 'data' => $data)); 54 | } 55 | else { 56 | Query::table($table)->insert(array('id' => $id, 'expire' => $expire, 'data' => $data)); 57 | } 58 | } 59 | 60 | } -------------------------------------------------------------------------------- /anchor/models/page.php: -------------------------------------------------------------------------------- 1 | fetch(); 9 | } 10 | 11 | public static function dropdown($params = array()) { 12 | $items = array(); 13 | $exclude = array(); 14 | 15 | if(isset($params['show_empty_option']) and $params['show_empty_option']) { 16 | $items[0] = 'None'; 17 | } 18 | 19 | if(isset($params['exclude'])) { 20 | $exclude = (array) $params['exclude']; 21 | } 22 | 23 | foreach(static::get() as $page) { 24 | if(in_array($page->id, $exclude)) continue; 25 | 26 | $items[$page->id] = $page->name; 27 | } 28 | 29 | return $items; 30 | } 31 | 32 | public static function home() { 33 | return static::find(Config::meta('home_page')); 34 | } 35 | 36 | public static function posts() { 37 | return static::find(Config::meta('posts_page')); 38 | } 39 | 40 | public function uri() { 41 | return Uri::to($this->relative_uri()); 42 | } 43 | 44 | public function relative_uri() { 45 | $segments = array($this->slug); 46 | $parent = $this->parent; 47 | 48 | while($parent) { 49 | $page = static::find($parent); 50 | $segments[] = $page->slug; 51 | $parent = $page->parent; 52 | } 53 | 54 | return implode('/', array_reverse($segments)); 55 | } 56 | 57 | public function active() { 58 | if (Registry::prop('page', 'slug') == $this->slug || Registry::prop('page', 'parent') == $this->id) { 59 | return true; 60 | } 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /anchor/views/categories/add.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

5 |
6 | 7 |
8 | 9 | 10 |
11 | 12 | 13 | 14 |
15 |

16 | 17 | 18 | 19 |

20 |

21 | 22 | 23 | 24 |

25 |

26 | 27 | 28 | 29 |

30 |
31 | 32 | 35 | 36 |
37 |
38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /themes/default/posts.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 34 | 35 | 36 | 42 | 43 | 44 | 45 |

Looks like you have some writing to do!

46 | 47 | 48 |
49 | 50 | -------------------------------------------------------------------------------- /anchor/views/intro.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <?php echo __('global.welcome_to_anchor'); ?> 7 | 8 | 41 | 42 | 43 |
44 | Anchor logo 45 |

46 | 47 |
48 | 49 | 55 | 56 | -------------------------------------------------------------------------------- /system/autoloader.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

title); ?>

5 |
6 | 7 |
8 | 9 | 10 |
11 | 12 | 13 | 14 |
15 |

16 | 17 | title)); ?> 18 | 19 |

20 |

21 | 22 | slug)); ?> 23 | 24 |

25 |

26 | 27 | description)); ?> 28 | 29 |

30 |
31 | 32 | 39 |
40 |
41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /anchor/views/assets/js/sortable.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Zepto sortable plugin using html5 drag and drop api. 3 | */ 4 | ;(function($) { 5 | $.fn.sortable = function(options) { 6 | 7 | var defaults = { 8 | element: 'li', 9 | dropped: function() {} 10 | }; 11 | 12 | var settings = $.extend({}, defaults, options); 13 | var sortables = $(this).find(settings.element); 14 | var dragsrc; 15 | 16 | var dragstart = function(event) { 17 | $(this).addClass('moving'); 18 | 19 | dragsrc = this; 20 | 21 | event.dataTransfer.effectAllowed = 'move'; 22 | event.dataTransfer.setData('text/html', this.innerHTML); 23 | }; 24 | 25 | var dragenter = function() { 26 | $(this).addClass('over'); 27 | } 28 | 29 | var dragleave = function() { 30 | $(this).removeClass('over'); 31 | }; 32 | 33 | var dragover = function(event) { 34 | event.preventDefault(); 35 | event.stopPropagation(); 36 | 37 | event.dataTransfer.dropEffect = 'move'; 38 | }; 39 | 40 | var drop = function(event) { 41 | event.preventDefault(); 42 | event.stopPropagation(); 43 | 44 | if (dragsrc != this) { 45 | dragsrc.innerHTML = this.innerHTML; 46 | 47 | this.innerHTML = event.dataTransfer.getData('text/html'); 48 | } 49 | 50 | settings.dropped(); 51 | }; 52 | 53 | var dragend = function() { 54 | $(this).removeClass('moving'); 55 | sortables.removeClass('over'); 56 | }; 57 | 58 | sortables.on('dragstart', dragstart); 59 | sortables.on('dragenter', dragenter); 60 | sortables.on('dragover', dragover); 61 | sortables.on('dragleave', dragleave); 62 | sortables.on('drop', drop); 63 | sortables.on('dragend', dragend); 64 | }; 65 | }(Zepto)); -------------------------------------------------------------------------------- /system/database/connectors/mysql.php: -------------------------------------------------------------------------------- 1 | pdo = new PDO($dns, $username, $password); 52 | $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 53 | } catch(PDOException $e) { 54 | throw new ErrorException($e->getMessage()); 55 | } 56 | } 57 | 58 | /** 59 | * Return the pdo instance 60 | * 61 | * @param object PDO Object 62 | */ 63 | public function instance() { 64 | return $this->pdo; 65 | } 66 | 67 | public function beginTransaction(){ 68 | $this->pdo->beginTransaction(); 69 | } 70 | 71 | public function commit(){ 72 | $this->pdo->commit(); 73 | } 74 | 75 | public function rollBack(){ 76 | $this->pdo->rollBack(); 77 | } 78 | } -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## Anchor CMS 2 | 3 | Anchor is a super-simple, lightweight blog system, made to let you just write. [Check out the site](http://anchorcms.com/). 4 | 5 | ### Requirements 6 | 7 | - PHP 5.3.6+ 8 | - curl 9 | - mcrypt 10 | - gd 11 | - pdo\_mysql or pdo\_sqlite 12 | - MySQL 5.2+ 13 | 14 | To determine your PHP version, create a new file with this PHP code: `queries[] = compact('sql', 'binds'); 43 | } 44 | 45 | $statement = $this->instance()->prepare($sql); 46 | $result = $statement->execute($binds); 47 | 48 | return array($result, $statement); 49 | } 50 | catch(Exception $e) { 51 | $error = 'Database Error: ' . $e->getMessage() . '

SQL: ' . trim($sql); 52 | throw new Exception($error, 0, $e); 53 | } 54 | } 55 | 56 | /** 57 | * Return the profile array 58 | * 59 | * @return array 60 | */ 61 | public function profile() { 62 | return $this->queries; 63 | } 64 | 65 | /** 66 | * Magic method for calling methods on PDO instance 67 | * 68 | * @param string 69 | * @param array 70 | * @return mixed 71 | */ 72 | public static function __callStatic($method, $arguments) { 73 | return call_user_func_array(array($this->instance(), $method), $arguments); 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /anchor/views/comments/edit.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 |

5 |
6 | 7 |
8 | 9 | 10 |
11 | 12 | 13 | 14 |
15 |

16 | 17 | name)); ?> 18 | 19 |

20 | 21 |

22 | 23 | email)); ?> 24 | 25 |

26 | 27 |

28 | 29 | text)); ?> 30 | 31 |

32 | 33 |

34 | 35 | status)); ?> 36 | 37 |

38 |
39 | 40 | 47 |
48 |
49 | 50 | -------------------------------------------------------------------------------- /anchor/libraries/html.php: -------------------------------------------------------------------------------- 1 | $val) { 19 | $pairs[] = $key . '="' . $val . '"'; 20 | } 21 | 22 | return ' ' . implode(' ', $pairs); 23 | } 24 | 25 | public static function entities($value) { 26 | return htmlentities($value, ENT_QUOTES, static::encoding(), false); 27 | } 28 | 29 | public static function decode($value) { 30 | return html_entity_decode($value, ENT_QUOTES, static::encoding()); 31 | } 32 | 33 | public static function specialchars($value) { 34 | return htmlspecialchars($value, ENT_QUOTES, static::encoding(), false); 35 | } 36 | 37 | public static function element($name, $content = '', $attributes = null) { 38 | $short = array('img', 'input', 'br', 'hr', 'frame', 'area', 'base', 'basefont', 39 | 'col', 'isindex', 'link', 'meta', 'param'); 40 | 41 | if(in_array($name, $short)) { 42 | if($content) $attributes['value'] = $content; 43 | 44 | return '<' . $name . static::attributes($attributes) . '>'; 45 | } 46 | 47 | return '<' . $name . static::attributes($attributes) . '>' . $content . ''; 48 | } 49 | 50 | public static function link($uri, $title = '', $attributes = array()) { 51 | if(strpos('#', $uri) !== 0) $uri = Uri::to($uri); 52 | 53 | if($title == '') $title = $uri; 54 | 55 | $attributes['href'] = $uri; 56 | 57 | return static::element('a', $title, $attributes); 58 | } 59 | 60 | } -------------------------------------------------------------------------------- /install/views/start.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |

Hello. Willkommen. Bonjour. Croeso.

6 | 7 |

If you were looking for a truly lightweight blogging experience, you’ve 8 | found the right place. Simply fill in the details below, and you’ll have your 9 | new blog set up in no time.

10 |
11 | 12 |
13 | 14 | 15 |
16 |

17 | 21 | 27 |

28 | 29 |

30 | 34 | 44 |

45 |
46 | 47 |
48 | 49 |
50 |
51 |
52 | 53 | -------------------------------------------------------------------------------- /anchor/libraries/migrations.php: -------------------------------------------------------------------------------- 1 | current = intval($current); 9 | } 10 | 11 | public function files($reverse = false) { 12 | $iterator = new FilesystemIterator(APP . 'migrations', FilesystemIterator::SKIP_DOTS); 13 | $files = array(); 14 | 15 | foreach($iterator as $file) { 16 | $parts = explode('_', $file->getBasename(EXT)); 17 | $num = array_shift($parts); 18 | 19 | $files[$num] = array( 20 | 'path' => $file->getPathname(), 21 | 'class' => 'Migration_' . implode('_', $parts) 22 | ); 23 | } 24 | 25 | if($reverse) { 26 | krsort($files, SORT_NUMERIC); 27 | } 28 | else { 29 | ksort($files, SORT_NUMERIC); 30 | } 31 | 32 | return $files; 33 | } 34 | 35 | public function up($to = null) { 36 | // sorted migration files 37 | $files = $this->files(); 38 | 39 | if(is_null($to)) $to = end(array_keys($files)); 40 | 41 | // run migrations 42 | foreach($files as $num => $item) { 43 | // upto 44 | if($num > $to) break; 45 | 46 | // starting from 47 | if($num < $this->current) continue; 48 | 49 | // run 50 | require $item['path']; 51 | 52 | $m = new $item['class']; 53 | 54 | $m->up(); 55 | } 56 | 57 | return $num; 58 | } 59 | 60 | public function down() { 61 | // reverse sorted migration files 62 | $files = $this->files(true); 63 | 64 | if(is_null($to)) $to = current(array_keys($files)); 65 | 66 | // run migrations 67 | foreach($files as $num => $item) { 68 | // upto 69 | if($num < $to) break; 70 | 71 | // starting from 72 | if($num > $this->current) continue; 73 | 74 | // run 75 | require $item['path']; 76 | 77 | $m = new $item['class']; 78 | 79 | $m->down(); 80 | } 81 | 82 | return $num; 83 | } 84 | 85 | } -------------------------------------------------------------------------------- /anchor/views/pages/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

5 | 6 | count): ?> 7 | 10 | 11 |
12 | 13 |
14 | 15 | 16 | 26 | 27 | count): ?> 28 | 45 | 46 | 47 | 48 | 49 | 54 | 55 |
56 | 57 | -------------------------------------------------------------------------------- /system/boot.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

5 | 6 | count): ?> 7 | 10 | 11 |
12 | 13 |
14 | 15 | 16 | 26 | 27 | count): ?> 28 | 46 | 47 | 48 | 49 | 50 | 51 |

52 | 53 |
54 | 'btn')); ?> 55 |

56 | 57 | 58 |
59 | 60 | -------------------------------------------------------------------------------- /install/config/strings.php: -------------------------------------------------------------------------------- 1 | array( 6 | '/æ|ǽ/' => 'ae', 7 | '/œ/' => 'oe', 8 | '/À|Á|Â|Ã|Ä|Å|Ǻ|Ā|Ă|Ą|Ǎ|А/' => 'A', 9 | '/à|á|â|ã|ä|å|ǻ|ā|ă|ą|ǎ|ª|а/' => 'a', 10 | '/Б/' => 'B', 11 | '/б/' => 'b', 12 | '/Ç|Ć|Ĉ|Ċ|Č|Ц/' => 'C', 13 | '/ç|ć|ĉ|ċ|č|ц/' => 'c', 14 | '/Ð|Ď|Đ|Д/' => 'Dj', 15 | '/ð|ď|đ|д/' => 'dj', 16 | '/È|É|Ê|Ë|Ē|Ĕ|Ė|Ę|Ě|Е|Ё|Э/' => 'E', 17 | '/è|é|ê|ë|ē|ĕ|ė|ę|ě|е|ё|э/' => 'e', 18 | '/Ф/' => 'F', 19 | '/ƒ|ф/' => 'f', 20 | '/Ĝ|Ğ|Ġ|Ģ|Г/' => 'G', 21 | '/ĝ|ğ|ġ|ģ|г/' => 'g', 22 | '/Ĥ|Ħ|Х/' => 'H', 23 | '/ĥ|ħ|х/' => 'h', 24 | '/Ì|Í|Î|Ï|Ĩ|Ī|Ĭ|Ǐ|Į|İ|И/' => 'I', 25 | '/ì|í|î|ï|ĩ|ī|ĭ|ǐ|į|ı|и/' => 'i', 26 | '/Ĵ|Й/' => 'J', 27 | '/ĵ|й/' => 'j', 28 | '/Ķ|К/' => 'K', 29 | '/ķ|к/' => 'k', 30 | '/Ĺ|Ļ|Ľ|Ŀ|Ł|Л/' => 'L', 31 | '/ĺ|ļ|ľ|ŀ|ł|л/' => 'l', 32 | '/М/' => 'M', 33 | '/м/' => 'm', 34 | '/Ñ|Ń|Ņ|Ň|Н/' => 'N', 35 | '/ñ|ń|ņ|ň|ʼn|н/' => 'n', 36 | '/Ö|Ò|Ó|Ô|Õ|Ō|Ŏ|Ǒ|Ő|Ơ|Ø|Ǿ|О/' => 'O', 37 | '/ö|ò|ó|ô|õ|ō|ŏ|ǒ|ő|ơ|ø|ǿ|º|о/' => 'o', 38 | '/П/' => 'P', 39 | '/п/' => 'p', 40 | '/Ŕ|Ŗ|Ř|Р/' => 'R', 41 | '/ŕ|ŗ|ř|р/' => 'r', 42 | '/Ś|Ŝ|Ş|Ș|Š|С/' => 'S', 43 | '/ś|ŝ|ş|ș|š|ſ|с/' => 's', 44 | '/Ţ|Ț|Ť|Ŧ|Т/' => 'T', 45 | '/ţ|ț|ť|ŧ|т/' => 't', 46 | '/Ù|Ú|Û|Ũ|Ū|Ŭ|Ů|Ü|Ű|Ų|Ư|Ǔ|Ǖ|Ǘ|Ǚ|Ǜ|У/' => 'U', 47 | '/ù|ú|û|ũ|ū|ŭ|ů|ü|ű|ų|ư|ǔ|ǖ|ǘ|ǚ|ǜ|у/' => 'u', 48 | '/В/' => 'V', 49 | '/в/' => 'v', 50 | '/Ý|Ÿ|Ŷ|Ы/' => 'Y', 51 | '/ý|ÿ|ŷ|ы/' => 'y', 52 | '/Ŵ/' => 'W', 53 | '/ŵ/' => 'w', 54 | '/Ź|Ż|Ž|З/' => 'Z', 55 | '/ź|ż|ž|з/' => 'z', 56 | '/Æ|Ǽ/' => 'AE', 57 | '/ß/'=> 'ss', 58 | '/IJ/' => 'IJ', 59 | '/ij/' => 'ij', 60 | '/Œ/' => 'OE', 61 | '/Ч/' => 'Ch', 62 | '/ч/' => 'ch', 63 | '/Ю/' => 'Ju', 64 | '/ю/' => 'ju', 65 | '/Я/' => 'Ja', 66 | '/я/' => 'ja', 67 | '/Ш/' => 'Sh', 68 | '/ш/' => 'sh', 69 | '/Щ/' => 'Shch', 70 | '/щ/' => 'shch', 71 | '/Ж/' => 'Zh', 72 | '/ж/' => 'zh', 73 | ) 74 | 75 | ); -------------------------------------------------------------------------------- /anchor/routes/metadata.php: -------------------------------------------------------------------------------- 1 | 'auth,csrf'), function() { 4 | 5 | /* 6 | List Metadata 7 | */ 8 | Route::get('admin/extend/metadata', function() { 9 | $vars['messages'] = Notify::read(); 10 | $vars['token'] = Csrf::token(); 11 | 12 | $vars['meta'] = Config::get('meta'); 13 | $vars['pages'] = Page::dropdown(); 14 | $vars['themes'] = Themes::all(); 15 | 16 | return View::create('extend/metadata/edit', $vars) 17 | ->partial('header', 'partials/header') 18 | ->partial('footer', 'partials/footer'); 19 | }); 20 | 21 | /* 22 | Update Metadata 23 | */ 24 | Route::post('admin/extend/metadata', function() { 25 | $input = Input::get(array('sitename', 'description', 'home_page', 'posts_page', 26 | 'posts_per_page', 'auto_published_comments', 'theme', 'comment_notifications', 'comment_moderation_keys')); 27 | 28 | $validator = new Validator($input); 29 | 30 | $validator->check('sitename') 31 | ->is_max(3, __('metadata.sitename_missing')); 32 | 33 | $validator->check('description') 34 | ->is_max(3, __('metadata.sitedescription_missing')); 35 | 36 | $validator->check('posts_per_page') 37 | ->is_regex('#^[0-9]+$#', __('metadata.missing_posts_per_page', 'Please enter a number for posts per page')); 38 | 39 | if($errors = $validator->errors()) { 40 | Input::flash(); 41 | 42 | Notify::error($errors); 43 | 44 | return Response::redirect('admin/extend/metadata'); 45 | } 46 | 47 | // convert double quotes so we dont break html 48 | $input['sitename'] = e($input['sitename'], ENT_COMPAT); 49 | $input['description'] = e($input['description'], ENT_COMPAT); 50 | 51 | foreach($input as $key => $value) { 52 | Query::table(Base::table('meta'))->where('key', '=', $key)->update(array('value' => $value)); 53 | } 54 | 55 | Notify::success(__('metadata.updated')); 56 | 57 | return Response::redirect('admin/extend/metadata'); 58 | }); 59 | 60 | }); -------------------------------------------------------------------------------- /themes/default/functions.php: -------------------------------------------------------------------------------- 1 | 4) ? 'th' : (($test < 4) ? ($test < 3) ? ($test < 2) ? ($test < 1) ? 'th' : 'st' : 'nd' : 'rd' : 'th')); 12 | return $number . $ext; 13 | } 14 | 15 | function count_words($str) { 16 | return count(preg_split('/\s+/', strip_tags($str), null, PREG_SPLIT_NO_EMPTY)); 17 | } 18 | 19 | function pluralise($amount, $str, $alt = '') { 20 | return intval($amount) === 1 ? $str : $str . ($alt !== '' ? $alt : 's'); 21 | } 22 | 23 | function relative_time($date) { 24 | if(is_numeric($date)) $date = '@' . $date; 25 | 26 | $user_timezone = new DateTimeZone(Config::app('timezone')); 27 | $date = new DateTime($date, $user_timezone); 28 | 29 | // get current date in user timezone 30 | $now = new DateTime('now', $user_timezone); 31 | 32 | $elapsed = $now->format('U') - $date->format('U'); 33 | 34 | if($elapsed <= 1) { 35 | return 'Just now'; 36 | } 37 | 38 | $times = array( 39 | 31104000 => 'year', 40 | 2592000 => 'month', 41 | 604800 => 'week', 42 | 86400 => 'day', 43 | 3600 => 'hour', 44 | 60 => 'minute', 45 | 1 => 'second' 46 | ); 47 | 48 | foreach($times as $seconds => $title) { 49 | $rounded = $elapsed / $seconds; 50 | 51 | if($rounded > 1) { 52 | $rounded = round($rounded); 53 | return $rounded . ' ' . pluralise($rounded, $title) . ' ago'; 54 | } 55 | } 56 | } 57 | 58 | function twitter_account() { 59 | return site_meta('twitter', 'idiot'); 60 | } 61 | 62 | function twitter_url() { 63 | return 'https://twitter.com/' . twitter_account(); 64 | } 65 | 66 | function total_articles() { 67 | return Post::where(Base::table('posts.status'), '=', 'published')->count(); 68 | } -------------------------------------------------------------------------------- /system/view.php: -------------------------------------------------------------------------------- 1 | 'Home')); 45 | * 46 | * @param string 47 | * @param array 48 | * @return object 49 | */ 50 | public static function __callStatic($method, $arguments) { 51 | $vars = count($arguments) ? current($arguments) : array(); 52 | return new static($method, $vars); 53 | } 54 | 55 | /** 56 | * Create a instance or the View class 57 | * 58 | * @param string 59 | * @param array 60 | */ 61 | public function __construct($path, $vars = array()) { 62 | $this->path = APP . 'views/' . $path . EXT; 63 | $this->vars = array_merge($this->vars, $vars); 64 | } 65 | 66 | /** 67 | * Render a partial view 68 | * 69 | * @return string 70 | */ 71 | public function partial($name, $path, $vars = array()) { 72 | $this->vars[$name] = static::create($path, $vars)->render(); 73 | 74 | return $this; 75 | } 76 | 77 | /** 78 | * Render the view 79 | * 80 | * @return string 81 | */ 82 | public function render() { 83 | ob_start(); 84 | 85 | extract($this->vars); 86 | 87 | require $this->path; 88 | 89 | return ob_get_clean(); 90 | } 91 | 92 | } -------------------------------------------------------------------------------- /anchor/functions/posts.php: -------------------------------------------------------------------------------- 1 | 0; 8 | } 9 | 10 | function posts() { 11 | $posts = Registry::get('posts'); 12 | 13 | if($result = $posts->valid()) { 14 | // register single post 15 | Registry::set('article', $posts->current()); 16 | 17 | // move to next 18 | $posts->next(); 19 | } 20 | // back to the start 21 | else $posts->rewind(); 22 | 23 | return $result; 24 | } 25 | 26 | function posts_next($text = 'Next →', $default = '') { 27 | $total = Registry::get('total_posts'); 28 | $offset = Registry::get('page_offset'); 29 | $per_page = Config::meta('posts_per_page'); 30 | $page = Registry::get('page'); 31 | $url = base_url($page->slug . '/'); 32 | 33 | // filter category 34 | if($category = Registry::get('post_category')) { 35 | $url = base_url('category/' . $category->slug . '/'); 36 | } 37 | 38 | $pagination = new Paginator(array(), $total, $offset, $per_page, $url); 39 | 40 | return $pagination->prev_link($text, $default); 41 | } 42 | 43 | function posts_prev($text = '← Previous', $default = '') { 44 | $total = Registry::get('total_posts'); 45 | $offset = Registry::get('page_offset'); 46 | $per_page = Config::meta('posts_per_page'); 47 | $page = Registry::get('page'); 48 | $url = base_url($page->slug . '/'); 49 | 50 | // filter category 51 | if($category = Registry::get('post_category')) { 52 | $url = base_url('category/' . $category->slug . '/'); 53 | } 54 | 55 | $pagination = new Paginator(array(), $total, $offset, $per_page, $url); 56 | 57 | return $pagination->next_link($text, $default); 58 | } 59 | 60 | function total_posts() { 61 | return Registry::get('total_posts'); 62 | } 63 | 64 | function has_pagination() { 65 | return Registry::get('total_posts') > Config::meta('posts_per_page'); 66 | } 67 | 68 | function posts_per_page() { 69 | return min(Registry::get('total_posts'), Config::meta('posts_per_page')); 70 | } -------------------------------------------------------------------------------- /anchor/libraries/themes.php: -------------------------------------------------------------------------------- 1 | isDir()) { 11 | $theme = $file->getFilename(); 12 | 13 | if($about = static::parse($theme)) { 14 | $themes[$theme] = $about; 15 | } 16 | } 17 | } 18 | 19 | ksort($themes); 20 | 21 | return $themes; 22 | } 23 | 24 | public static function parse($theme) { 25 | $file = PATH . 'themes/' . $theme . '/about.txt'; 26 | 27 | if( ! is_readable($file)) { 28 | return false; 29 | } 30 | 31 | // read file into a array 32 | $contents = explode("\n", trim(file_get_contents($file))); 33 | $about = array(); 34 | 35 | foreach(array('name', 'description', 'author', 'site', 'license') as $index => $key) { 36 | // temp value 37 | $about[$key] = ''; 38 | 39 | // find line if exists 40 | if( ! isset($contents[$index])) { 41 | continue; 42 | } 43 | 44 | $line = $contents[$index]; 45 | 46 | // skip if not separated by a colon character 47 | if(strpos($line, ":") === false) { 48 | continue; 49 | } 50 | 51 | $parts = explode(":", $line); 52 | 53 | // remove the key part 54 | array_shift($parts); 55 | 56 | // in case there was a colon in our value part glue it back together 57 | $value = implode('', $parts); 58 | 59 | $about[$key] = trim($value); 60 | } 61 | 62 | return $about; 63 | } 64 | 65 | public static function templates($theme) { 66 | $templates = array(); 67 | $fi = new FilesystemIterator(PATH . 'themes/' . $theme, FilesystemIterator::SKIP_DOTS); 68 | 69 | foreach($fi as $file) { 70 | $ext = pathinfo($file->getFilename(), PATHINFO_EXTENSION); 71 | $base = $file->getBasename('.' . $ext); 72 | 73 | if($file->isFile() and $ext == 'php') { 74 | $templates[$base] = $base; 75 | } 76 | } 77 | 78 | return $templates; 79 | } 80 | 81 | } -------------------------------------------------------------------------------- /anchor/functions/helpers.php: -------------------------------------------------------------------------------- 1 | valid()) { 14 | Registry::set('menu_item', $pages->current()); 15 | 16 | $pages->next(); 17 | } 18 | 19 | // back to the start 20 | if( ! $result) $pages->rewind(); 21 | 22 | return $result; 23 | } 24 | 25 | /* 26 | Object props 27 | */ 28 | function menu_id() { 29 | return Registry::prop('menu_item', 'id'); 30 | } 31 | 32 | function menu_url() { 33 | if($page = Registry::get('menu_item')) { 34 | return $page->uri(); 35 | } 36 | } 37 | 38 | function menu_relative_url() { 39 | if($page = Registry::get('menu_item')) { 40 | return $page->relative_uri(); 41 | } 42 | } 43 | 44 | function menu_name() { 45 | return Registry::prop('menu_item', 'name'); 46 | } 47 | 48 | function menu_title() { 49 | return Registry::prop('menu_item', 'title'); 50 | } 51 | 52 | function menu_active() { 53 | if($page = Registry::get('menu_item')) { 54 | return $page->active(); 55 | } 56 | } 57 | 58 | function menu_parent() { 59 | return Registry::prop('menu_item', 'parent'); 60 | } 61 | 62 | /* 63 | HTML Builders 64 | */ 65 | function menu_render($params = array()) { 66 | $html = ''; 67 | $menu = Registry::get('menu'); 68 | 69 | // options 70 | $parent = isset($params['parent']) ? $params['parent'] : 0; 71 | $class = isset($params['class']) ? $params['class'] : 'active'; 72 | 73 | foreach($menu as $item) { 74 | if($item->parent == $parent) { 75 | $attr = array(); 76 | 77 | if($item->active()) $attr['class'] = $class; 78 | 79 | $html .= '
  • '; 80 | $html .= Html::link($item->relative_uri(), $item->name, $attr); 81 | $html .= menu_render(array('parent' => $item->id)); 82 | $html .= '
  • ' . PHP_EOL; 83 | } 84 | } 85 | 86 | if($html) $html = PHP_EOL . '' . PHP_EOL; 87 | 88 | return $html; 89 | } -------------------------------------------------------------------------------- /system/database.php: -------------------------------------------------------------------------------- 1 | profile(); 67 | } 68 | 69 | /** 70 | * Magic method for calling database driver methods on the default connection 71 | * 72 | * @param string 73 | * @param array 74 | * @return mixed 75 | */ 76 | public static function __callStatic($method, $arguments) { 77 | return call_user_func_array(array(static::connection(), $method), $arguments); 78 | } 79 | 80 | } -------------------------------------------------------------------------------- /anchor/language/en_GB/global.php: -------------------------------------------------------------------------------- 1 | 'Save', 13 | 'delete' => 'Delete', 14 | 'update' => 'Update', 15 | 'edit' => 'Edit', 16 | 'editing' => 'Editing', 17 | 'create' => 'Create', 18 | 'created' => 'Created', 19 | 'submit' => 'Submit', 20 | 'close' => 'Close', 21 | 'status' => 'Status', 22 | 'manage' => 'Manage', 23 | 'reset' => 'Reset', 24 | 'all' => 'All', 25 | 26 | // pagination 27 | 'next' => 'Next', 28 | 'previous' => 'Previous', 29 | 'first' => 'First', 30 | 'last' => 'Last', 31 | 32 | // statuses 33 | 'draft' => 'Draft', 34 | 'archived' => 'Archived', 35 | 'published' => 'Published', 36 | 'pending' => 'Pending', 37 | 'approved' => 'Approved', 38 | 'spam' => 'Spam', 39 | 40 | 'inactive' => 'Inactive', 41 | 'active' => 'Active', 42 | 43 | // roles 44 | 'administrator' => 'Admin', 45 | 'editor' => 'Editor', 46 | 'user' => 'User', 47 | 48 | 'log_in' => 'Log in', 49 | 'login' => 'Login', 50 | 'log_out' => 'Log out', 51 | 'logout' => 'Logout', 52 | 53 | // pharses 54 | 'visit_your_site' => 'Visit your site', 55 | 'powered_by_anchor' => 'Powered by Anchor, version %s', 56 | 'make_blogging_beautiful' => 'Make blogging beautiful.', 57 | 58 | // intro 59 | 'welcome_to_anchor' => 'Welcome to Anchor', 60 | 'welcome_to_anchor_lets_go' => 'Welcome to Anchor. Let’s go.', 61 | 'run_the_installer' => 'Run the installer', 62 | 63 | // upgrade 64 | 'upgrade' => 'Upgrade', 65 | 'good_news' => 'Great News!', 66 | 'new_version_available' => 'There\'s a new version of anchor available.', 67 | 'download_now' => 'Download Now', 68 | 'upgrade_later' => 'Upgrade later', 69 | 70 | // debug profiler 71 | 'profile' => 'Profile', 72 | 'profile_memory_usage' => 'Total memory usage', 73 | 74 | // messages 75 | 'confirm_delete' => 'Are you sure you want to delete? This can’t be undone!' 76 | 77 | ); -------------------------------------------------------------------------------- /anchor/language/en_GB/users.php: -------------------------------------------------------------------------------- 1 | 'Users', 6 | 7 | 'create_user' => 'Create a new user', 8 | 'add_user' => 'Add a new user', 9 | 'editing_user' => 'Editing %s’s Profile', 10 | 'remembered' => 'I know my password', 11 | 'forgotten_password' => 'Forgotten your password?', 12 | 13 | // roles 14 | 'administrator' => 'Admin', 15 | 'administrator_explain' => '', 16 | 17 | 'editor' => 'Editor', 18 | 'editor_explain' => '', 19 | 20 | 'user' => 'User', 21 | 'user_explain' => '', 22 | 23 | // form fields 24 | 'real_name' => 'Real Name', 25 | 'real_name_explain' => '', 26 | 27 | 'bio' => 'Biography', 28 | 'bio_explain' => '', 29 | 30 | 'status' => 'Status', 31 | 'status_explain' => '', 32 | 33 | 'role' => 'Role', 34 | 'role_explain' => '', 35 | 36 | 'username' => 'Username', 37 | 'username_explain' => '', 38 | 'username_missing' => 'Please enter a username, must be at least %s characters', 39 | 40 | 'password' => 'Password', 41 | 'password_explain' => '', 42 | 'password_too_short' => 'Password must be at least %s characters', 43 | 44 | 'new_password' => 'New Password', 45 | 46 | 'email' => 'Email', 47 | 'email_explain' => '', 48 | 'email_missing' => 'Please enter a valid email address', 49 | 'email_not_found' => 'Profile not found.', 50 | 51 | // messages 52 | 'updated' => 'User profile updated.', 53 | 'created' => 'User profile created.', 54 | 'deleted' => 'User profile deleted.', 55 | 'delete_error' => 'You cannot delete your own profile', 56 | 'login_error' => 'Username or password is wrong.', 57 | 'logout_notice' => 'You are now logged out.', 58 | 'recovery_sent' => 'We have sent you an email to confirm your password change.', 59 | 'recovery_expired' => 'Password recovery token has expired, please try again.', 60 | 'password_reset' => 'Your new password has been set. Go and login now!', 61 | 62 | // password recovery email 63 | 'recovery_subject' => 'Password Reset', 64 | 'recovery_message' => 'You have requested to reset your password.' . 65 | 'To continue follow the link below.' . PHP_EOL . '%s', 66 | 67 | ); -------------------------------------------------------------------------------- /system/input.php: -------------------------------------------------------------------------------- 1 | where(Base::table('posts.'.$row), '=', $val) 18 | ->fetch(array(Base::table('posts.*'), 19 | Base::table('users.id as author_id'), 20 | Base::table('users.bio as author_bio'), 21 | Base::table('users.real_name as author_name'))); 22 | } 23 | 24 | public static function listing($category = null, $page = 1, $per_page = 10) { 25 | // get total 26 | $query = static::left_join(Base::table('users'), Base::table('users.id'), '=', Base::table('posts.author')) 27 | ->where(Base::table('posts.status'), '=', 'published'); 28 | 29 | if($category) { 30 | $query->where(Base::table('posts.category'), '=', $category->id); 31 | } 32 | 33 | $total = $query->count(); 34 | 35 | // get posts 36 | $posts = $query->sort(Base::table('posts.created'), 'desc') 37 | ->take($per_page) 38 | ->skip(--$page * $per_page) 39 | ->get(array(Base::table('posts.*'), 40 | Base::table('users.id as author_id'), 41 | Base::table('users.bio as author_bio'), 42 | Base::table('users.real_name as author_name'))); 43 | 44 | return array($total, $posts); 45 | } 46 | 47 | public static function search($term, $page = 1, $per_page = 10) { 48 | $query = static::left_join(Base::table('users'), Base::table('users.id'), '=', Base::table('posts.author')) 49 | ->where(Base::table('posts.status'), '=', 'published') 50 | ->where(Base::table('posts.title'), 'like', '%' . $term . '%'); 51 | 52 | $total = $query->count(); 53 | 54 | $posts = $query->take($per_page) 55 | ->skip(--$page * $per_page) 56 | ->get(array(Base::table('posts.*'), 57 | Base::table('users.id as author_id'), 58 | Base::table('users.bio as author_bio'), 59 | Base::table('users.real_name as author_name'))); 60 | 61 | return array($total, $posts); 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /anchor/views/users/add.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
    4 |

    5 |
    6 | 7 |
    8 | 9 | 10 |
    11 | 12 | 13 | 14 |
    15 |

    16 | 17 | 18 | 19 |

    20 |

    21 | 22 | 20)); ?> 23 | 24 |

    25 |

    26 | 27 | 28 | 29 |

    30 |

    31 | 32 | 33 | 34 |

    35 |
    36 | 37 |
    38 |

    39 | 40 | 41 | 42 |

    43 |

    44 | 45 | 46 | 47 |

    48 |

    49 | 50 | 51 | 52 |

    53 |
    54 | 55 | 58 |
    59 | 60 |
    61 | 62 | -------------------------------------------------------------------------------- /anchor/libraries/update.php: -------------------------------------------------------------------------------- 1 | insert(array('key' => 'last_update_check', 'value' => $today)); 23 | Query::table($table)->insert(array('key' => 'update_version', 'value' => $version)); 24 | 25 | // reload database metadata 26 | foreach(Query::table($table)->get() as $item) { 27 | $meta[$item->key] = $item->value; 28 | } 29 | 30 | Config::set('meta', $meta); 31 | } 32 | 33 | public static function renew() { 34 | $version = static::touch(); 35 | $today = date('Y-m-d H:i:s'); 36 | $table = Base::table('meta'); 37 | 38 | Query::table($table)->where('key', '=', 'last_update_check')->update(array('value' => $today)); 39 | Query::table($table)->where('key', '=', 'update_version')->update(array('value' => $version)); 40 | 41 | // reload database metadata 42 | foreach(Query::table($table)->get() as $item) { 43 | $meta[$item->key] = $item->value; 44 | } 45 | 46 | Config::set('meta', $meta); 47 | } 48 | 49 | public static function touch() { 50 | $url = 'http://anchorcms.com/version'; 51 | 52 | if(in_array(ini_get('allow_url_fopen'), array('true', '1', 'On'))) { 53 | try { 54 | $context = stream_context_create(array('http' => array('timeout' => 2))); 55 | $result = file_get_contents($url, false, $context); 56 | } catch(Exception $e) { 57 | $result = false; 58 | } 59 | } 60 | else if(function_exists('curl_init')) { 61 | $session = curl_init(); 62 | 63 | curl_setopt_array($session, array( 64 | CURLOPT_URL => $url, 65 | CURLOPT_HEADER => false, 66 | CURLOPT_RETURNTRANSFER => true 67 | )); 68 | 69 | $result = curl_exec($session); 70 | 71 | curl_close($session); 72 | } 73 | else { 74 | $result = false; 75 | } 76 | 77 | return $result; 78 | } 79 | 80 | } -------------------------------------------------------------------------------- /themes/default/js/main.js: -------------------------------------------------------------------------------- 1 | var Anchor = { 2 | init: function() { 3 | Anchor.slidey = $('.slidey'); 4 | Anchor.keys = []; 5 | 6 | // Uh, bind to the resizing of the window? 7 | $(window).resize(Anchor.bindResize).trigger('resize'); 8 | 9 | // Re-/Set keys 10 | $(window).on('keyup', Anchor.keyup); 11 | $(window).on('keydown', Anchor.keydown); 12 | 13 | // Set up the toggle link 14 | Anchor.linky = $('.linky').on('click', Anchor.toggleSlidey); 15 | 16 | // Hide the thingymabob 17 | setTimeout(function() { 18 | // Set up the slidey panel 19 | Anchor.hideSlidey(); 20 | 21 | $('body').addClass('js-enabled'); 22 | }, 10); 23 | 24 | // Listen for search link 25 | $('a[href="#search"]').click(function() { 26 | if(!Anchor.linky.hasClass('active')) { 27 | return Anchor.toggleSlidey.call(Anchor.linky); 28 | } 29 | }); 30 | }, 31 | 32 | keyup: function(event) { 33 | Anchor.keys[event.keyCode] = false; 34 | }, 35 | 36 | keydown: function(event) { 37 | Anchor.keys[event.keyCode] = true; 38 | 39 | // ctrl + shift + f => show Slidey and/or focus search bar 40 | if(Anchor.keys[17] && Anchor.keys[16] && Anchor.keys[70]) { 41 | event.preventDefault(); 42 | 43 | Anchor.showSlidey.call(Anchor.linky); 44 | $('input[type="search"]').focus(); 45 | } 46 | 47 | // esc => hide Slidey 48 | if(Anchor.keys[27]) { 49 | event.preventDefault(); 50 | 51 | Anchor.hideSlidey(); 52 | $('input[type="search"]').blur(); 53 | } 54 | }, 55 | 56 | hideSlidey: function() { 57 | Anchor.slidey.css('margin-top', this._slideyHeight); 58 | Anchor.linky && Anchor.linky.removeClass('active'); 59 | 60 | return this; 61 | }, 62 | 63 | showSlidey: function() { 64 | Anchor.slidey.css('margin-top', 0); 65 | Anchor.linky && Anchor.linky.addClass('active'); 66 | 67 | return this; 68 | }, 69 | 70 | toggleSlidey: function() { 71 | var self = Anchor; 72 | var me = $(this); 73 | 74 | me.toggleClass('active'); 75 | self.slidey.css('margin-top', me.hasClass('active') ? 0 : self._slideyHeight); 76 | 77 | return false; 78 | }, 79 | 80 | bindResize: function() { 81 | Anchor._slideyHeight = -(Anchor.slidey.height() + 1); 82 | Anchor.hideSlidey(); 83 | } 84 | }; 85 | 86 | // And bind loading 87 | $(Anchor.init); 88 | -------------------------------------------------------------------------------- /anchor/functions/search.php: -------------------------------------------------------------------------------- 1 | 0; 8 | } 9 | 10 | function total_search_results() { 11 | return Registry::get('total_posts', 0); 12 | } 13 | 14 | function search_results() { 15 | $posts = Registry::get('search_results'); 16 | 17 | if($result = $posts->valid()) { 18 | // register single post 19 | Registry::set('article', $posts->current()); 20 | 21 | // move to next 22 | $posts->next(); 23 | } 24 | 25 | return $result; 26 | } 27 | 28 | function search_term() { 29 | return Registry::get('search_term'); 30 | } 31 | 32 | function has_search_pagination() { 33 | return Registry::get('total_posts') > Config::meta('posts_per_page'); 34 | } 35 | 36 | function search_next($text = 'Next', $default = '') { 37 | $per_page = Config::meta('posts_per_page'); 38 | $page = Registry::get('page_offset'); 39 | 40 | $offset = ($page - 1) * $per_page; 41 | $total = Registry::get('total_posts'); 42 | 43 | $pages = floor($total / $per_page); 44 | 45 | $search_page = Registry::get('page'); 46 | $next = $page + 1; 47 | $term = Registry::get('search_term'); 48 | Session::put(slug($term), $term); 49 | 50 | $url = base_url($search_page->slug . '/' . $term . '/' . $next); 51 | 52 | if(($page - 1) < $pages) { 53 | return '' . $text . ''; 54 | } 55 | 56 | return $default; 57 | } 58 | 59 | function search_prev($text = 'Previous', $default = '') { 60 | $per_page = Config::get('meta.posts_per_page'); 61 | $page = Registry::get('page_offset'); 62 | 63 | $offset = ($page - 1) * $per_page; 64 | $total = Registry::get('total_posts'); 65 | 66 | $pages = ceil($total / $per_page); 67 | 68 | $search_page = Registry::get('page'); 69 | $prev = $page - 1; 70 | $term = Registry::get('search_term'); 71 | Session::put(slug($term), $term); 72 | 73 | $url = base_url($search_page->slug . '/' . $term . '/' . $prev); 74 | 75 | if($offset > 0) { 76 | return '' . $text . ''; 77 | } 78 | 79 | return $default; 80 | } 81 | 82 | function search_url() { 83 | return base_url('search'); 84 | } 85 | 86 | function search_form_input($extra = '') { 87 | return ''; 88 | } -------------------------------------------------------------------------------- /themes/default/article.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
    4 |

    5 | 6 |
    7 | 8 |
    9 | 10 |
    11 | 12 |

    This article is my oldest. It is words long, and it’s got for now.

    13 |
    14 |
    15 | 16 | 17 |
    18 | 19 | 35 | 36 | 37 |
    38 | 39 | 40 |

    41 | 42 | 43 |

    44 | 45 | 49 | 50 |

    51 | 52 | 53 |

    54 | 55 |

    56 | 57 |

    58 |
    59 | 60 |
    61 | 62 | 63 | -------------------------------------------------------------------------------- /anchor/views/partials/header.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | <?php echo __('global.manage'); ?> <?php echo Config::meta('sitename'); ?> 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
    24 |
    25 | 26 | 42 | 43 | 'btn')); ?> 44 | 45 | 46 | 47 | slug, __('global.visit_your_site'), array('class' => 'btn', 'target' => '_blank')); ?> 48 | 49 | 50 | 53 | 54 |
    55 |
    -------------------------------------------------------------------------------- /anchor/libraries/paginator.php: -------------------------------------------------------------------------------- 1 | results = $results; 17 | $this->count = $count; 18 | $this->page = $page; 19 | $this->perpage = $perpage; 20 | $this->url = rtrim($url, '/'); 21 | } 22 | 23 | public function next_link($text = null, $default = '') { 24 | if(is_null($text)) $text = $this->next; 25 | 26 | $pages = ceil($this->count / $this->perpage); 27 | 28 | if($this->page < $pages) { 29 | $page = $this->page + 1; 30 | 31 | return '' . $text . ''; 32 | } 33 | 34 | return $default; 35 | } 36 | 37 | public function prev_link($text = null, $default = '') { 38 | if(is_null($text)) $text = $this->prev; 39 | 40 | if($this->page > 1) { 41 | $page = $this->page - 1; 42 | 43 | return '' . $text . ''; 44 | } 45 | 46 | return $default; 47 | } 48 | 49 | public function links() { 50 | $html = ''; 51 | 52 | $pages = ceil($this->count / $this->perpage); 53 | $range = 4; 54 | 55 | if($pages > 1) { 56 | 57 | if($this->page > 1) { 58 | $page = $this->page - 1; 59 | 60 | $html = '' . $this->first . ' 61 | ' . $this->prev . ''; 62 | } 63 | 64 | for($i = $this->page - $range; $i < $this->page + $range; $i++) { 65 | if($i < 0) continue; 66 | 67 | $page = $i + 1; 68 | 69 | if($page > $pages) break; 70 | 71 | if($page == $this->page) { 72 | $html .= ' ' . $page . ' '; 73 | } 74 | else { 75 | $html .= ' ' . $page . ' '; 76 | } 77 | } 78 | 79 | if($this->page < $pages) { 80 | $page = $this->page + 1; 81 | 82 | $html .= '' . $this->next . ' 83 | ' . $this->last . ''; 84 | } 85 | 86 | } 87 | 88 | return $html; 89 | } 90 | 91 | } -------------------------------------------------------------------------------- /anchor/language/en_GB/extend.php: -------------------------------------------------------------------------------- 1 | 'Extend', 6 | 7 | 'fields' => 'Custom Fields', 8 | 'fields_desc' => 'Create additional fields', 9 | 10 | 'variables' => 'Site Variables', 11 | 'variables_desc' => 'Create additional metadata', 12 | 13 | 'create_field' => 'Create a new field', 14 | 'editing_custom_field' => 'Editing field “%s”', 15 | 'nofields_desc' => 'No fields yet', 16 | 17 | 'create_variable' => 'Create a new variable', 18 | 'editing_variable' => 'Editing variable “%s”', 19 | 'novars_desc' => 'No variables yet', 20 | 21 | // form fields 22 | 'type' => 'Type', 23 | 'type_explain' => 'The type of content you want to add this field to.', 24 | 25 | 'field' => 'Field', 26 | 'field_explain' => 'Html input type', 27 | 28 | 'key' => 'Unique Key', 29 | 'key_explain' => 'The unique key for your field', 30 | 'key_missing' => 'Please enter a unique key', 31 | 'key_exists' => 'Key is already in use', 32 | 33 | 'label' => 'Label', 34 | 'label_explain' => 'Human readable name for your field', 35 | 'label_missing' => 'Please enter a label', 36 | 37 | 'attribute_type' => 'File types', 38 | 'attribute_type_explain' => 'Comma separated list of accepted file types, empty to accept all.', 39 | 40 | // images 41 | 'attributes_size_width' => 'Image max width', 42 | 'attributes_size_width_explain' => 'Images will be resized if they are bigger than the max size', 43 | 44 | 'attributes_size_height' => 'Image max height', 45 | 'attributes_size_height_explain' => 'Images will be resized if they are bigger than the max size', 46 | 47 | // custom vars 48 | 'name' => 'Name', 49 | 'name_explain' => 'A unique name', 50 | 'name_missing' => 'Please enter a unique name', 51 | 'name_exists' => 'Name is already in use', 52 | 53 | 'value' => 'Value', 54 | 'value_explain' => 'The data you want to store (up to 64kb)', 55 | 'value_code_snipet' => 'Snippet to insert into your template:
    56 | ' . e('') . '', 57 | 58 | // messages 59 | 'variable_created' => 'Your variable was created', 60 | 'variable_updated' => 'Your variable was updated', 61 | 'variable_deleted' => 'Your variable was deleted', 62 | 63 | 'field_created' => 'Your field was created', 64 | 'field_updated' => 'Your field was updated', 65 | 'field_deleted' => 'Your field was deleted' 66 | 67 | ); 68 | -------------------------------------------------------------------------------- /anchor/views/assets/js/dragdrop.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Drag and Drop upload 3 | * 4 | * Allows the drag and drop of single files into posts 5 | */ 6 | $(function() { 7 | var zone = $(document), body = $('body'); 8 | var allowed = ['text/css', 'text/javascript', 'application/javascript', 'text/x-markdown']; 9 | 10 | var cancel = function(event) { 11 | event.preventDefault(); 12 | return false; 13 | }; 14 | 15 | var open = function(event) { 16 | event.preventDefault(); 17 | body.addClass('draggy'); 18 | return false; 19 | }; 20 | 21 | var close = function(event) { 22 | event.preventDefault(); 23 | body.removeClass('draggy'); 24 | return false; 25 | }; 26 | 27 | var drop = function(event) { 28 | event.preventDefault(); 29 | 30 | var files = event.target.files || event.dataTransfer.files; 31 | 32 | for(var i = 0; i < files.length; i++) { 33 | var file = files.item(i); 34 | 35 | if(allowed.indexOf(file.type) !== -1) { 36 | transfer(file); 37 | } 38 | } 39 | 40 | body.removeClass('draggy'); 41 | 42 | return false; 43 | }; 44 | 45 | var transfer = function(file) { 46 | var reader = new FileReader(); 47 | reader.file = file; 48 | reader.callback = complete; 49 | reader.onload = reader.callback; 50 | reader.readAsText(file); 51 | }; 52 | 53 | var complete = function() { 54 | if(['text/css'].indexOf(this.file.type) !== -1) { 55 | $('textarea[name=css]').val(this.result).parent().show(); 56 | } 57 | 58 | if(['text/javascript', 'application/javascript'].indexOf(this.file.type) !== -1) { 59 | $('textarea[name=js]').val(this.result).parent().show(); 60 | } 61 | 62 | if(['text/x-markdown'].indexOf(this.file.type) !== -1) { 63 | var textarea = $('textarea[name=html]'), value = textarea.val(); 64 | 65 | textarea.val(this.result).trigger('keydown'); 66 | } 67 | }; 68 | 69 | if(window.FileReader && window.FileList && window.File) { 70 | zone.on('dragover', open); 71 | zone.on('dragenter', cancel); 72 | zone.on('drop', drop); 73 | zone.on('dragleave', cancel); 74 | zone.on('dragexit', close); 75 | 76 | body.append('
    Upload your file
    '); 77 | 78 | // hide drag/drop inputs until populated 79 | $('textarea[name=css],textarea[name=js]').each(function(index, item) { 80 | var element = $(item); 81 | 82 | if(element.val() == '') { 83 | element.parent().hide(); 84 | } 85 | }); 86 | } 87 | }); -------------------------------------------------------------------------------- /system/session.php: -------------------------------------------------------------------------------- 1 | read(); 73 | } 74 | 75 | /** 76 | * Write the current session using the driver set in the config file 77 | */ 78 | public static function write() { 79 | static::instance()->write(); 80 | } 81 | 82 | /** 83 | * Magic method to call a method on the session driver 84 | * 85 | * @param string 86 | * @param array 87 | */ 88 | public static function __callStatic($method, $arguments) { 89 | $cargo = static::instance(); 90 | 91 | if(method_exists($cargo, $method)) { 92 | return call_user_func_array(array($cargo, $method), $arguments); 93 | } 94 | 95 | throw new ErrorException('Unknown session method'); 96 | } 97 | 98 | } -------------------------------------------------------------------------------- /anchor/views/users/edit.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
    4 |

    username); ?>

    5 |
    6 | 7 |
    8 | 9 | 10 |
    11 | 12 | 13 | 14 |
    15 |

    16 | 17 | real_name)); ?> 18 | 19 |

    20 |

    21 | 22 | bio), array('cols' => 20)); ?> 23 | 24 |

    25 |

    26 | 27 | status)); ?> 28 | 29 |

    30 |

    31 | 32 | role)); ?> 33 | 34 |

    35 |
    36 | 37 |
    38 |

    39 | 40 | username)); ?> 41 | 42 |

    43 |

    44 | 45 | 46 | 47 |

    48 |

    49 | 50 | email)); ?> 51 | 52 |

    53 |
    54 | 55 | 63 |
    64 | 65 |
    66 | 67 | -------------------------------------------------------------------------------- /themes/default/css/reset.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Anchor, default reset 3 | */ 4 | * { 5 | margin: 0; 6 | padding: 0; 7 | 8 | -webkit-font-smoothing: antialiased; 9 | 10 | /* Don't count padding and borders towards widths */ 11 | -webkit-box-sizing: border-box; 12 | -moz-box-sizing: border-box; 13 | box-sizing: border-box; 14 | } 15 | 16 | /** 17 | * Typographic reset 18 | */ 19 | body { 20 | /* Use a serif font for nice readability, but not Times */ 21 | font: 17px/26px Skolar, Tisa, "Chaparral Pro", Merriweather, Georgia, serif; 22 | } 23 | 24 | h1, h2, h3, h4, h5, #logo, #top, .slidey b, .slidey label, .counter, input, textarea, button, .pagination { 25 | font-family: "Helvetica Neue", sans-serif; 26 | font-weight: 300; 27 | } 28 | 29 | pre, code, .mono { 30 | font: 12px/19px "Anonymous Pro", Consolas, monospace; 31 | padding: 0 2px; 32 | } 33 | 34 | p { 35 | padding-bottom: 15px; 36 | } 37 | 38 | pre { 39 | padding: 15px 20px; 40 | margin-bottom: 20px; 41 | 42 | border-radius: 5px; 43 | white-space: pre-wrap; 44 | } 45 | 46 | img { 47 | max-width: 100%; 48 | height: auto; 49 | } 50 | 51 | a { 52 | text-decoration: none; 53 | } 54 | a img { 55 | border: none; 56 | } 57 | 58 | /** 59 | * Layout reset 60 | */ 61 | .wrap { 62 | min-width: 280px; 63 | max-width: 750px; 64 | width: 60%; 65 | 66 | margin: 0 auto; 67 | } 68 | 69 | /** 70 | * Default colours 71 | */ 72 | body, .items > li:first-child { 73 | color: #6e7886; 74 | } 75 | a, .items h1 a:hover { 76 | color: #4075c3; 77 | } 78 | a:hover { 79 | color: #1e4d92; 80 | } 81 | 82 | pre, .hilite, mark { 83 | background: #f9f6ea; 84 | color: #8b7c65; 85 | text-shadow: 0 1px 0 rgba(255,255,255,.2); 86 | } 87 | 88 | input, textarea { 89 | color: #697281; 90 | } 91 | ::-webkit-input-placeholder { 92 | color: #b2b9c5; 93 | } 94 | :-moz-placeholder, :placeholder { 95 | color: #b2b9c5; 96 | } 97 | 98 | .error, .success { 99 | padding: 20px 30px; 100 | margin-bottom: 30px; 101 | 102 | background: #e25d47; 103 | color: #fff; 104 | 105 | border-radius: 5px; 106 | } 107 | .success { 108 | background: #88be33; 109 | } 110 | .error p, .success p { 111 | float: none !important; 112 | width: 100%; 113 | padding: 0; 114 | margin: 0 !important; 115 | } 116 | 117 | /** 118 | * Transitions and animations 119 | */ 120 | a, a img { 121 | -webkit-transition: opacity .2s, color .2s; 122 | -moz-transition: opacity .2s, color .2s; 123 | transition: opacity .2s, color .2s; 124 | } -------------------------------------------------------------------------------- /install/views/database.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
    4 |
    5 |

    Your database details

    6 | 7 |

    Firstly, we’ll need a database. Anchor needs them to store all of your blog’s information, so it’s vital you fill these in correctly. If you don’t know what these are, you’ll need to contact your webhost.

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

    15 | 16 | 17 | 18 | Most likely localhost or 127.0.0.1. 19 |

    20 | 21 |

    22 | 23 | 24 | 25 | Usually 3306. 26 |

    27 | 28 |

    29 | 30 | 31 | 32 | The database user, usually root. 33 |

    34 | 35 |

    36 | 37 | 38 | 39 | Leave blank for empty password. 40 |

    41 | 42 |

    43 | 44 | 45 | 46 | Your database’s name. 47 |

    48 | 49 |

    50 | 51 | 52 | 53 | Database table name prefix. 54 |

    55 | 56 |

    57 | 58 | 66 | 67 | Change if utf8_general_ci doesn’t work. 68 |

    69 |
    70 | 71 |
    72 | « Back 73 | 74 |
    75 |
    76 |
    77 | 78 | -------------------------------------------------------------------------------- /anchor/models/comment.php: -------------------------------------------------------------------------------- 1 | id); 9 | 10 | $headers = 'MIME-Version: 1.0' . "\r\n"; 11 | $headers .= 'Content-type: text/html; charset=utf-8' . "\r\n"; 12 | $headers .= 'From: notifications@' . $_SERVER['HTTP_HOST'] . "\r\n"; 13 | 14 | $message = ' 15 | 16 | ' . __('comments.notify_subject') . ' 17 | 23 | 24 | 25 |

    ' . __('comments.nofity_heading') . '

    26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
    ' . __('comments.name') . '' . $this->name . '
    ' . __('comments.email') . '' . $this->email . '
    ' . __('comments.text') . '' . $this->text . '
    41 | 42 |

    ' . __('comments.view_comment') . '

    43 | 44 | '; 45 | 46 | // notify administrators 47 | foreach(User::where('role', '=', 'administrator')->get() as $user) { 48 | $to = $user->real_name . ' <' . $user->email . '>'; 49 | mail($to, __('comments.notify_subject'), $message, $headers); 50 | } 51 | } 52 | 53 | public static function paginate($page = 1, $perpage = 10) { 54 | $query = Query::table(static::table()); 55 | 56 | $count = $query->count(); 57 | 58 | $results = $query->take($perpage)->skip(($page - 1) * $perpage)->sort('date', 'desc')->get(); 59 | 60 | return new Paginator($results, $count, $page, $perpage, url('comments')); 61 | } 62 | 63 | public static function spam($comment) { 64 | $parts = explode('@', $comment['email']); 65 | $domain = array_pop($parts); 66 | 67 | // check domain 68 | $query = static::where('email', 'like', '%' . $domain) 69 | ->where('status', '=', 'spam'); 70 | 71 | if($query->count()) { 72 | // duplicate spam 73 | return true; 74 | } 75 | 76 | // check keywords 77 | $badwords = Config::get('meta.comment_moderation_keys'); 78 | 79 | if($badwords) { 80 | $words = explode(',', $badwords); 81 | 82 | foreach($words as $word) { 83 | $word = preg_quote($word, '#'); 84 | $pattern = "#$word#i"; 85 | 86 | foreach($comment as $part) { 87 | if(preg_match($pattern, $part)) return true; 88 | } 89 | } 90 | } 91 | 92 | return false; 93 | } 94 | 95 | } -------------------------------------------------------------------------------- /anchor/functions/comments.php: -------------------------------------------------------------------------------- 1 | where('post', '=', $itm->id)->get(); 14 | 15 | $comments = new Items($comments); 16 | 17 | Registry::set('comments', $comments); 18 | } 19 | 20 | return $comments->length(); 21 | } 22 | 23 | function total_comments() { 24 | if( ! has_comments()) return 0; 25 | 26 | $comments = Registry::get('comments'); 27 | 28 | return $comments->length(); 29 | } 30 | 31 | // loop comments 32 | function comments() { 33 | if( ! has_comments()) return false; 34 | 35 | $comments = Registry::get('comments'); 36 | 37 | if($result = $comments->valid()) { 38 | // register single comment 39 | Registry::set('comment', $comments->current()); 40 | 41 | // move to next 42 | $comments->next(); 43 | } 44 | 45 | return $result; 46 | } 47 | 48 | // single comments 49 | function comment_id() { 50 | return Registry::prop('comment', 'id'); 51 | } 52 | 53 | function comment_time() { 54 | if($time = Registry::prop('comment', 'date')) { 55 | return Date::format($time,'U'); 56 | } 57 | } 58 | 59 | function comment_date() { 60 | if($date = Registry::prop('comment', 'date')) { 61 | return Date::format($date); 62 | } 63 | } 64 | 65 | function comment_name() { 66 | return Registry::prop('comment', 'name'); 67 | } 68 | 69 | function comment_email() { 70 | return Registry::prop('comment', 'email'); 71 | } 72 | 73 | function comment_text() { 74 | return Registry::prop('comment', 'text'); 75 | } 76 | 77 | function comments_open() { 78 | return Registry::prop('article', 'comments') ? true : false; 79 | } 80 | 81 | // form elements 82 | function comment_form_notifications() { 83 | return Notify::read(); 84 | } 85 | 86 | function comment_form_url() { 87 | return Uri::to(Uri::current()); 88 | } 89 | 90 | function comment_form_input_name($extra = '') { 91 | return ''; 92 | } 93 | 94 | function comment_form_input_email($extra = '') { 95 | return ''; 96 | } 97 | 98 | function comment_form_input_text($extra = '') { 99 | return ''; 100 | } 101 | 102 | function comment_form_button($text = 'Post Comment', $extra = '') { 103 | return ''; 104 | } -------------------------------------------------------------------------------- /anchor/libraries/rss.php: -------------------------------------------------------------------------------- 1 | document->createElement($name); 9 | 10 | if(is_null($value) === false) { 11 | $text = $this->document->createTextNode($value); 12 | $element->appendChild($text); 13 | } 14 | 15 | foreach($attributes as $key => $val) { 16 | $element->setAttribute($key, $val); 17 | } 18 | 19 | return $element; 20 | } 21 | 22 | public function __construct($name, $description, $url, $language) { 23 | // create a dom xml object 24 | $this->document = new DOMDocument('1.0', 'UTF-8'); 25 | 26 | // create our rss feed 27 | $rss = $this->element('rss', null, array('version' => '2.0', 'xmlns:atom' => 'http://www.w3.org/2005/Atom')); 28 | $this->document->appendChild($rss); 29 | 30 | // create channel 31 | $this->channel = $this->element('channel'); 32 | $rss->appendChild($this->channel); 33 | 34 | // title 35 | $title = $this->element('title', $name); 36 | $this->channel->appendChild($title); 37 | 38 | // link 39 | $link = $this->element('link', $url); 40 | $this->channel->appendChild($link); 41 | 42 | // description 43 | $description = $this->element('description', $description); 44 | $this->channel->appendChild($description); 45 | 46 | // laguage 47 | // http://www.rssboard.org/rss-language-codes 48 | $language = $this->element('language', $language); 49 | $this->channel->appendChild($language); 50 | 51 | $ttl = $this->element('ttl', 60); 52 | $this->channel->appendChild($ttl); 53 | 54 | $docs = $this->element('docs', 'http://blogs.law.harvard.edu/tech/rss'); 55 | $this->channel->appendChild($docs); 56 | 57 | $copyright = $this->element('copyright', $name); 58 | $this->channel->appendChild($copyright); 59 | 60 | // atom self link 61 | $atom = $this->element('atom:link', null, array( 62 | 'href' => $url, 63 | 'rel' => 'self', 64 | 'type' => 'application/rss+xml' 65 | )); 66 | $this->channel->appendChild($atom); 67 | } 68 | 69 | public function item($title, $url, $description, $date) { 70 | $item = $this->element('item'); 71 | $this->channel->appendChild($item); 72 | 73 | // title 74 | $title = $this->element('title', $title); 75 | $item->appendChild($title); 76 | 77 | // link 78 | $link = $this->element('link', $url); 79 | $item->appendChild($link); 80 | 81 | // description 82 | $description = $this->element('description', $description); 83 | $item->appendChild($description); 84 | 85 | // date 86 | $date = $this->element('pubDate', date(DATE_RSS, strtotime($date))); 87 | $item->appendChild($date); 88 | } 89 | 90 | public function output() { 91 | // dump xml tree 92 | return $this->document->saveXML(); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /anchor/libraries/validator.php: -------------------------------------------------------------------------------- 1 | payload = $payload; 9 | $this->defaults(); 10 | } 11 | 12 | private function defaults() { 13 | $this->methods['null'] = function($str) { 14 | return is_null($str); 15 | }; 16 | 17 | $this->methods['min'] = function($str, $length) { 18 | return strlen($str) <= $length; 19 | }; 20 | 21 | $this->methods['max'] = function($str, $length) { 22 | return strlen($str) >= $length; 23 | }; 24 | 25 | $this->methods['float'] = function($str) { 26 | return is_float($str); 27 | }; 28 | 29 | $this->methods['int'] = function($str) { 30 | return is_int($str); 31 | }; 32 | 33 | $this->methods['url'] = function($str) { 34 | return filter_var($str, FILTER_VALIDATE_URL) !== false; 35 | }; 36 | 37 | $this->methods['email'] = function($str) { 38 | return filter_var($str, FILTER_VALIDATE_EMAIL) !== false; 39 | }; 40 | 41 | $this->methods['ip'] = function($str) { 42 | return filter_var($str, FILTER_VALIDATE_IP) !== false; 43 | }; 44 | 45 | $this->methods['alnum'] = function($str) { 46 | return ctype_alnum($str); 47 | }; 48 | 49 | $this->methods['contains'] = function($str, $needle) { 50 | return strpos($str, $needle) !== false; 51 | }; 52 | 53 | $this->methods['regex'] = function($str, $pattern) { 54 | return preg_match($pattern, $str); 55 | }; 56 | } 57 | 58 | public function check($key) { 59 | $this->key = isset($this->payload[$key]) ? $key : null; 60 | $this->value = isset($this->payload[$this->key]) ? $this->payload[$this->key] : null; 61 | 62 | return $this; 63 | } 64 | 65 | public function add($method, $callback) { 66 | $this->methods[$method] = $callback; 67 | } 68 | 69 | public function __call($method, $params) { 70 | if(is_null($this->key)) { 71 | return $this; 72 | } 73 | 74 | if(strpos($method, 'is_') === 0) { 75 | $method = substr($method, 3); 76 | $reverse = false; 77 | } elseif(strpos($method, 'not_') === 0) { 78 | $method = substr($method, 4); 79 | $reverse = true; 80 | } 81 | 82 | if(isset($this->methods[$method]) === false) { 83 | throw new ErrorException('Validator method ' . $method . ' not found'); 84 | } 85 | 86 | $validator = $this->methods[$method]; 87 | 88 | $message = array_pop($params); 89 | 90 | $result = (bool) call_user_func_array($validator, array_merge(array($this->value), $params)); 91 | 92 | $result = (bool) ($result ^ $reverse); 93 | 94 | if($result === false) { 95 | $this->errors[$this->key][] = $message; 96 | } 97 | 98 | return $this; 99 | } 100 | 101 | public function errors() { 102 | return $this->errors; 103 | } 104 | 105 | } -------------------------------------------------------------------------------- /install/views/metadata.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
    4 |
    5 |

    Site metadata

    6 | 7 |

    In order to personalise your Anchor blog, it's recommended you add some metadata about your site. This can all be changed at any time, though.

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

    15 | 16 | What’s your blog called?. 17 | 18 | 19 |

    20 | 21 |

    22 | 23 | A little bit about you or your blog. 24 | 25 | 27 |

    28 | 29 |

    30 | 31 | Anchor’s folder. Change if this is wrong. 32 | 33 |

    34 | 35 | 1): ?> 36 |

    37 | 38 | Your Anchor theme. 39 | 44 |

    45 | 46 | 47 | 48 | 49 |

    50 | 51 | Url rewiting 52 | 53 | 54 | 55 |

    Looks like you are running apache with mod_rewrite enabled.
    56 | The installer will create the htaccess for you.
    57 | 58 | 59 | 60 |
    Looks like you are running apache, but mod_rewrite is not enabled.
    61 | 62 |
    63 | Create the htaccess file for me anyway.
    64 | 65 | 66 | 67 |
    Looks like you are running PHP as a fastcgi process.
    68 | You will have to setup your own url rewriting.
    69 | 70 | 71 |

    72 |
    73 | 74 |
    75 | « Back 76 | 77 |
    78 |
    79 |
    80 | 81 | -------------------------------------------------------------------------------- /system/arr.php: -------------------------------------------------------------------------------- 1 | 1) { 48 | $key = array_shift($keys); 49 | 50 | // make sure we have a array to set our new key in 51 | if( ! array_key_exists($key, $array)) { 52 | $array[$key] = array(); 53 | } 54 | 55 | $array =& $array[$key]; 56 | } 57 | 58 | $array[array_shift($keys)] = $value; 59 | } 60 | 61 | /** 62 | * Remove a value from a array 63 | * 64 | * @param array 65 | * @param string 66 | */ 67 | public static function erase(&$array, $key) { 68 | $keys = explode('.', $key); 69 | 70 | // traverse the array into the second last key 71 | while(count($keys) > 1) { 72 | $key = array_shift($keys); 73 | 74 | if(array_key_exists($key, $array)) { 75 | $array =& $array[$key]; 76 | } 77 | } 78 | 79 | // if the last key exists unset it 80 | if(array_key_exists($key = array_shift($keys), $array)) { 81 | unset($array[$key]); 82 | } 83 | } 84 | 85 | /** 86 | * Create a new instance of the Arr class 87 | * 88 | * @param array 89 | */ 90 | public static function create($stack = array()) { 91 | return new static($stack); 92 | } 93 | 94 | /** 95 | * Arr constructor 96 | * 97 | * @param array 98 | */ 99 | public function __construct($stack = array()) { 100 | $this->stack = $stack; 101 | } 102 | 103 | /** 104 | * Shuffle the array elements in the stack 105 | * 106 | * @return object Returns self for chaining 107 | */ 108 | public function shuffle() { 109 | shuffle($this->stack); 110 | 111 | return $this; 112 | } 113 | 114 | /** 115 | * Returns the first element in the stack 116 | * 117 | * @return mixed 118 | */ 119 | public function first() { 120 | return current($this->stack); 121 | } 122 | 123 | /** 124 | * Returns the last element in the stack 125 | * 126 | * @return mixed 127 | */ 128 | public function last() { 129 | return end($this->stack); 130 | } 131 | 132 | } -------------------------------------------------------------------------------- /anchor/views/extend/fields/add.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
    4 |

    5 |
    6 | 7 |
    8 | 9 | 10 |
    11 | 12 | 13 | 14 |
    15 |

    16 | 17 | 23 | 24 |

    25 | 26 |

    27 | 28 | 34 | 35 |

    36 | 37 |

    38 | 39 | 40 | 41 |

    42 | 43 |

    44 | 45 | 46 | 47 |

    48 | 49 |

    50 | 51 | 52 | 53 |

    54 | 55 |

    56 | 57 | 59 | 60 | 61 |

    62 | 63 |

    64 | 65 | 67 | 68 | 69 |

    70 |
    71 | 72 | 75 |
    76 |
    77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /system/error.php: -------------------------------------------------------------------------------- 1 | 1) ob_end_clean(); 31 | 32 | if(Request::cli()) { 33 | Cli::write(PHP_EOL . 'Uncaught Exception', 'light_red'); 34 | Cli::write($e->getMessage() . PHP_EOL); 35 | 36 | Cli::write('Origin', 'light_red'); 37 | Cli::write(substr($e->getFile(), strlen(PATH)) . ' on line ' . $e->getLine() . PHP_EOL); 38 | 39 | Cli::write('Trace', 'light_red'); 40 | Cli::write($e->getTraceAsString() . PHP_EOL); 41 | } 42 | else { 43 | echo ' 44 | 45 | Uncaught Exception 46 | 50 | 51 | 52 |

    Uncaught Exception

    53 |

    ' . $e->getMessage() . '

    54 |

    Origin

    55 |

    ' . substr($e->getFile(), strlen(PATH)) . ' on line ' . $e->getLine() . '

    56 |

    Trace

    57 |
    ' . $e->getTraceAsString() . '
    58 | 59 | '; 60 | } 61 | } 62 | else { 63 | // issue a 500 response 64 | Response::error(500, array('exception' => $e))->send(); 65 | } 66 | 67 | exit(1); 68 | } 69 | 70 | /** 71 | * Error handler 72 | * 73 | * This will catch the php native error and treat it as a exception 74 | * which will provide a full back trace on all errors 75 | * 76 | * @param int 77 | * @param string 78 | * @param string 79 | * @param int 80 | * @param array 81 | */ 82 | public static function native($code, $message, $file, $line, $context) { 83 | if($code & error_reporting()) { 84 | static::exception(new ErrorException($message, $code, 0, $file, $line)); 85 | } 86 | } 87 | 88 | /** 89 | * Shutdown handler 90 | * 91 | * This will catch errors that are generated at the 92 | * shutdown level of execution 93 | */ 94 | public static function shutdown() { 95 | if($error = error_get_last()) { 96 | extract($error); 97 | 98 | static::exception(new ErrorException($message, $type, 0, $file, $line)); 99 | } 100 | } 101 | 102 | /** 103 | * Exception logger 104 | * 105 | * Log the exception depending on the application config 106 | * 107 | * @param object The exception 108 | */ 109 | public static function log($e) { 110 | if(is_callable($logger = Config::error('log'))) { 111 | call_user_func($logger, $e); 112 | } 113 | } 114 | 115 | } --------------------------------------------------------------------------------