├── .gitignore ├── LICENSE.txt ├── README.md ├── app ├── Config │ ├── Schema │ │ └── schema.php │ ├── acl.ini.php │ ├── bootstrap.php │ ├── core.php │ ├── database.php.default │ ├── email.php.default │ ├── html_tags.php │ ├── production.php.default │ ├── routes.php │ └── settings.php ├── Console │ ├── Command │ │ ├── AppShell.php │ │ ├── CheckShell.php │ │ ├── CloneShell.php │ │ ├── GithubCloseShell.php │ │ ├── RefreshShell.php │ │ ├── ScanShell.php │ │ ├── StatsShell.php │ │ └── UpdateShell.php │ ├── cake │ ├── cake.bat │ └── cake.php ├── Controller │ ├── AppController.php │ ├── ContributorsController.php │ ├── DescriptionsController.php │ ├── PagesController.php │ ├── PluginsController.php │ ├── PluginsStatesController.php │ ├── SettingsController.php │ ├── StatesController.php │ ├── StatsController.php │ └── TagsController.php ├── Model │ ├── AppModel.php │ ├── Contributor.php │ ├── Datasource │ │ └── Session │ │ │ └── ComboSession.php │ ├── Description.php │ ├── Plugin.php │ ├── PluginsState.php │ ├── Session.php │ ├── Setting.php │ ├── Stat.php │ ├── State.php │ └── Tag.php ├── Test │ ├── Case │ │ ├── AllTest.php │ │ ├── Console │ │ │ └── Command │ │ │ │ ├── CheckShellTest.php │ │ │ │ ├── CloneShellTest.php │ │ │ │ ├── RefreshShellTest.php │ │ │ │ ├── ScanShellTest.php │ │ │ │ ├── StatsShellTest.php │ │ │ │ └── UpdateShellTest.php │ │ ├── Controller │ │ │ ├── ContributorsControllerTest.php │ │ │ ├── DescriptionsControllerTest.php │ │ │ ├── PluginsControllerTest.php │ │ │ ├── PluginsStatesControllerTest.php │ │ │ ├── SettingsControllerTest.php │ │ │ ├── StatesControllerTest.php │ │ │ ├── StatsControllerTest.php │ │ │ └── TagsControllerTest.php │ │ └── Model │ │ │ ├── ContributorTest.php │ │ │ ├── DescriptionTest.php │ │ │ ├── PluginTest.php │ │ │ ├── PluginsStateTest.php │ │ │ ├── SessionTest.php │ │ │ ├── SettingTest.php │ │ │ ├── StatTest.php │ │ │ ├── StateTest.php │ │ │ └── TagTest.php │ └── Fixture │ │ ├── ContributorFixture.php │ │ ├── DescriptionFixture.php │ │ ├── PluginFixture.php │ │ ├── PluginsStateFixture.php │ │ ├── SessionFixture.php │ │ ├── SettingFixture.php │ │ ├── StatFixture.php │ │ ├── StateFixture.php │ │ └── TagFixture.php ├── TestSuite │ ├── Reporter │ │ └── HtmlReporter.php │ └── templates │ │ ├── footer.php │ │ ├── header.php │ │ └── menu.php ├── View │ ├── Common │ │ └── sidebar.ctp │ ├── Elements │ │ ├── alert-error.ctp │ │ ├── alert-success.ctp │ │ ├── alert-warning.ctp │ │ ├── alert.ctp │ │ ├── footer.ctp │ │ ├── head.ctp │ │ ├── header.ctp │ │ ├── nav.ctp │ │ ├── scripts.ctp │ │ └── sql_dump.ctp │ ├── Emails │ │ ├── html │ │ │ └── default.ctp │ │ └── text │ │ │ └── default.ctp │ ├── Errors │ │ ├── error400.ctp │ │ ├── error500.ctp │ │ ├── fatal_error.ctp │ │ └── missing_view.ctp │ ├── Helper │ │ ├── AppFormHelper.php │ │ ├── AppHelper.php │ │ ├── AppHtmlHelper.php │ │ ├── AppPaginatorHelper.php │ │ └── SettingsFormHelper.php │ ├── Layouts │ │ ├── Emails │ │ │ ├── html │ │ │ │ └── default.ctp │ │ │ └── text │ │ │ │ └── default.ctp │ │ ├── ajax.ctp │ │ ├── default.ctp │ │ ├── flash.ctp │ │ ├── js │ │ │ └── default.ctp │ │ ├── rss │ │ │ └── default.ctp │ │ └── xml │ │ │ └── default.ctp │ ├── Pages │ │ ├── about.ctp │ │ ├── add-new-guide.ctp │ │ ├── home.ctp │ │ └── plugin-developer-guide.ctp │ ├── Plugins │ │ ├── index.ctp │ │ └── view.ctp │ ├── Settings │ │ └── manage.ctp │ └── Stats │ │ ├── index.ctp │ │ └── json │ │ └── index.ctp ├── tmp │ ├── .gitignore │ ├── cache │ │ ├── .gitignore │ │ ├── models │ │ │ └── .gitignore │ │ └── persistent │ │ │ └── .gitignore │ ├── logs │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ └── tests │ │ └── .gitignore └── webroot │ ├── .htaccess │ ├── css │ ├── application.css │ ├── font-awesome.min.css │ ├── foundation.min.css │ ├── normalize.min.css │ ├── rickshaw.min.css │ └── testsuite.css │ ├── favicon.ico │ ├── fonts │ ├── FontAwesome.otf │ ├── fontawesome-webfont.eot │ ├── fontawesome-webfont.svg │ ├── fontawesome-webfont.ttf │ └── fontawesome-webfont.woff │ ├── index.php │ ├── js │ ├── d3.v2.min.js │ ├── foundation.min.js │ ├── modernizr.min.js │ └── rickshaw.min.js │ └── test.php ├── build.xml ├── composer.json └── composer.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # PluginMirror Configuration Files 2 | /app/Config/production.php 3 | /app/Config/database.php 4 | 5 | # API Documentation and Package Builds 6 | /build/ 7 | 8 | # Composer 9 | /composer.phar 10 | /vendor/ 11 | 12 | # External CakePHP Resources (see Composer) 13 | /cakephp/ 14 | /app/Plugin/DebugKit/ 15 | 16 | # PhpStorm 17 | /.idea/ 18 | 19 | # NetBeans 20 | /nbproject/ 21 | 22 | # Eclipse / Zend Studio 23 | /.settings/ 24 | /.buildpath 25 | /.project 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > [!CAUTION] 2 | > This project is no longer actively maintained. The repository is archived for public availability in case anyone would like to fork it and create their own instance of the project. 3 | 4 | WordPress Plugins GitHub Mirror Application 5 | =========================================== 6 | 7 | Provides a fully automated git-svn mirror of any and all plugins in the 8 | WordPress.org plugin repository. 9 | 10 | The [WordPress Plugins GitHub Mirror](http://www.pluginmirror.com/) is sponsored 11 | and hosted by [Bluehost](http://www.bluehost.com/). 12 | 13 | License 14 | ------- 15 | 16 | Copyright 2013 Bluehost 17 | 18 | In the spirit of [WordPress](http://wordpress.org/)... 19 | 20 | This program is free software; you can redistribute it and/or modify it under 21 | the terms of the [GNU General Public License](http://www.gnu.org/licenses/gpl-2.0.txt) 22 | as published by the Free Software Foundation; either version 2 of the License, 23 | or (at your option) any later version. 24 | 25 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 26 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 27 | PARTICULAR PURPOSE. See the GNU General Public License for more details. 28 | 29 | You should have received a copy of the GNU General Public License along with 30 | this program; if not, write to the Free Software Foundation, Inc., 51 Franklin 31 | Street, Fifth Floor, Boston, MA 02110-1301 USA. 32 | 33 | This application has also been built with the following libraries and components 34 | with their own respective licenses: 35 | 36 | CakePHP (and DebugKit plugin): 37 | 38 | * Copyright (c) 2005-2013 Cake Software Foundation, Inc. 39 | * Licensed under the [MIT License](http://opensource.org/licenses/MIT) (MIT) 40 | 41 | Foundation: 42 | 43 | * Copyright (c) 2012 Mark Hayes 44 | * Licensed under the [MIT License](http://opensource.org/licenses/MIT) (MIT) 45 | 46 | Font Awesome: 47 | 48 | * [Font Awesome](http://fortawesome.github.com/Font-Awesome) by Dave Gandy 49 | * The Font Awesome font is licensed under the [SIL Open Font License 1.1](http://scripts.sil.org/OFL) (OFL-1.1) 50 | * Font Awesome CSS, LESS, and SASS files are licensed under the [MIT License](http://opensource.org/licenses/MIT) (MIT) 51 | * The Font Awesome pictograms are licensed under the [CC BY 3.0 License](http://creativecommons.org/licenses/by/3.0/) (CC-BY-3.0) 52 | * Attribution is no longer required in Font Awesome 3.0, but much appreciated. 53 | 54 | D3.js: 55 | 56 | * Copyright (c) 2013 Michael Bostock 57 | * Licensed under the [BSD 3-Clause License](http://opensource.org/licenses/BSD-3-Clause) (BSD-3-Clause) 58 | 59 | Rickshaw: 60 | 61 | * Copyright (C) 2011 Shutterstock Images, LLC 62 | * Licensed under the [MIT License](http://opensource.org/licenses/MIT) (MIT) 63 | -------------------------------------------------------------------------------- /app/Config/acl.ini.php: -------------------------------------------------------------------------------- 1 | ; 2 | ;/** 3 | ; * ACL Configuration 4 | ; * 5 | ; * 6 | ; * PHP 5 7 | ; * 8 | ; * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) 9 | ; * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) 10 | ; * 11 | ; * Licensed under The MIT License 12 | ; * Redistributions of files must retain the above copyright notice. 13 | ; * 14 | ; * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) 15 | ; * @link http://cakephp.org CakePHP(tm) Project 16 | ; * @package app.Config 17 | ; * @since CakePHP(tm) v 0.10.0.1076 18 | ; * @license MIT License (http://www.opensource.org/licenses/mit-license.php) 19 | ; */ 20 | 21 | ; acl.ini.php - Cake ACL Configuration 22 | ; --------------------------------------------------------------------- 23 | ; Use this file to specify user permissions. 24 | ; aco = access control object (something in your application) 25 | ; aro = access request object (something requesting access) 26 | ; 27 | ; User records are added as follows: 28 | ; 29 | ; [uid] 30 | ; groups = group1, group2, group3 31 | ; allow = aco1, aco2, aco3 32 | ; deny = aco4, aco5, aco6 33 | ; 34 | ; Group records are added in a similar manner: 35 | ; 36 | ; [gid] 37 | ; allow = aco1, aco2, aco3 38 | ; deny = aco4, aco5, aco6 39 | ; 40 | ; The allow, deny, and groups sections are all optional. 41 | ; NOTE: groups names *cannot* ever be the same as usernames! 42 | ; 43 | ; ACL permissions are checked in the following order: 44 | ; 1. Check for user denies (and DENY if specified) 45 | ; 2. Check for user allows (and ALLOW if specified) 46 | ; 3. Gather user's groups 47 | ; 4. Check group denies (and DENY if specified) 48 | ; 5. Check group allows (and ALLOW if specified) 49 | ; 6. If no aro, aco, or group information is found, DENY 50 | ; 51 | ; --------------------------------------------------------------------- 52 | 53 | ;------------------------------------- 54 | ;Users 55 | ;------------------------------------- 56 | 57 | [username-goes-here] 58 | groups = group1, group2 59 | deny = aco1, aco2 60 | allow = aco3, aco4 61 | 62 | ;------------------------------------- 63 | ;Groups 64 | ;------------------------------------- 65 | 66 | [groupname-goes-here] 67 | deny = aco5, aco6 68 | allow = aco7, aco8 69 | -------------------------------------------------------------------------------- /app/Config/bootstrap.php: -------------------------------------------------------------------------------- 1 | array(ROOT . DS . 'vendor' . DS))); 12 | App::import('Vendor', 'autoload'); 13 | 14 | CakePlugin::loadAll(); 15 | 16 | 17 | Configure::write('Dispatcher.filters', array( 18 | 'AssetDispatcher', 19 | 'CacheDispatcher' 20 | )); 21 | 22 | 23 | App::uses('CakeLog', 'Log'); 24 | CakeLog::config('debug', array( 25 | 'engine' => 'FileLog', 26 | 'types' => array('notice', 'info', 'debug'), 27 | 'file' => 'debug', 28 | )); 29 | CakeLog::config('error', array( 30 | 'engine' => 'FileLog', 31 | 'types' => array('warning', 'error', 'critical', 'alert', 'emergency'), 32 | 'file' => 'error', 33 | )); 34 | 35 | 36 | Cache::config('default', array( 37 | 'engine' => Configure::read('Cache.engine'), 38 | 'prefix' => Configure::read('Cache.prefix') . 'default_', 39 | 'path' => CACHE . 'persistent' . DS, 40 | 'serialize' => (Configure::read('Cache.engine') === 'File'), 41 | 'duration' => Configure::read('Cache.duration') 42 | )); 43 | 44 | Cache::config('session', array( 45 | 'engine' => Configure::read('Cache.engine'), 46 | 'prefix' => Configure::read('Cache.prefix') . 'session_', 47 | 'path' => CACHE . 'persistent' . DS, 48 | 'serialize' => (Configure::read('Cache.engine') === 'File'), 49 | 'duration' => '+12 hours' 50 | )); 51 | -------------------------------------------------------------------------------- /app/Config/core.php: -------------------------------------------------------------------------------- 1 | 'ErrorHandler::handleError', 21 | 'level' => E_ALL & ~E_DEPRECATED, 22 | 'trace' => true 23 | )); 24 | 25 | Configure::write('Exception', array( 26 | 'handler' => 'ErrorHandler::handleException', 27 | 'renderer' => 'ExceptionRenderer', 28 | 'log' => true 29 | )); 30 | 31 | define('LOG_ERROR', LOG_ERR); 32 | 33 | 34 | Configure::write('App.encoding', 'UTF-8'); 35 | Configure::write('App.name', 'Plugin Mirror'); 36 | 37 | Configure::write('App.svn_url', 'https://plugins.svn.wordpress.org'); 38 | 39 | Configure::write('App.max_cloning_per_ip', 4); 40 | 41 | Configure::write('App.plugin_api_url', 'http://api.wordpress.org/plugins/info/1.0/%s.json'); 42 | Configure::write('App.plugin_app_url', 'http://www.pluginmirror.com/plugins/%s/'); 43 | Configure::write('App.plugin_repo_path', '/home/pluginmirror/disk/repos/%s'); 44 | Configure::write('App.plugin_git_url', 'git@github.com:wp-plugins/%s.git'); 45 | Configure::write('App.plugin_github_url', 'https://github.com/wp-plugins/%s/'); 46 | Configure::write('App.plugin_http_url', 'http://wordpress.org/plugins/%s/'); 47 | Configure::write('App.plugin_support_url', 'http://wordpress.org/support/plugin/%s/'); 48 | Configure::write('App.plugin_svn_url', 'https://plugins.svn.wordpress.org/%s/'); 49 | Configure::write('App.plugin_trac_url', 'http://plugins.trac.wordpress.org/browser/%s/'); 50 | 51 | Configure::write('App.profile_url', 'http://profiles.wordpress.org/%s/'); 52 | 53 | Configure::write('GitHub.org_name', 'wp-plugins'); 54 | Configure::write('GitHub.repo_description', 'WordPress.org Plugin Mirror'); 55 | Configure::write('GitHub.ssh_host', 'pluginmirror-github'); 56 | Configure::write('GitHub.user_agent', 'Plugin Mirror (http://www.pluginmirror.com/)'); 57 | 58 | 59 | Configure::write('Acl.classname', 'DbAcl'); 60 | Configure::write('Acl.database', 'default'); 61 | 62 | Configure::write('Asset.timestamp', true); 63 | 64 | date_default_timezone_set('UTC'); 65 | 66 | 67 | Configure::write('Security.level', 'medium'); 68 | 69 | if(defined('APP_SECURITY_SALT')) 70 | Configure::write('Security.salt', APP_SECURITY_SALT); 71 | 72 | if(defined('APP_SECURITY_CIPHERSEED')) 73 | Configure::write('Security.cipherSeed', APP_SECURITY_CIPHERSEED); 74 | 75 | 76 | if(defined('APP_CACHE_DISABLE')) 77 | Configure::write('Cache.disable', APP_CACHE_DISABLE); 78 | else 79 | Configure::write('Cache.disable', true); 80 | 81 | if(defined('APP_CACHE_CHECK')) 82 | Configure::write('Cache.check', APP_CACHE_CHECK); 83 | else 84 | Configure::write('Cache.check', false); 85 | 86 | 87 | Configure::write('Cache.engine', 'File'); 88 | if (extension_loaded('apc') && function_exists('apc_dec') && 89 | (php_sapi_name() !== 'cli' || ini_get('apc.enable_cli'))) 90 | { 91 | Configure::write('Cache.engine', 'Apc'); 92 | } 93 | 94 | Configure::write('Cache.duration', '+100 days'); 95 | if (Configure::read('debug') >= 1) 96 | { 97 | Configure::write('Cache.duration', '+60 minutes'); 98 | } 99 | 100 | Configure::write('Cache.prefix', 'app_'); 101 | 102 | Cache::config('_cake_core_', array( 103 | 'engine' => Configure::read('Cache.engine'), 104 | 'prefix' => Configure::read('Cache.prefix') . 'cake_core_', 105 | 'path' => CACHE . 'persistent' . DS, 106 | 'serialize' => (Configure::read('Cache.engine') === 'File'), 107 | 'duration' => Configure::read('Cache.duration') 108 | )); 109 | 110 | Cache::config('_cake_model_', array( 111 | 'engine' => Configure::read('Cache.engine'), 112 | 'prefix' => Configure::read('Cache.prefix') . 'cake_model_', 113 | 'path' => CACHE . 'models' . DS, 114 | 'serialize' => (Configure::read('Cache.engine') === 'File'), 115 | 'duration' => Configure::read('Cache.duration') 116 | )); 117 | 118 | 119 | Configure::write('Session', array( 120 | 'defaults' => 'database', 121 | 'handler' => array( 122 | 'engine' => 'ComboSession', 123 | 'model' => 'Session', 124 | 'cache' => 'session' 125 | ), 126 | 'cookie' => 'session', 127 | 'timeout' => 1440 // 1 day 128 | )); -------------------------------------------------------------------------------- /app/Config/database.php.default: -------------------------------------------------------------------------------- 1 | The name of a supported datasource; valid options are as follows: 31 | * Database/Mysql - MySQL 4 & 5, 32 | * Database/Sqlite - SQLite (PHP5 only), 33 | * Database/Postgres - PostgreSQL 7 and higher, 34 | * Database/Sqlserver - Microsoft SQL Server 2005 and higher 35 | * 36 | * You can add custom database datasources (or override existing datasources) by adding the 37 | * appropriate file to app/Model/Datasource/Database. Datasources should be named 'MyDatasource.php', 38 | * 39 | * 40 | * persistent => true / false 41 | * Determines whether or not the database should use a persistent connection 42 | * 43 | * host => 44 | * the host you connect to the database. To add a socket or port number, use 'port' => # 45 | * 46 | * prefix => 47 | * Uses the given prefix for all the tables in this database. This setting can be overridden 48 | * on a per-table basis with the Model::$tablePrefix property. 49 | * 50 | * schema => 51 | * For Postgres/Sqlserver specifies which schema you would like to use the tables in. Postgres defaults to 'public'. For Sqlserver, it defaults to empty and use 52 | * the connected user's default schema (typically 'dbo'). 53 | * 54 | * encoding => 55 | * For MySQL, Postgres specifies the character encoding to use when connecting to the 56 | * database. Uses database default not specified. 57 | * 58 | * unix_socket => 59 | * For MySQL to connect via socket specify the `unix_socket` parameter instead of `host` and `port` 60 | */ 61 | class DATABASE_CONFIG { 62 | 63 | public $default = array( 64 | 'datasource' => 'Database/Mysql', 65 | 'persistent' => false, 66 | 'host' => 'localhost', 67 | 'login' => 'user', 68 | 'password' => 'password', 69 | 'database' => 'database_name', 70 | 'prefix' => '', 71 | //'encoding' => 'utf8', 72 | ); 73 | 74 | public $test = array( 75 | 'datasource' => 'Database/Mysql', 76 | 'persistent' => false, 77 | 'host' => 'localhost', 78 | 'login' => 'user', 79 | 'password' => 'password', 80 | 'database' => 'test_database_name', 81 | 'prefix' => '', 82 | //'encoding' => 'utf8', 83 | ); 84 | } 85 | -------------------------------------------------------------------------------- /app/Config/email.php.default: -------------------------------------------------------------------------------- 1 | The name of a supported transport; valid options are as follows: 31 | * Mail - Send using PHP mail function 32 | * Smtp - Send using SMTP 33 | * Debug - Do not send the email, just return the result 34 | * 35 | * You can add custom transports (or override existing transports) by adding the 36 | * appropriate file to app/Network/Email. Transports should be named 'YourTransport.php', 37 | * where 'Your' is the name of the transport. 38 | * 39 | * from => 40 | * The origin email. See CakeEmail::from() about the valid values 41 | * 42 | */ 43 | class EmailConfig { 44 | 45 | public $default = array( 46 | 'transport' => 'Mail', 47 | 'from' => 'you@localhost', 48 | //'charset' => 'utf-8', 49 | //'headerCharset' => 'utf-8', 50 | ); 51 | 52 | public $smtp = array( 53 | 'transport' => 'Smtp', 54 | 'from' => array('site@localhost' => 'My Site'), 55 | 'host' => 'localhost', 56 | 'port' => 25, 57 | 'timeout' => 30, 58 | 'username' => 'user', 59 | 'password' => 'secret', 60 | 'client' => null, 61 | 'log' => false 62 | //'charset' => 'utf-8', 63 | //'headerCharset' => 'utf-8', 64 | ); 65 | 66 | public $fast = array( 67 | 'from' => 'you@localhost', 68 | 'sender' => null, 69 | 'to' => null, 70 | 'cc' => null, 71 | 'bcc' => null, 72 | 'replyTo' => null, 73 | 'readReceipt' => null, 74 | 'returnPath' => null, 75 | 'messageId' => true, 76 | 'subject' => null, 77 | 'message' => null, 78 | 'headers' => null, 79 | 'viewRender' => null, 80 | 'template' => false, 81 | 'layout' => false, 82 | 'viewVars' => null, 83 | 'attachments' => null, 84 | 'emailFormat' => null, 85 | 'transport' => 'Smtp', 86 | 'host' => 'localhost', 87 | 'port' => 25, 88 | 'timeout' => 30, 89 | 'username' => 'user', 90 | 'password' => 'secret', 91 | 'client' => null, 92 | 'log' => true, 93 | //'charset' => 'utf-8', 94 | //'headerCharset' => 'utf-8', 95 | ); 96 | 97 | } 98 | -------------------------------------------------------------------------------- /app/Config/html_tags.php: -------------------------------------------------------------------------------- 1 | array( 11 | 'meta' => '', 12 | 'metalink' => '', 13 | 'input' => '', 14 | 'hidden' => '', 15 | 'checkbox' => '', 16 | 'checkboxmultiple' => '', 17 | 'radio' => '%s', 18 | 'password' => '', 19 | 'file' => '', 20 | 'file_no_model' => '', 21 | 'submit' => '', 22 | 'submitimage' => '', 23 | 'image' => '', 24 | 'tagselfclosing' => '<%s%s>', 25 | 'css' => '', 26 | 'style' => '%s', 27 | 'charset' => '', 28 | 'javascriptblock' => '%s', 29 | 'javascriptstart' => '', 31 | 'javascriptend' => '' 32 | )); -------------------------------------------------------------------------------- /app/Config/production.php.default: -------------------------------------------------------------------------------- 1 | 'pages', 'action' => 'display', 'home')); 11 | Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display')); 12 | 13 | Router::connect('/contributors/:name', 14 | array('controller' => 'contributors', 'action' => 'view'), 15 | array('pass' => array('name'))); 16 | 17 | Router::connect('/descriptions/:id', 18 | array('controller' => 'descriptions', 'action' => 'view'), 19 | array('pass' => array('id'))); 20 | 21 | Router::connect('/plugins/:slug', 22 | array('controller' => 'plugins', 'action' => 'view'), 23 | array('pass' => array('slug'))); 24 | Router::connect('/plugins/:slug/:action', 25 | array('controller' => 'plugins'), 26 | array('pass' => array('slug'))); 27 | 28 | Router::connect('/plugins_states/:id', 29 | array('controller' => 'plugins_states', 'action' => 'view'), 30 | array('pass' => array('id'))); 31 | 32 | Router::connect('/tags/:name', 33 | array('controller' => 'tags', 'action' => 'view'), 34 | array('pass' => array('name'))); 35 | 36 | Router::connect('/states/:name', 37 | array('controller' => 'states', 'action' => 'view'), 38 | array('pass' => array('name'))); 39 | 40 | Router::connect('/status', array('controller' => 'stats', 'action' => 'index')); 41 | 42 | Router::connect('/:controller', array('action' => 'index')); 43 | Router::connect('/:controller/:action/*'); 44 | 45 | Router::parseExtensions('json', 'xml'); 46 | 47 | CakePlugin::routes(); -------------------------------------------------------------------------------- /app/Config/settings.php: -------------------------------------------------------------------------------- 1 | 'smtp', 16 | ); -------------------------------------------------------------------------------- /app/Console/Command/AppShell.php: -------------------------------------------------------------------------------- 1 | addOptions(array( 36 | 'no-colors' => array( 37 | 'help' => __('Do not use colors in output.'), 38 | 'boolean' => true 39 | ), 40 | )); 41 | 42 | if(!empty($this->locked_commands)) { 43 | $parser->addOption('skip-lock', array( 44 | 'short' => 's', 45 | 'help' => __('Forces the command to run even if locked.'), 46 | 'boolean' => true 47 | )); 48 | } 49 | 50 | return $parser; 51 | } 52 | 53 | /** 54 | * Loads database settings, disables console colors if requested, and 55 | * prevents re-entry if the current command is locked. 56 | * 57 | * @return void 58 | */ 59 | function startup() 60 | { 61 | if(empty($this->Setting)) { 62 | App::uses('ClassRegistry', 'Utility'); 63 | $this->Setting = ClassRegistry::init('Setting'); 64 | } 65 | $this->Setting->load(); 66 | 67 | $this->_checkColors(); 68 | $this->_checkLock(); 69 | 70 | parent::startup(); 71 | } 72 | 73 | /** 74 | * Disables console colors if requested. 75 | * 76 | * @return void 77 | */ 78 | protected function _checkColors() 79 | { 80 | if(isset($this->params['no-colors']) && $this->params['no-colors']) { 81 | $this->stdout->outputAs(ConsoleOutput::PLAIN); 82 | $this->stderr->outputAs(ConsoleOutput::PLAIN); 83 | } 84 | } 85 | 86 | /** 87 | * @return string Fully qualified configuration setting for the current command lock state. 88 | */ 89 | protected function _getLockName() 90 | { 91 | if(empty($this->command)) { 92 | return implode('.', array('Shell', $this->name, 'main', 'lock')); 93 | } 94 | return implode('.', array('Shell', $this->name, $this->command, 'lock')); 95 | } 96 | 97 | /** 98 | * @return bool True if the current command uses locking. 99 | */ 100 | protected function _lockRequested() 101 | { 102 | if(empty($this->locked_commands)) { 103 | return false; 104 | } 105 | if(empty($this->command)) { 106 | return in_array('main', $this->locked_commands); 107 | } 108 | return in_array($this->command, $this->locked_commands); 109 | } 110 | 111 | /** 112 | * Prevents re-entry if the current command is locked. 113 | * 114 | * @return void 115 | */ 116 | protected function _checkLock() 117 | { 118 | if($this->_lockRequested()) 119 | { 120 | if(!$this->params['skip-lock'] && Configure::read($this->_getLockName())) { 121 | $this->error(__('Shell Locked'), __('There is another instance of this shell running already. Use --skip-lock to force this shell to run anyway.')); 122 | } 123 | $this->Setting->write($this->_getLockName(), true); 124 | } 125 | } 126 | 127 | /** 128 | * Erases the current command lock if it is set. 129 | * 130 | * @return mixed 131 | */ 132 | protected function _unlock() 133 | { 134 | return $this->Setting->write($this->_getLockName(), false); 135 | } 136 | 137 | /** 138 | * Wrapper around PHP exec() that automatically escapes shell args. 139 | * 140 | * @param string $command 141 | * @internal param mixed $arg [optional] 142 | * @internal param $mixed $... [optional] 143 | * 144 | * @throws RuntimeException 145 | * 146 | * @return array Lines of output from running the given command. 147 | */ 148 | protected function _exec($command) 149 | { 150 | $return_code = 0; 151 | $output = array(); 152 | 153 | if(func_num_args() > 1) { 154 | $args = func_get_args(); 155 | array_shift($args); 156 | $args = array_map('escapeshellarg', $args); 157 | $command = vsprintf($command, $args); 158 | } 159 | 160 | exec($command, $output, $return_code); 161 | 162 | if($return_code !== 0) { 163 | throw new RuntimeException( 164 | __('Command returned with an error.'), $return_code); 165 | } 166 | 167 | return $output; 168 | } 169 | 170 | } 171 | -------------------------------------------------------------------------------- /app/Console/Command/CheckShell.php: -------------------------------------------------------------------------------- 1 | description(__('Adds any new plugins on WordPress.org, and queues them up for updates.')); 37 | return $parser; 38 | } 39 | 40 | /** 41 | * Adds any new plugins on WordPress.org, and queues them up for updates. 42 | * 43 | * @return int Shell return code. 44 | */ 45 | function main() 46 | { 47 | $this->out(__('Fetching list of plugins from SVN repository...')); 48 | 49 | $repo_url = Configure::read('App.svn_url'); 50 | $command = "svn list $repo_url | sed 's/\\/$//'"; 51 | $results = shell_exec($command); 52 | if(is_null($results)) { 53 | $this->_unlock(); 54 | $this->error(__('Error'), __('Failed to fetch list of plugins using SVN.')); 55 | return 1; 56 | } 57 | $plugins = explode("\n", $results); 58 | 59 | $this->out(__('Looking for new plugins that have not been added yet...')); 60 | 61 | $plugins = array_filter($plugins, function($value) { 62 | return preg_match('/^[-0-9a-z_]+$/i', $value); 63 | }); 64 | $plugins = array_diff($plugins, $this->Plugin->find('list', array('fields' => array('slug')))); 65 | if(empty($plugins)) { 66 | $this->out(__('No new plugins to add.')); 67 | $this->_unlock(); 68 | return 0; 69 | } 70 | // TODO: Remove once live, or testing repo is in place. 71 | $plugins = array_slice($plugins, 0, 1000); 72 | 73 | $this->out(__('Saving %d new plugins...', count($plugins))); 74 | 75 | $plugins = Hash::map($plugins, '{n}', array($this, '_newPluginMap')); 76 | 77 | if($this->Plugin->saveAll($plugins, array('deep' => true))) { 78 | $this->out(__('All new plugins added successfully.')); 79 | $this->_unlock(); 80 | return 0; 81 | } 82 | $this->_unlock(); 83 | $this->error(__('Database Error'), __('Failed adding %d new plugins to the database.', count($plugins))); 84 | return 1; 85 | } 86 | 87 | /** 88 | * Helper for mapping new plugin default settings. 89 | */ 90 | function _newPluginMap($value) 91 | { 92 | return array( 93 | 'Plugin' => array( 94 | 'slug' => $value, 95 | ), 96 | 'PluginsState' => array( 97 | array( 98 | 'PluginsState' => array( 99 | 'state_id' => $this->State->getIdByName('refreshing'), 100 | ), 101 | ), 102 | ), 103 | ); 104 | } 105 | 106 | } -------------------------------------------------------------------------------- /app/Console/Command/GithubCloseShell.php: -------------------------------------------------------------------------------- 1 | close_reply = trim(' 36 | This repository is just a mirror, pull requests are not monitored or accepted 37 | here. Please look at the official page for instructions on how to contribute 38 | changes back to this plugin. If none exist, we suggest posting a new topic to 39 | address this on the support forum on WordPress.org. 40 | 41 | Official Page: %1$s 42 | Support Forum: %2$s 43 | '); 44 | parent::__construct($stdout, $stderr, $stdin); 45 | } 46 | 47 | /** 48 | * Gets the option parser instance and configures it. 49 | * 50 | * @return ConsoleOptionParser 51 | */ 52 | function getOptionParser() { 53 | $parser = parent::getOptionParser(); 54 | $parser->description(__('Closes all pull requests to mirrored repos.')); 55 | return $parser; 56 | } 57 | 58 | /** 59 | * Closes any open pull requests on mirrored repositories. 60 | * 61 | * Since these are mirrored repos, any pull requests submitted are not 62 | * monitored or handled. Since GitHub does not support turning off pull 63 | * requests, it is inevitable that users will submit them anyway. 64 | * 65 | * Note: GitHub supports turning off issues, but not pull requests. 66 | * 67 | * This utility will simply auto-close any opened pull requests while 68 | * directing author to a (hopefully) more appropriate location to submit 69 | * changes to. 70 | * 71 | * @return int Shell return code. 72 | */ 73 | function main() 74 | { 75 | $this->out(__('Fetching list of open issues...')); 76 | 77 | try { 78 | $client = new Github\Client(); 79 | $client->getHttpClient()->setOption( 80 | 'user_agent', Configure::read('GitHub.user_agent')); 81 | $client->authenticate(GITHUB_USERNAME, GITHUB_PASSWORD, 82 | Github\Client::AUTH_HTTP_PASSWORD); 83 | } catch(Exception $exception) { 84 | $this->out(__('Failed to authenticate with GitHub: %s', 85 | $exception->getMessage())); 86 | $this->_unlock(); 87 | return 1; 88 | } 89 | 90 | try { 91 | $response = $client->getHttpClient()->get('search/issues', array( 92 | 'q' => sprintf('user:%s state:open', Configure::read('GitHub.org_name')) 93 | )); 94 | $issues = $response->getContent(); 95 | } catch(Exception $exception) { 96 | $this->out(__('Failed to fetch list of open issues: %s', 97 | $exception->getMessage())); 98 | $this->_unlock(); 99 | return 1; 100 | } 101 | 102 | if($issues['total_count'] == 0) { 103 | $this->out(__('No open pull requests were found.')); 104 | $this->_unlock(); 105 | return 0; 106 | } 107 | 108 | foreach($issues['items'] as $pull_request) { 109 | $parts = explode('/', $pull_request['html_url']); 110 | $user = $parts[3]; 111 | $plugin = $parts[4]; 112 | $issue_number = $parts[6]; 113 | $plugin_page = sprintf(Configure::read('App.plugin_http_url'), $plugin); 114 | $support_page = sprintf(Configure::read('App.plugin_support_url'), $plugin); 115 | $pull_request_url = sprintf('repos/%s/%s/pulls/%d', $user, $plugin, $issue_number); 116 | 117 | try { 118 | $client->getHttpClient()->post($pull_request['comments_url'], 119 | array('body' => sprintf($this->close_reply, $plugin_page, $support_page)) 120 | ); 121 | $client->getHttpClient()->patch($pull_request_url, 122 | array('state' => 'closed') 123 | ); 124 | } catch(Exception $exception) { 125 | $this->out(__('Failed to close pull request <%s>: %s', 126 | $pull_request['html_url'], $exception->getMessage())); 127 | continue; 128 | } 129 | $this->out(__('Closed pull request: %s', $pull_request['html_url'])); 130 | } 131 | 132 | $this->out(__('Finished closing open issues on GitHub.')); 133 | $this->_unlock(); 134 | return 0; 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /app/Console/Command/StatsShell.php: -------------------------------------------------------------------------------- 1 | description(__('Updates the current iteration of stats.')); 39 | return $parser; 40 | } 41 | 42 | /** 43 | * Updates the current iteration of stats. 44 | * 45 | * @return int Shell return code. 46 | */ 47 | function main() 48 | { 49 | $this->out(__('Gathering plugin and work queue statistics...')); 50 | 51 | $plugin_count = $this->Plugin->find('count'); 52 | 53 | $this->State->recursive = -1; 54 | $states = $this->State->find('all', array( 55 | 'joins' => array( 56 | array( 57 | 'table' => 'plugins_states', 58 | 'alias' => 'PluginsState', 59 | 'type' => 'LEFT', 60 | 'conditions' => array('PluginsState.state_id = State.id'), 61 | ), 62 | ), 63 | 'fields' => array( 64 | 'State.name', 'COUNT(PluginsState.id) as count' 65 | ), 66 | 'group' => 'State.id', 67 | )); 68 | 69 | $state_counts = Hash::combine($states, '{n}.State.name', '{n}.0.count'); 70 | 71 | $stat = $this->Stat->save(array( 72 | 'total' => $plugin_count, 73 | 'cloned' => $state_counts['cloned'], 74 | 'cloning' => $state_counts['cloning'], 75 | 'refreshing' => $state_counts['refreshing'], 76 | 'removed' => $state_counts['removed'], 77 | 'updating' => $state_counts['updating'], 78 | )); 79 | 80 | if(!$stat) { 81 | $this->_unlock(); 82 | $this->error(__('Database Error'), __('Failed saving plugin statistics to the database.')); 83 | } 84 | 85 | $this->out(__('Saved statistics successfully.')); 86 | $this->_unlock(); 87 | return 0; 88 | } 89 | 90 | } -------------------------------------------------------------------------------- /app/Console/Command/UpdateShell.php: -------------------------------------------------------------------------------- 1 | description(__('Updates the git clones from SVN.')); 37 | $parser->addArgument('max', array('help' => __('Maximum number of plugins to update.'))); 38 | return $parser; 39 | } 40 | 41 | /** 42 | * Updates plugin git repositories from SVN. 43 | * 44 | * If unspecified, a maximum of 5 plugins will be updated with one run. 45 | * 46 | * @return int Shell return code. 47 | */ 48 | function main() 49 | { 50 | $max = 5; 51 | if(isset($this->args[0]) && is_numeric($this->args[0]) && $this->args[0] > 0) { 52 | $max = (int) $this->args[0]; 53 | } 54 | 55 | $plugins = $this->Plugin->findByState('updating', array( 56 | 'contain' => array( 57 | 'PluginsState' => array('State'), 58 | ), 59 | 'order' => array('InnerPluginsState.modified'), 60 | 'limit' => $max, 61 | )); 62 | 63 | if(count($plugins) == 0) { 64 | $this->out(__('No plugins need to be updated.')); 65 | $this->_unlock(); 66 | return 0; 67 | } 68 | 69 | $this->out(__('Updating %d plugins...', count($plugins))); 70 | 71 | foreach($plugins as $plugin) 72 | { 73 | $this->out(__('Updating: "%s" (%d)', 74 | $plugin['Plugin']['slug'], 75 | $plugin['Plugin']['id'])); 76 | 77 | $git_path = sprintf(Configure::read('App.plugin_repo_path'), $plugin['Plugin']['slug']); 78 | $log_path = TMP . 'logs' . DS . 'git' . DS . $plugin['Plugin']['slug'] . '.log'; 79 | 80 | if(!chdir($git_path)) { 81 | $this->out(__('Failed reading the git clone path.')); 82 | $this->PluginsState->touch($plugin['InnerPluginsState']['id']); 83 | continue; 84 | } 85 | 86 | try 87 | { 88 | $this->_exec('git svn fetch --quiet --quiet >> %s 2>&1', $log_path); 89 | $this->_exec('git svn rebase --quiet --quiet >> %s 2>&1', $log_path); 90 | 91 | $existing_tags = $this->_exec('git tag --list'); 92 | $tags = $this->_exec( 93 | 'git for-each-ref --format %s %s | cut --delimiter / --fields 3-', 94 | '%(refname:short)', 'refs/remotes/svn/tags' 95 | ); 96 | $tags = array_diff($tags, $existing_tags); 97 | foreach($tags as $tag) { 98 | $this->_exec( 99 | 'git tag %s %s >> %s 2>&1', $tag, 100 | sprintf('refs/remotes/svn/tags/%s', $tag), $log_path 101 | ); 102 | } 103 | 104 | $branches = $this->_getBranches($plugin['Plugin']['slug']); 105 | foreach($branches as $branch) { 106 | $this->_exec( 107 | 'git branch --force %s %s >> %s 2>&1', $branch, 108 | sprintf('refs/remotes/svn/%s', $branch), $log_path 109 | ); 110 | } 111 | 112 | $this->_exec( 113 | 'git push --mirror %s >> %s 2>&1', 114 | sprintf(Configure::read('App.plugin_git_url'), $plugin['Plugin']['slug']), 115 | $log_path 116 | ); 117 | } 118 | catch(RuntimeException $e) 119 | { 120 | $this->out(__('Failed to update "%s", please check the git log file.', 121 | $plugin['Plugin']['slug'])); 122 | $this->PluginsState->touch($plugin['InnerPluginsState']['id']); 123 | continue; 124 | } 125 | 126 | if(!$this->PluginsState->delete($plugin['InnerPluginsState']['id'])) { 127 | $this->out(__('Failed removing "updating" state on cloned plugin.')); 128 | $this->PluginsState->touch($plugin['InnerPluginsState']['id']); 129 | } 130 | } 131 | 132 | $this->out(__('Finished updating plugins.')); 133 | $this->_unlock(); 134 | return 0; 135 | } 136 | 137 | /** 138 | * Fetches the list of plugin branches from SVN. 139 | * 140 | * @param $plugin_slug 141 | * 142 | * @return array 143 | */ 144 | protected function _getBranches($plugin_slug) 145 | { 146 | $svn_url = sprintf(Configure::read('App.plugin_svn_url'), $plugin_slug); 147 | 148 | $branches = array(); 149 | 150 | try 151 | { 152 | $xml_list = $this->_exec( 153 | 'svn list --xml %s', $svn_url . 'branches' 154 | ); 155 | $data = Xml::build(implode('', $xml_list)); 156 | foreach($data->list->entry as $path) { 157 | if($path['kind'] != 'dir') 158 | continue; 159 | $branches[] = $path->name; 160 | } 161 | } 162 | catch(Exception $e) 163 | { 164 | return array(); 165 | } 166 | 167 | return $branches; 168 | } 169 | 170 | } -------------------------------------------------------------------------------- /app/Console/cake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ################################################################################ 3 | # 4 | # Bake is a shell script for running CakePHP bake script 5 | # PHP 5 6 | # 7 | # CakePHP(tm) : Rapid Development Framework (http://cakephp.org) 8 | # Copyright 2005-2012, Cake Software Foundation, Inc. 9 | # 10 | # Licensed under The MIT License 11 | # Redistributions of files must retain the above copyright notice. 12 | # 13 | # @copyright Copyright 2005-2012, Cake Software Foundation, Inc. 14 | # @link http://cakephp.org CakePHP(tm) Project 15 | # @package app.Console 16 | # @since CakePHP(tm) v 2.0 17 | # @license MIT License (http://www.opensource.org/licenses/mit-license.php) 18 | # 19 | ################################################################################ 20 | LIB=$(cd -P -- "$(dirname -- "$0")" && pwd -P) && LIB=$LIB/$(basename -- "$0") 21 | 22 | while [ -h "$LIB" ]; do 23 | DIR=$(dirname -- "$LIB") 24 | SYM=$(readlink "$LIB") 25 | LIB=$(cd "$DIR" && cd $(dirname -- "$SYM") && pwd)/$(basename -- "$SYM") 26 | done 27 | 28 | LIB=$(dirname -- "$LIB")/ 29 | APP=$(dirname -- $(dirname -- "$LIB"))/app 30 | 31 | exec php -q "$LIB"cake.php -working "$APP" "$@" 32 | 33 | exit; 34 | -------------------------------------------------------------------------------- /app/Console/cake.bat: -------------------------------------------------------------------------------- 1 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 2 | :: 3 | :: Bake is a shell script for running CakePHP bake script 4 | :: PHP 5 5 | :: 6 | :: CakePHP(tm) : Rapid Development Framework (http://cakephp.org) 7 | :: Copyright 2005-2012, Cake Software Foundation, Inc. 8 | :: 9 | :: Licensed under The MIT License 10 | :: Redistributions of files must retain the above copyright notice. 11 | :: 12 | :: @copyright Copyright 2005-2012, Cake Software Foundation, Inc. 13 | :: @link http://cakephp.org CakePHP(tm) Project 14 | :: @package app.Console 15 | :: @since CakePHP(tm) v 2.0 16 | :: @license MIT License (http://www.opensource.org/licenses/mit-license.php) 17 | :: 18 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 19 | 20 | :: In order for this script to work as intended, the cake\console\ folder must be in your PATH 21 | 22 | @echo. 23 | @echo off 24 | 25 | SET app=%0 26 | SET lib=%~dp0 27 | 28 | php -q "%lib%cake.php" -working "%CD% " %* 29 | 30 | echo. 31 | 32 | exit /B %ERRORLEVEL% 33 | -------------------------------------------------------------------------------- /app/Console/cake.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | array(), 38 | 'Paginator' => array( 39 | 'paramType' => 'querystring', 40 | 'limit' => 10, 41 | ), 42 | 'RequestHandler' => array(), 43 | 'Security' => array(), 44 | 'Session' => array(), 45 | ); 46 | 47 | /** 48 | * Helpers 49 | * 50 | * @var array 51 | */ 52 | public $helpers = array( 53 | 'Form' => array('className' => 'AppForm'), 54 | 'Html' => array('className' => 'AppHtml', 'configFile' => 'html_tags'), 55 | 'Paginator' => array('className' => 'AppPaginator'), 56 | 'Session', 57 | ); 58 | 59 | /** 60 | * beforeFilter method 61 | * 62 | * @return void 63 | */ 64 | public function beforeFilter() 65 | { 66 | $this->Setting->load(); 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /app/Controller/ContributorsController.php: -------------------------------------------------------------------------------- 1 | array( 29 | 'contain' => array('Plugin'), 30 | ), 31 | ); 32 | 33 | /** 34 | * index action 35 | * 36 | * @return void 37 | */ 38 | public function index() 39 | { 40 | $this->set(array( 41 | 'contributors' => $this->Paginator->paginate(), 42 | '_serialize' => array('contributors') 43 | )); 44 | } 45 | 46 | /** 47 | * view action 48 | * 49 | * @throws NotFoundException 50 | * @param string $name 51 | * @return void 52 | */ 53 | public function view($name = null) 54 | { 55 | $contributor = $this->Contributor->find('first', array( 56 | 'contain' => array( 57 | 'Plugin' => array( 58 | 'Description', 59 | 'PluginState' => array('State'), 60 | 'Tag', 61 | ), 62 | ), 63 | 'conditions' => array( 64 | 'Contributor.name' => $name, 65 | ), 66 | )); 67 | if (!$contributor) { 68 | throw new NotFoundException(__('Invalid contributor')); 69 | } 70 | $this->set(array( 71 | 'contributor' => $contributor, 72 | '_serialize' => array('contributor') 73 | )); 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /app/Controller/DescriptionsController.php: -------------------------------------------------------------------------------- 1 | array( 29 | 'contain' => array('Plugin'), 30 | ), 31 | ); 32 | 33 | /** 34 | * index action 35 | * 36 | * @return void 37 | */ 38 | public function index() 39 | { 40 | $this->set(array( 41 | 'descriptions' => $this->Paginator->paginate(), 42 | '_serialize' => array('descriptions') 43 | )); 44 | } 45 | 46 | /** 47 | * view action 48 | * 49 | * @throws NotFoundException 50 | * @param string $id 51 | * @return void 52 | */ 53 | public function view($id = null) 54 | { 55 | $description = $this->Description->find('first', array( 56 | 'contain' => array( 57 | 'Plugin' => array( 58 | 'Contributor', 59 | 'PluginsState' => array('State'), 60 | 'Tag', 61 | ), 62 | ), 63 | 'conditions' => array( 64 | 'Description.id' => $id, 65 | ), 66 | )); 67 | if (!$description) { 68 | throw new NotFoundException(__('Invalid description')); 69 | } 70 | $this->set(array( 71 | 'description' => $description, 72 | '_serialize' => array('description') 73 | )); 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /app/Controller/PagesController.php: -------------------------------------------------------------------------------- 1 | redirect('/'); 50 | } 51 | $page = $subpage = $title = null; 52 | 53 | if (!empty($path[0])) { 54 | $page = $path[0]; 55 | } 56 | if (!empty($path[1])) { 57 | $subpage = $path[1]; 58 | } 59 | if (!empty($path[$count - 1])) { 60 | $title = Inflector::humanize($path[$count - 1]); 61 | } 62 | $this->set(compact('page', 'subpage')); 63 | $this->set('title_for_layout', $title); 64 | $this->render(implode('/', $path)); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /app/Controller/PluginsController.php: -------------------------------------------------------------------------------- 1 | array( 28 | 'contain' => array( 29 | 'Contributor', 30 | 'Description', 31 | 'PluginsState' => array('State'), 32 | 'Tag', 33 | ), 34 | 'order' => array( 35 | 'Plugin.wp_updated' => 'desc' 36 | ), 37 | ), 38 | ); 39 | 40 | /** 41 | * index action 42 | * 43 | * @return void 44 | */ 45 | function index() 46 | { 47 | $this->set(array( 48 | 'plugins' => $this->Paginator->paginate(), 49 | '_serialize' => array('plugins') 50 | )); 51 | } 52 | 53 | /** 54 | * view action 55 | * 56 | * @param string $slug 57 | * 58 | * @throws NotFoundException 59 | * @return void 60 | */ 61 | function view($slug = null) 62 | { 63 | $plugin = $this->Plugin->find('first', array( 64 | 'contain' => array( 65 | 'Contributor', 66 | 'Description', 67 | 'PluginsState' => array('State'), 68 | 'Tag', 69 | ), 70 | 'conditions' => array( 71 | 'slug' => $slug, 72 | ), 73 | )); 74 | if (!$plugin) { 75 | throw new NotFoundException(__('Invalid plugin')); 76 | } 77 | $this->set(array( 78 | 'title_for_layout' => $plugin['Plugin']['display_name'], 79 | 'plugin' => $plugin, 80 | '_serialize' => array('plugin') 81 | )); 82 | } 83 | 84 | /** 85 | * mirror action 86 | * 87 | * @param null $slug 88 | * 89 | * @throws NotFoundException 90 | * @return void 91 | */ 92 | function mirror($slug = null) 93 | { 94 | $this->PluginsState->recursive = -1; 95 | $cloning_count = $this->PluginsState->find('count', array( 96 | 'conditions' => array( 97 | 'PluginsState.ip_address' => $this->request->clientIp(false), 98 | ), 99 | )); 100 | 101 | if($cloning_count >= Configure::read('App.max_cloning_per_ip')) { 102 | $this->Session->setFlash( 103 | __('You have reached the maximum of %s plugins queued for cloning currently, please try again later.', Configure::read('App.max_cloning_per_ip')), 104 | 'alert-warning', array('close' => true)); 105 | $this->redirect($this->referer()); 106 | } 107 | 108 | $plugin = $this->Plugin->find('first', array( 109 | 'contain' => array( 110 | 'PluginsState' => array('State'), 111 | ), 112 | 'conditions' => array( 113 | 'slug' => $slug, 114 | ), 115 | )); 116 | 117 | // Some basic sanity checks... 118 | if (!$plugin) { 119 | throw new NotFoundException(__('Invalid plugin')); 120 | } 121 | if(in_array('cloned', Hash::extract($plugin, 'PluginsState.{n}.State.name'))) { 122 | $this->Session->setFlash(__('This plugin has already been cloned.'), 123 | 'alert-error', array('close' => true)); 124 | $this->redirect($this->referer()); 125 | } 126 | if(in_array('cloning', Hash::extract($plugin, 'PluginsState.{n}.State.name'))) { 127 | $this->Session->setFlash(__('This plugin is already in the cloning queue.'), 128 | 'alert-error', array('close' => true)); 129 | $this->redirect($this->referer()); 130 | } 131 | 132 | if($this->PluginsState->findOrCreate($plugin['Plugin']['id'], 'cloning', 133 | $this->request->clientIp(false))) { 134 | $this->Session->setFlash(__('Plugin has been added to the queue to be cloned.'), 135 | 'alert-success', array('close' => true)); 136 | $this->redirect($this->referer()); 137 | } 138 | 139 | $this->Session->setFlash(__('There was a problem adding the plugin to the cloning queue.'), 140 | 'alert-error', array('close' => true)); 141 | $this->redirect($this->referer()); 142 | } 143 | 144 | } 145 | -------------------------------------------------------------------------------- /app/Controller/PluginsStatesController.php: -------------------------------------------------------------------------------- 1 | array( 29 | 'contain' => array( 30 | 'Plugin', 31 | 'State', 32 | ), 33 | ), 34 | ); 35 | 36 | /** 37 | * index action 38 | * 39 | * @return void 40 | */ 41 | public function index() 42 | { 43 | $this->set(array( 44 | 'pluginsStates' => $this->Paginator->paginate(), 45 | '_serialize' => array('pluginsStates') 46 | )); 47 | } 48 | 49 | /** 50 | * view action 51 | * 52 | * @throws NotFoundException 53 | * @param string $id 54 | * @return void 55 | */ 56 | public function view($id = null) 57 | { 58 | $pluginState = $this->PluginsState->find('first', array( 59 | 'contain' => array( 60 | 'Plugin' => array('Contributor', 'Tag'), 61 | 'State', 62 | ), 63 | 'conditions' => array( 64 | 'PluginsState.id' => $id, 65 | ), 66 | )); 67 | if (!$pluginState) { 68 | throw new NotFoundException(__('Invalid plugin state')); 69 | } 70 | $this->set(array( 71 | 'pluginsState' => $pluginState, 72 | '_serialize' => array('pluginsState') 73 | )); 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /app/Controller/SettingsController.php: -------------------------------------------------------------------------------- 1 | array('className' => 'SettingsForm'), 27 | ); 28 | 29 | /** 30 | * manage action 31 | * 32 | * @throws NotFoundException 33 | * @return void 34 | */ 35 | public function manage() 36 | { 37 | // This needs auth restrictions if it is ever enabled in production, 38 | // but this can still be helpful during development. 39 | if(Configure::read('debug') < 2) { 40 | throw new NotFoundException(); 41 | } 42 | 43 | $this->set('title_for_layout', __('Application Settings')); 44 | 45 | if ($this->request->is('post') || $this->request->is('put')) { 46 | if ($this->Setting->update($this->request->data['Setting'])) { 47 | $this->Session->setFlash( 48 | __('All settings have been saved.'), 'alert-success' 49 | ); 50 | $this->Setting->load(); 51 | } else { 52 | $this->Session->setFlash( 53 | __('Settings could not be saved.'), 'alert-error' 54 | ); 55 | } 56 | } 57 | 58 | if (!$this->request->data) { 59 | $this->request->data = array('Setting' => Configure::read()); 60 | } 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /app/Controller/StatesController.php: -------------------------------------------------------------------------------- 1 | array( 29 | 'contain' => array(), 30 | ), 31 | ); 32 | 33 | /** 34 | * index action 35 | * 36 | * @return void 37 | */ 38 | public function index() 39 | { 40 | $this->set(array( 41 | 'states' => $this->Paginator->paginate(), 42 | '_serialize' => array('states') 43 | )); 44 | } 45 | 46 | /** 47 | * view action 48 | * 49 | * @throws NotFoundException 50 | * @param string $name 51 | * @return void 52 | */ 53 | public function view($name = null) 54 | { 55 | $state = $this->State->find('first', array( 56 | 'contain' => array( 57 | 'PluginsState' => array('Plugin'), 58 | ), 59 | 'conditions' => array( 60 | 'State.name' => $name, 61 | ), 62 | )); 63 | if (!$state) { 64 | throw new NotFoundException(__('Invalid state')); 65 | } 66 | $this->set(array( 67 | 'state' => $state, 68 | '_serialize' => array('state') 69 | )); 70 | } 71 | 72 | } -------------------------------------------------------------------------------- /app/Controller/StatsController.php: -------------------------------------------------------------------------------- 1 | array( 29 | 'maxLimit' => 2016, // 14 days of stats 30 | 'limit' => 288, // 2 days of stats 31 | 'fields' => array( 32 | 'total', 'cloned', 'cloning', 'refreshing', 33 | 'removed', 'updating', 'created_iso8601' 34 | ), 35 | 'order' => array('Stat.created' => 'DESC') 36 | ), 37 | ); 38 | 39 | /** 40 | * index method 41 | * 42 | * @return void 43 | */ 44 | public function index() { 45 | if(in_array($this->RequestHandler->ext, array('json', 'xml'))) { 46 | $this->set('stats', $this->Paginator->paginate()); 47 | } else { 48 | $this->set('title_for_layout', __('Status')); 49 | $this->set('latest_stat', $this->Stat->find('first', array( 50 | 'order' => 'Stat.created DESC', 51 | ))); 52 | } 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /app/Controller/TagsController.php: -------------------------------------------------------------------------------- 1 | array( 29 | 'contain' => array('Plugin'), 30 | ), 31 | ); 32 | 33 | /** 34 | * index action 35 | * 36 | * @return void 37 | */ 38 | public function index() 39 | { 40 | $this->set(array( 41 | 'tags' => $this->Paginator->paginate(), 42 | '_serialize' => array('tags') 43 | )); 44 | } 45 | 46 | /** 47 | * view action 48 | * 49 | * @throws NotFoundException 50 | * @param string $name 51 | * @return void 52 | */ 53 | public function view($name = null) 54 | { 55 | $tag = $this->Tag->find('first', array( 56 | 'contain' => array( 57 | 'Plugin' => array( 58 | // With thousands of plugins, this needs to be conservative. 59 | 'fields' => array('id', 'slug', 'display_name', 'wp_updated'), 60 | ), 61 | ), 62 | 'conditions' => array( 63 | 'Tag.name' => $name, 64 | ), 65 | )); 66 | if (!$tag) { 67 | throw new NotFoundException(__('Invalid tag')); 68 | } 69 | $this->set(array( 70 | 'tag' => $tag, 71 | '_serialize' => array('tag') 72 | )); 73 | } 74 | 75 | } -------------------------------------------------------------------------------- /app/Model/AppModel.php: -------------------------------------------------------------------------------- 1 | cacheKey = Configure::read('Session.handler.cache'); 32 | parent::__construct(); 33 | } 34 | 35 | /** 36 | * @param int|string $id 37 | * 38 | * @return mixed 39 | */ 40 | public function read($id) 41 | { 42 | $result = Cache::read($id, $this->cacheKey); 43 | if ($result) { 44 | return $result; 45 | } 46 | 47 | return parent::read($id); 48 | } 49 | 50 | /** 51 | * @param int $id 52 | * @param mixed $data 53 | * @return bool 54 | */ 55 | public function write($id, $data) 56 | { 57 | Cache::write($id, $data, $this->cacheKey); 58 | 59 | return parent::write($id, $data); 60 | } 61 | 62 | /** 63 | * @param int $id 64 | * @return bool 65 | */ 66 | public function destroy($id) 67 | { 68 | Cache::delete($id, $this->cacheKey); 69 | 70 | return parent::destroy($id); 71 | } 72 | 73 | /** 74 | * @param null $expires 75 | * @return bool 76 | */ 77 | public function gc($expires = null) 78 | { 79 | return Cache::gc($this->cacheKey) && parent::gc($expires); 80 | } 81 | 82 | } -------------------------------------------------------------------------------- /app/Model/Description.php: -------------------------------------------------------------------------------- 1 | array('dependent' => true), 41 | ); 42 | 43 | /** 44 | * hasOne associations 45 | * 46 | * @var array 47 | */ 48 | public $hasOne = array('Description'); 49 | 50 | /** 51 | * Property data validation settings. 52 | * 53 | * @var array 54 | */ 55 | public $validate = array( 56 | 'slug' => array( 57 | 'maxlength' => array( 58 | 'rule' => array('maxlength', 255), 59 | //'message' => 'Your custom message here', 60 | //'allowEmpty' => false, 61 | //'required' => false, 62 | //'last' => false, // Stop validation after this rule 63 | //'on' => 'create', // Limit validation to 'create' or 'update' operations 64 | ), 65 | 'notempty' => array( 66 | 'rule' => array('notempty'), 67 | //'message' => 'Your custom message here', 68 | //'allowEmpty' => false, 69 | //'required' => false, 70 | //'last' => false, // Stop validation after this rule 71 | //'on' => 'create', // Limit validation to 'create' or 'update' operations 72 | ), 73 | // 'custom' => array( 74 | // 'rule' => array('custom'), 75 | // //'message' => 'Your custom message here', 76 | // //'allowEmpty' => false, 77 | // //'required' => false, 78 | // //'last' => false, // Stop validation after this rule 79 | // //'on' => 'create', // Limit validation to 'create' or 'update' operations 80 | // ), 81 | ), 82 | ); 83 | 84 | /** 85 | * Plugin constructor. 86 | * 87 | * @param array|bool|int|string $id Set this ID for this model on startup, can also be an array of options, see Model::__construct(). 88 | * @param string $table Name of database table to use. 89 | * @param string $ds DataSource connection name. 90 | */ 91 | public function __construct($id = false, $table = null, $ds = null) 92 | { 93 | parent::__construct($id, $table, $ds); 94 | 95 | $this->virtualFields['display_name'] = sprintf('IFNULL(%1$s.name, %1$s.slug)', $this->alias); 96 | } 97 | 98 | /** 99 | * Find all plugins with all of the states provided. 100 | * 101 | * @param string|array $states State name or array of states to search for. 102 | * @param array $query Additional find conditions. 103 | * 104 | * @return array Array of plugin records, or null on failure. 105 | */ 106 | public function findByState($states, $query = array()) 107 | { 108 | if(!is_array($states)) { 109 | $states = array($states); 110 | } 111 | 112 | $this->bindModel(array('hasOne' => array( 113 | 'InnerPluginsState' => array( 114 | 'className' => 'PluginsState', 115 | 'foreignKey' => false, 116 | 'type' => 'INNER', 117 | 'conditions' => array( 118 | 'InnerPluginsState.plugin_id = Plugin.id' 119 | ), 120 | ), 121 | 'InnerState' => array( 122 | 'className' => 'State', 123 | 'foreignKey' => false, 124 | 'type' => 'INNER', 125 | 'conditions' => array( 126 | 'InnerState.id = InnerPluginsState.state_id', 127 | 'InnerState.name' => $states, 128 | ), 129 | ), 130 | ))); 131 | 132 | $query = Hash::merge($query, array( 133 | 'contain' => array( 134 | 'InnerPluginsState', 135 | 'InnerState', 136 | ), 137 | 'group' => array( 138 | 'Plugin.id', 139 | 'HAVING COUNT(Plugin.id) =' => count($states), 140 | ), 141 | )); 142 | 143 | return $this->find('all', $query); 144 | } 145 | 146 | /** 147 | * Save method overridden from parent Model::save() in order to clear 148 | * modified field if it's set (so all modifications result in an updated 149 | * date in the modified field). 150 | * 151 | * @see http://book.cakephp.org/2.0/en/models/saving-your-data.html#using-created-and-modified 152 | * 153 | * @param array $data Data to save. 154 | * @param boolean|array $validate Either a boolean, or an array. 155 | * If a boolean, indicates whether or not to validate before saving. 156 | * If an array, can have following keys: 157 | * 158 | * - validate: Set to true/false to enable or disable validation. 159 | * - fieldList: An array of fields you want to allow for saving. 160 | * - callbacks: Set to false to disable callbacks. Using 'before' or 'after' 161 | * will enable only those callbacks. 162 | * 163 | * @param array $fieldList List of fields to allow to be saved 164 | * @return mixed On success Model::$data if its not empty or true, false on failure 165 | */ 166 | public function save($data = null, $validate = true, $fieldList = array()) { 167 | // Clear modified field value before each save 168 | $this->set($data); 169 | if (isset($this->data[$this->alias]['modified'])) { 170 | unset($this->data[$this->alias]['modified']); 171 | } 172 | return parent::save($this->data, $validate, $fieldList); 173 | } 174 | 175 | } -------------------------------------------------------------------------------- /app/Model/PluginsState.php: -------------------------------------------------------------------------------- 1 | create(array('id' => $id)); 45 | return $this->save(); 46 | } 47 | 48 | /** 49 | * Returns the given PluginsState, creating it if it does not exist. 50 | * 51 | * @param integer $plugin_id 52 | * @param string $state_name 53 | * @param string $ip_address 54 | * 55 | * @return array|bool 56 | */ 57 | public function findOrCreate($plugin_id, $state_name, $ip_address = null) 58 | { 59 | $state_id = $this->State->getIdByName($state_name); 60 | 61 | if($state_id === false) { 62 | return false; 63 | } 64 | 65 | $this->recursive = -1; 66 | $plugin_state = $this->find('first', array( 67 | 'conditions' => array( 68 | 'PluginsState.plugin_id' => $plugin_id, 69 | 'PluginsState.state_id' => $state_id, 70 | ) 71 | )); 72 | 73 | if(empty($plugin_state)) { 74 | $this->create(array( 75 | 'plugin_id' => $plugin_id, 76 | 'state_id' => $state_id, 77 | )); 78 | if(!is_null($ip_address)) { 79 | $this->set('ip_address', $ip_address); 80 | } 81 | return $this->save(); 82 | } 83 | 84 | return $plugin_state; 85 | } 86 | 87 | /** 88 | * Returns the number of plugins with the given state. 89 | * 90 | * @param string $state_name Name of the state. 91 | * 92 | * @return int 93 | */ 94 | public function count($state_name) 95 | { 96 | $this->recursive = -1; 97 | $count = $this->find('count', array( 98 | 'conditions' => array( 99 | 'state_id' => $this->State->getIdByName($state_name), 100 | ), 101 | )); 102 | 103 | return $count; 104 | } 105 | 106 | } -------------------------------------------------------------------------------- /app/Model/Session.php: -------------------------------------------------------------------------------- 1 | validate = array( 41 | 'App.name' => array( 42 | 'maxLength' => array( 43 | 'rule' => array('maxLength', 40), 44 | 'allowEmpty' => false, 45 | 'message' => __('Name is required, and must be less than 40 characters long.') 46 | ), 47 | ), 48 | ); 49 | } 50 | 51 | /** 52 | * Update all the settings. Validation rules are also configured here. 53 | * 54 | * @param array $data Associative array of all settings to save. 55 | * 56 | * @return boolean 57 | */ 58 | function update($data = array()) 59 | { 60 | $flat_data = Hash::flatten($data); 61 | $this->set($flat_data); 62 | 63 | if ($this->validates()) { 64 | $list = $this->find('list', array('fields' => array('key', 'id'))); 65 | foreach ($flat_data as $key => $value) { 66 | if(array_key_exists($key, $list)) { 67 | // This setting already exists in the DB, just update it. 68 | $this->id = $list[$key]; 69 | $this->saveField('value', $value); 70 | } else { 71 | // This is a new setting, add a new entry. 72 | $this->create(); 73 | $this->save(array('key' => $key, 'value' => $value)); 74 | } 75 | } 76 | return true; 77 | } 78 | return false; 79 | } 80 | 81 | /** 82 | * Reads all settings from the database, and writes them to the configuration. 83 | * 84 | * @return void 85 | */ 86 | function load() 87 | { 88 | Configure::write($this->find('list', array('fields' => array('key', 'value')))); 89 | 90 | /* Settings found here always override anything set in the database. */ 91 | Configure::load('settings'); 92 | } 93 | 94 | /** 95 | * Save an individual setting to the database. 96 | * 97 | * @param string $key The dot-notation form of the setting key. 98 | * @param mixed $value Any serializable value. 99 | * 100 | * @return bool|mixed On success data if its not empty or true, false on failure 101 | */ 102 | function write($key, $value) 103 | { 104 | $setting = $this->findByKey($key); 105 | if(!empty($setting)) { 106 | $this->id = $setting['Setting']['id']; 107 | $setting = $this->saveField('value', $value, true); 108 | $this->load(); 109 | return $setting; 110 | } 111 | $this->create(array('key' => $key, 'value' => $value)); 112 | $setting = $this->save(); 113 | $this->load(); 114 | return $setting; 115 | } 116 | 117 | /** 118 | * Unserialize all settings fetched from the database before being used. 119 | * 120 | * @param mixed $results The results of the find operation. 121 | * @param bool $primary Whether this model is being queried directly (vs. being queried as an association) 122 | * 123 | * @return array Unserialized setting data. 124 | */ 125 | function afterFind($results, $primary = false) 126 | { 127 | if($primary) { 128 | foreach($results as &$result) { 129 | if(!empty($result['Setting']['value'])) { 130 | $result['Setting']['value'] = unserialize($result['Setting']['value']); 131 | } 132 | } 133 | } 134 | return $results; 135 | } 136 | 137 | /** 138 | * Serialize all settings saved to the database. 139 | * 140 | * @param array $options 141 | * 142 | * @return bool Always returns true to continue saving regardless of whether 143 | * it found data that needed to be serialized or not. 144 | */ 145 | function beforeSave($options = array()) 146 | { 147 | if(!empty($this->data['Setting']['value'])) { 148 | $this->data['Setting']['value'] = serialize($this->data['Setting']['value']); 149 | } 150 | return true; 151 | } 152 | 153 | } -------------------------------------------------------------------------------- /app/Model/Stat.php: -------------------------------------------------------------------------------- 1 | virtualFields['created_iso8601'] = sprintf( 32 | 'DATE_FORMAT(%1$s.created, %2$s)', 33 | $this->alias, "'%Y-%m-%dT%TZ'"); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /app/Model/State.php: -------------------------------------------------------------------------------- 1 | array( 40 | 'dependent' => true, 41 | 'order' => 'PluginsState.modified', 42 | ), 43 | ); 44 | 45 | /** 46 | * Finds cached State id by the given name. 47 | * 48 | * @param string $state_name Name of the state. 49 | * 50 | * @return bool 51 | */ 52 | public function getIdByName($state_name) 53 | { 54 | if (($states = Cache::read('states_by_name')) === false) { 55 | $this->recursive = -1; 56 | $states = $this->find('all'); 57 | $states = Hash::combine($states, '{n}.State.name', '{n}.State.id'); 58 | Cache::write('states_by_name', $states); 59 | } 60 | 61 | if(array_key_exists($state_name, $states)) { 62 | return $states[$state_name]; 63 | } 64 | 65 | return false; 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /app/Model/Tag.php: -------------------------------------------------------------------------------- 1 | addTestDirectoryRecursive(APP_TEST_CASES); 25 | return $suite; 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /app/Test/Case/Console/Command/CheckShellTest.php: -------------------------------------------------------------------------------- 1 | getMock('ConsoleOutput', array(), array(), '', false); 29 | $in = $this->getMock('ConsoleInput', array(), array(), '', false); 30 | 31 | $this->shell = $this->getMock('CheckShell', 32 | array('_checkLock', '_unlock', 'in', 'err', 'createFile', '_stop', 'clear'), 33 | array($out, $out, $in) 34 | ); 35 | 36 | $this->shell->initialize(); 37 | $this->shell->loadTasks(); 38 | $this->shell->startup(); 39 | } 40 | 41 | public function tearDown() 42 | { 43 | parent::tearDown(); 44 | 45 | unset($this->shell); 46 | } 47 | 48 | public function testMain() 49 | { 50 | $this->assertIdentical($this->shell->main(), null, 51 | __('Check shell failed.')); 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /app/Test/Case/Console/Command/CloneShellTest.php: -------------------------------------------------------------------------------- 1 | getMock('ConsoleOutput', array(), array(), '', false); 29 | $in = $this->getMock('ConsoleInput', array(), array(), '', false); 30 | 31 | $this->shell = $this->getMock('CloneShell', 32 | array('_checkLock', '_unlock', 'in', 'err', 'createFile', '_stop', 'clear'), 33 | array($out, $out, $in) 34 | ); 35 | 36 | $this->shell->initialize(); 37 | $this->shell->loadTasks(); 38 | $this->shell->startup(); 39 | } 40 | 41 | public function tearDown() 42 | { 43 | parent::tearDown(); 44 | 45 | unset($this->shell); 46 | } 47 | 48 | public function testMain() 49 | { 50 | $this->assertIdentical($this->shell->main(), null, 51 | __('Clone shell failed.')); 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /app/Test/Case/Console/Command/RefreshShellTest.php: -------------------------------------------------------------------------------- 1 | getMock('ConsoleOutput', array(), array(), '', false); 31 | $in = $this->getMock('ConsoleInput', array(), array(), '', false); 32 | 33 | $this->shell = $this->getMock('RefreshShell', 34 | array('_checkLock', '_unlock', 'in', 'err', 'createFile', '_stop', 'clear'), 35 | array($out, $out, $in) 36 | ); 37 | 38 | $this->shell->initialize(); 39 | $this->shell->loadTasks(); 40 | $this->shell->startup(); 41 | } 42 | 43 | public function tearDown() 44 | { 45 | parent::tearDown(); 46 | 47 | unset($this->shell); 48 | } 49 | 50 | public function testMain() 51 | { 52 | $this->assertIdentical($this->shell->main(), 0, 53 | __('Refresh shell failed.')); 54 | } 55 | 56 | public function testQueue() 57 | { 58 | $this->assertIdentical($this->shell->queue(), 0, 59 | __('Refresh queue shell failed.')); 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /app/Test/Case/Console/Command/ScanShellTest.php: -------------------------------------------------------------------------------- 1 | getMock('ConsoleOutput', array(), array(), '', false); 29 | $in = $this->getMock('ConsoleInput', array(), array(), '', false); 30 | 31 | $this->shell = $this->getMock('ScanShell', 32 | array('_checkLock', '_unlock', 'in', 'err', 'createFile', '_stop', 'clear'), 33 | array($out, $out, $in) 34 | ); 35 | 36 | $this->shell->initialize(); 37 | $this->shell->loadTasks(); 38 | $this->shell->startup(); 39 | } 40 | 41 | public function tearDown() 42 | { 43 | parent::tearDown(); 44 | 45 | unset($this->shell); 46 | } 47 | 48 | public function testMain() 49 | { 50 | $this->assertIdentical($this->shell->main(), null, 51 | __('Scan shell failed.')); 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /app/Test/Case/Console/Command/StatsShellTest.php: -------------------------------------------------------------------------------- 1 | getMock('ConsoleOutput', array(), array(), '', false); 29 | $in = $this->getMock('ConsoleInput', array(), array(), '', false); 30 | 31 | $this->shell = $this->getMock('StatsShell', 32 | array('_checkLock', '_unlock', 'in', 'err', 'createFile', '_stop', 'clear'), 33 | array($out, $out, $in) 34 | ); 35 | 36 | $this->shell->initialize(); 37 | $this->shell->loadTasks(); 38 | $this->shell->startup(); 39 | } 40 | 41 | public function tearDown() 42 | { 43 | parent::tearDown(); 44 | 45 | unset($this->shell); 46 | } 47 | 48 | public function testMain() 49 | { 50 | $this->assertIdentical($this->shell->main(), null, 51 | __('Stats shell failed.')); 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /app/Test/Case/Console/Command/UpdateShellTest.php: -------------------------------------------------------------------------------- 1 | getMock('ConsoleOutput', array(), array(), '', false); 29 | $in = $this->getMock('ConsoleInput', array(), array(), '', false); 30 | 31 | $this->shell = $this->getMock('UpdateShell', 32 | array('_checkLock', '_unlock', 'in', 'err', 'createFile', '_stop', 'clear'), 33 | array($out, $out, $in) 34 | ); 35 | 36 | $this->shell->initialize(); 37 | $this->shell->loadTasks(); 38 | $this->shell->startup(); 39 | } 40 | 41 | public function tearDown() 42 | { 43 | parent::tearDown(); 44 | 45 | unset($this->shell); 46 | } 47 | 48 | public function testMain() 49 | { 50 | $this->assertIdentical($this->shell->main(), null, 51 | __('Update shell failed.')); 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /app/Test/Case/Controller/ContributorsControllerTest.php: -------------------------------------------------------------------------------- 1 | Contributor = ClassRegistry::init('Contributor'); 45 | } 46 | 47 | /** 48 | * tearDown method 49 | * 50 | * @return void 51 | */ 52 | public function tearDown() 53 | { 54 | unset($this->Contributor); 55 | parent::tearDown(); 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /app/Test/Case/Model/DescriptionTest.php: -------------------------------------------------------------------------------- 1 | Description = ClassRegistry::init('Description'); 45 | } 46 | 47 | /** 48 | * tearDown method 49 | * 50 | * @return void 51 | */ 52 | public function tearDown() 53 | { 54 | unset($this->Description); 55 | parent::tearDown(); 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /app/Test/Case/Model/PluginTest.php: -------------------------------------------------------------------------------- 1 | Plugin = ClassRegistry::init('Plugin'); 38 | } 39 | 40 | /** 41 | * tearDown method 42 | * 43 | * @return void 44 | */ 45 | public function tearDown() 46 | { 47 | unset($this->Plugin); 48 | parent::tearDown(); 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /app/Test/Case/Model/PluginsStateTest.php: -------------------------------------------------------------------------------- 1 | PluginsState = ClassRegistry::init('PluginsState'); 44 | } 45 | 46 | /** 47 | * tearDown method 48 | * 49 | * @return void 50 | */ 51 | public function tearDown() 52 | { 53 | unset($this->PluginsState); 54 | parent::tearDown(); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /app/Test/Case/Model/SessionTest.php: -------------------------------------------------------------------------------- 1 | Session = ClassRegistry::init('Session'); 38 | } 39 | 40 | /** 41 | * tearDown method 42 | * 43 | * @return void 44 | */ 45 | public function tearDown() 46 | { 47 | unset($this->Session); 48 | parent::tearDown(); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /app/Test/Case/Model/SettingTest.php: -------------------------------------------------------------------------------- 1 | Setting = ClassRegistry::init('Setting'); 38 | } 39 | 40 | /** 41 | * tearDown method 42 | * 43 | * @return void 44 | */ 45 | public function tearDown() 46 | { 47 | unset($this->Setting); 48 | parent::tearDown(); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /app/Test/Case/Model/StatTest.php: -------------------------------------------------------------------------------- 1 | Stat = ClassRegistry::init('Stat'); 38 | } 39 | 40 | /** 41 | * tearDown method 42 | * 43 | * @return void 44 | */ 45 | public function tearDown() 46 | { 47 | unset($this->Stat); 48 | parent::tearDown(); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /app/Test/Case/Model/StateTest.php: -------------------------------------------------------------------------------- 1 | State = ClassRegistry::init('State'); 39 | } 40 | 41 | /** 42 | * tearDown method 43 | * 44 | * @return void 45 | */ 46 | public function tearDown() 47 | { 48 | unset($this->State); 49 | parent::tearDown(); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /app/Test/Case/Model/TagTest.php: -------------------------------------------------------------------------------- 1 | Tag = ClassRegistry::init('Tag'); 45 | } 46 | 47 | /** 48 | * tearDown method 49 | * 50 | * @return void 51 | */ 52 | public function tearDown() { 53 | unset($this->Tag); 54 | parent::tearDown(); 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /app/Test/Fixture/ContributorFixture.php: -------------------------------------------------------------------------------- 1 | array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'primary'), 25 | 'name' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 64, 'key' => 'unique', 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), 26 | 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), 27 | 'indexes' => array( 28 | 'PRIMARY' => array('column' => 'id', 'unique' => 1), 29 | 'name' => array('column' => 'name', 'unique' => 1) 30 | ), 31 | 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') 32 | ); 33 | 34 | /** 35 | * Records 36 | * 37 | * @var array 38 | */ 39 | public $records = array( 40 | array( 41 | 'id' => 1, 42 | 'name' => 'Lorem ipsum dolor sit amet', 43 | 'created' => '2013-03-11 22:34:45' 44 | ), 45 | array( 46 | 'id' => 2, 47 | 'name' => 'Lorem ipsum dolor sit amet', 48 | 'created' => '2013-03-11 22:34:45' 49 | ), 50 | array( 51 | 'id' => 3, 52 | 'name' => 'Lorem ipsum dolor sit amet', 53 | 'created' => '2013-03-11 22:34:45' 54 | ), 55 | array( 56 | 'id' => 4, 57 | 'name' => 'Lorem ipsum dolor sit amet', 58 | 'created' => '2013-03-11 22:34:45' 59 | ), 60 | array( 61 | 'id' => 5, 62 | 'name' => 'Lorem ipsum dolor sit amet', 63 | 'created' => '2013-03-11 22:34:45' 64 | ), 65 | ); 66 | 67 | } -------------------------------------------------------------------------------- /app/Test/Fixture/DescriptionFixture.php: -------------------------------------------------------------------------------- 1 | array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'primary'), 25 | 'plugin_id' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 10, 'key' => 'unique'), 26 | 'content' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 16384, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), 27 | 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), 28 | 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), 29 | 'indexes' => array( 30 | 'PRIMARY' => array('column' => 'id', 'unique' => 1), 31 | 'plugin_id' => array('column' => 'plugin_id', 'unique' => 1) 32 | ), 33 | 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') 34 | ); 35 | 36 | /** 37 | * Records 38 | * 39 | * @var array 40 | */ 41 | public $records = array( 42 | array( 43 | 'id' => 1, 44 | 'plugin_id' => 1, 45 | 'content' => 'Lorem ipsum dolor sit amet', 46 | 'created' => '2013-03-11 19:42:42', 47 | 'modified' => '2013-03-11 19:42:42' 48 | ), 49 | ); 50 | 51 | } -------------------------------------------------------------------------------- /app/Test/Fixture/PluginFixture.php: -------------------------------------------------------------------------------- 1 | array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'primary'), 25 | 'slug' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'latin1_swedish_ci', 'charset' => 'latin1'), 26 | 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), 27 | 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), 28 | 'indexes' => array( 29 | 'PRIMARY' => array('column' => 'id', 'unique' => 1) 30 | ), 31 | 'tableParameters' => array('charset' => 'latin1', 'collate' => 'latin1_swedish_ci', 'engine' => 'InnoDB') 32 | ); 33 | 34 | /** 35 | * Records 36 | * 37 | * @var array 38 | */ 39 | public $records = array( 40 | array( 41 | 'id' => 1, 42 | 'slug' => 'Lorem ipsum dolor sit amet', 43 | 'created' => '2013-01-31 04:07:38', 44 | 'modified' => '2013-01-31 04:07:38' 45 | ), 46 | ); 47 | 48 | } -------------------------------------------------------------------------------- /app/Test/Fixture/PluginsStateFixture.php: -------------------------------------------------------------------------------- 1 | array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'primary'), 25 | 'plugin_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'index'), 26 | 'state_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10), 27 | 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), 28 | 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), 29 | 'indexes' => array( 30 | 'PRIMARY' => array('column' => 'id', 'unique' => 1), 31 | 'plugin_id' => array('column' => array('plugin_id', 'state_id'), 'unique' => 1) 32 | ), 33 | 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') 34 | ); 35 | 36 | /** 37 | * Records 38 | * 39 | * @var array 40 | */ 41 | public $records = array( 42 | array( 43 | 'id' => 1, 44 | 'plugin_id' => 1, 45 | 'state_id' => 1, 46 | 'created' => '2013-02-25 20:21:16', 47 | 'modified' => '2013-02-25 20:21:16' 48 | ), 49 | ); 50 | 51 | } -------------------------------------------------------------------------------- /app/Test/Fixture/SessionFixture.php: -------------------------------------------------------------------------------- 1 | array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'primary', 'collate' => 'latin1_swedish_ci', 'charset' => 'latin1'), 25 | 'data' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'latin1_swedish_ci', 'charset' => 'latin1'), 26 | 'expires' => array('type' => 'integer', 'null' => true, 'default' => null), 27 | 'indexes' => array( 28 | 'PRIMARY' => array('column' => 'id', 'unique' => 1) 29 | ), 30 | 'tableParameters' => array('charset' => 'latin1', 'collate' => 'latin1_swedish_ci', 'engine' => 'InnoDB') 31 | ); 32 | 33 | /** 34 | * Records 35 | * 36 | * @var array 37 | */ 38 | public $records = array( 39 | array( 40 | 'id' => 'Lorem ipsum dolor sit amet', 41 | 'data' => 'Lorem ipsum dolor sit amet, aliquet feugiat. Convallis morbi fringilla gravida, phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla vestibulum massa neque ut et, id hendrerit sit, feugiat in taciti enim proin nibh, tempor dignissim, rhoncus duis vestibulum nunc mattis convallis.', 42 | 'expires' => 1 43 | ), 44 | ); 45 | 46 | } -------------------------------------------------------------------------------- /app/Test/Fixture/SettingFixture.php: -------------------------------------------------------------------------------- 1 | array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary'), 25 | 'key' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'unique', 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), 26 | 'value' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 1024, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), 27 | 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), 28 | 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), 29 | 'indexes' => array( 30 | 'PRIMARY' => array('column' => 'id', 'unique' => 1), 31 | 'key' => array('column' => 'key', 'unique' => 1) 32 | ), 33 | 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') 34 | ); 35 | 36 | /** 37 | * Records 38 | * 39 | * @var array 40 | */ 41 | public $records = array( 42 | array( 43 | 'id' => 1, 44 | 'key' => 'Lorem ipsum dolor sit amet', 45 | 'value' => 'Lorem ipsum dolor sit amet', 46 | 'created' => '2013-02-06 22:50:41', 47 | 'modified' => '2013-02-06 22:50:41' 48 | ), 49 | ); 50 | 51 | } 52 | -------------------------------------------------------------------------------- /app/Test/Fixture/StatFixture.php: -------------------------------------------------------------------------------- 1 | array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary'), 25 | 'total' => array('type' => 'integer', 'null' => true, 'default' => null), 26 | 'cloned' => array('type' => 'integer', 'null' => true, 'default' => null), 27 | 'cloning' => array('type' => 'integer', 'null' => true, 'default' => null), 28 | 'refreshing' => array('type' => 'integer', 'null' => true, 'default' => null), 29 | 'removed' => array('type' => 'integer', 'null' => true, 'default' => null), 30 | 'updating' => array('type' => 'integer', 'null' => true, 'default' => null), 31 | 'created' => array('type' => 'datetime', 'null' => true, 'default' => null, 'key' => 'index'), 32 | 'indexes' => array( 33 | 'PRIMARY' => array('column' => 'id', 'unique' => 1), 34 | 'created' => array('column' => 'created', 'unique' => 0) 35 | ), 36 | 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') 37 | ); 38 | 39 | /** 40 | * Records 41 | * 42 | * @var array 43 | */ 44 | public $records = array( 45 | array( 46 | 'id' => 1, 47 | 'total' => 1, 48 | 'cloned' => 1, 49 | 'cloning' => 1, 50 | 'refreshing' => 1, 51 | 'removed' => 1, 52 | 'updating' => 1, 53 | 'created' => '2013-04-05 01:43:52' 54 | ), 55 | ); 56 | 57 | } 58 | -------------------------------------------------------------------------------- /app/Test/Fixture/StateFixture.php: -------------------------------------------------------------------------------- 1 | array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'primary'), 25 | 'name' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 32, 'key' => 'unique', 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), 26 | 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), 27 | 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), 28 | 'indexes' => array( 29 | 'PRIMARY' => array('column' => 'id', 'unique' => 1), 30 | 'name' => array('column' => 'name', 'unique' => 1) 31 | ), 32 | 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') 33 | ); 34 | 35 | /** 36 | * Records 37 | * 38 | * @var array 39 | */ 40 | public $records = array( 41 | array( 42 | 'id' => 1, 43 | 'name' => 'Lorem ipsum dolor sit amet', 44 | 'created' => '2013-02-10 01:03:56', 45 | 'modified' => '2013-02-10 01:03:56' 46 | ), 47 | ); 48 | 49 | } -------------------------------------------------------------------------------- /app/Test/Fixture/TagFixture.php: -------------------------------------------------------------------------------- 1 | array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'primary'), 25 | 'name' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 64, 'key' => 'unique', 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), 26 | 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), 27 | 'indexes' => array( 28 | 'PRIMARY' => array('column' => 'id', 'unique' => 1), 29 | 'name' => array('column' => 'name', 'unique' => 1) 30 | ), 31 | 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') 32 | ); 33 | 34 | /** 35 | * Records 36 | * 37 | * @var array 38 | */ 39 | public $records = array( 40 | array( 41 | 'id' => 1, 42 | 'name' => 'Lorem ipsum dolor sit amet', 43 | 'created' => '2013-03-11 22:34:53' 44 | ), 45 | array( 46 | 'id' => 2, 47 | 'name' => 'Lorem ipsum dolor sit amet', 48 | 'created' => '2013-03-11 22:34:53' 49 | ), 50 | array( 51 | 'id' => 3, 52 | 'name' => 'Lorem ipsum dolor sit amet', 53 | 'created' => '2013-03-11 22:34:53' 54 | ), 55 | array( 56 | 'id' => 4, 57 | 'name' => 'Lorem ipsum dolor sit amet', 58 | 'created' => '2013-03-11 22:34:53' 59 | ), 60 | array( 61 | 'id' => 5, 62 | 'name' => 'Lorem ipsum dolor sit amet', 63 | 'created' => '2013-03-11 22:34:53' 64 | ), 65 | ); 66 | 67 | } -------------------------------------------------------------------------------- /app/TestSuite/Reporter/HtmlReporter.php: -------------------------------------------------------------------------------- 1 | params['baseDir']; 30 | include APP . 'TestSuite' . DS . 'templates' . DS . 'header.php'; 31 | } 32 | 33 | /** 34 | * Renders the menu on the top of the test suite interface. 35 | * 36 | * @return void 37 | */ 38 | public function paintTestMenu() 39 | { 40 | /** @noinspection PhpUnusedLocalVariableInspection */ 41 | $cases = $this->baseUrl() . '?show=cases'; 42 | $plugins = App::objects('plugin', null, false); 43 | sort($plugins); 44 | include APP . 'TestSuite' . DS . 'templates' . DS . 'menu.php'; 45 | } 46 | 47 | /** 48 | * Renders the summary of test passes and failures. 49 | * 50 | * @param PHPUnit_Framework_TestResult $result Result object 51 | * 52 | * @return void 53 | */ 54 | public function paintFooter($result) 55 | { 56 | ob_end_flush(); 57 | echo ''; 58 | 59 | if($result->failureCount() + $result->errorCount() > 0) 60 | echo '
'; 61 | else 62 | echo '
'; 63 | 64 | echo ($result->count() - $result->skippedCount()) . ' of '; 65 | echo $result->count() . ' test methods complete: '; 66 | echo count($result->passed()) . ' passes, '; 67 | echo $result->failureCount() . ' fails, '; 68 | echo $this->numAssertions . ' assertions and '; 69 | echo $result->errorCount() . ' exceptions.'; 70 | 71 | echo '
'; 72 | 73 | echo '

Time: ' . __('%0.5f seconds', $result->time()) . '

'; 74 | echo '

Peak Memory: ' . number_format(memory_get_peak_usage()) . ' bytes

'; 75 | $this->_paintLinks(); 76 | 77 | if (isset($this->params['codeCoverage']) && $this->params['codeCoverage']) { 78 | $coverage = $result->getCodeCoverage(); 79 | if (method_exists($coverage, 'getSummary')) { 80 | $report = $coverage->getSummary(); 81 | $this->paintCoverage($report); 82 | } 83 | if (method_exists($coverage, 'getData')) { 84 | $report = $coverage->getData(); 85 | $this->paintCoverage($report); 86 | } 87 | } 88 | $this->paintDocumentEnd(); 89 | } 90 | 91 | /** 92 | * Renders the HTML footer. 93 | * 94 | * @return void 95 | */ 96 | public function paintDocumentEnd() 97 | { 98 | /** @noinspection PhpUnusedLocalVariableInspection */ 99 | $baseDir = $this->params['baseDir']; 100 | include APP . 'TestSuite' . DS . 'templates' . DS . 'footer.php'; 101 | if (ob_get_length()) { 102 | ob_end_flush(); 103 | } 104 | } 105 | 106 | } -------------------------------------------------------------------------------- /app/TestSuite/templates/footer.php: -------------------------------------------------------------------------------- 1 | 10 | 11 | element('sql_dump'); 16 | ?> 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 |
25 |
    26 |
  • CakePHP
  • 27 |
  • PHPUnit
  • 28 |
29 |
30 |
31 |
32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/TestSuite/templates/header.php: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | 14 | 15 | Test Suite - WordPress Plugins GitHub Mirror 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/TestSuite/templates/menu.php: -------------------------------------------------------------------------------- 1 | 10 |
11 | 29 |
30 | 31 |
32 |
33 | -------------------------------------------------------------------------------- /app/View/Common/sidebar.ctp: -------------------------------------------------------------------------------- 1 | 12 | 13 |
14 |
15 | fetch('content'); ?> 16 |
17 |
18 | 21 |
22 |
-------------------------------------------------------------------------------- /app/View/Elements/alert-error.ctp: -------------------------------------------------------------------------------- 1 | 'alert', 12 | 'icon' => 'exclamation-circle', 13 | 'title' => 'Error!', 14 | ); 15 | 16 | if(isset($class)) { $data['class'] .= " $class"; } 17 | if(isset($close)) { $data['close'] = $close; } 18 | if(isset($icon)) { $data['icon'] = $icon; } 19 | if(isset($message)) { $data['message'] = $message; } 20 | if(isset($title)) { $data['title'] = $title; } 21 | 22 | echo $this->element('alert', $data); -------------------------------------------------------------------------------- /app/View/Elements/alert-success.ctp: -------------------------------------------------------------------------------- 1 | 'success', 12 | 'icon' => 'check', 13 | 'title' => 'Success!', 14 | ); 15 | 16 | if(isset($class)) { $data['class'] .= " $class"; } 17 | if(isset($close)) { $data['close'] = $close; } 18 | if(isset($icon)) { $data['icon'] = $icon; } 19 | if(isset($message)) { $data['message'] = $message; } 20 | if(isset($title)) { $data['title'] = $title; } 21 | 22 | echo $this->element('alert', $data); -------------------------------------------------------------------------------- /app/View/Elements/alert-warning.ctp: -------------------------------------------------------------------------------- 1 | 'warning', 12 | 'icon' => 'exclamation-triangle', 13 | 'title' => 'Warning!', 14 | ); 15 | 16 | if(isset($class)) { $data['class'] .= " $class"; } 17 | if(isset($close)) { $data['close'] = $close; } 18 | if(isset($icon)) { $data['icon'] = $icon; } 19 | if(isset($message)) { $data['message'] = $message; } 20 | if(isset($title)) { $data['title'] = $title; } 21 | 22 | echo $this->element('alert', $data); -------------------------------------------------------------------------------- /app/View/Elements/alert.ctp: -------------------------------------------------------------------------------- 1 | 15 |
16 | × 17 | Html->icon($icon . ' 4x pull-left'); } ?> 18 |

19 | 20 |
-------------------------------------------------------------------------------- /app/View/Elements/footer.ctp: -------------------------------------------------------------------------------- 1 | 10 |
11 |
12 |
13 |
14 |

15 | Html->link('PluginMirror', 17 | 'https://github.com/bluehost/pluginmirror', 18 | array('target' => '_blank'))); 19 | ?> 20 |

21 |
22 |
23 |
-------------------------------------------------------------------------------- /app/View/Elements/head.ctp: -------------------------------------------------------------------------------- 1 | 12 | 13 | Html->charset(); 15 | 16 | if(isset($title_for_layout)) { 17 | echo $this->Html->tag('title', $title_for_layout .' - '. Configure::read('App.name')); 18 | } else { 19 | echo $this->Html->tag('title', Configure::read('App.name')); 20 | } 21 | 22 | echo $this->Html->meta( 23 | array('name' => 'viewport', 24 | 'content' => 'width=device-width, initial-scale=1.0')); 25 | echo $this->Html->meta('icon'); 26 | echo $this->fetch('meta'); 27 | 28 | echo $this->Html->css('normalize.min'); 29 | echo $this->Html->css('foundation.min'); 30 | echo $this->Html->css('font-awesome.min'); 31 | echo $this->Html->css('application'); 32 | echo $this->fetch('css'); 33 | 34 | echo $this->Html->script('modernizr.min'); 35 | ?> 36 | -------------------------------------------------------------------------------- /app/View/Elements/header.ctp: -------------------------------------------------------------------------------- 1 | 10 |

-------------------------------------------------------------------------------- /app/View/Elements/nav.ctp: -------------------------------------------------------------------------------- 1 | 10 |
    11 |
  • 12 |

    Html->link(Configure::read('App.name'), array('controller' => 'pages', 'action' => 'display', 'home')); ?>

    13 |
  • 14 | 15 |
16 |
17 |
    18 |
  • 19 |
  • Html->link(__('Plugins'), array('controller' => 'plugins', 'action' => 'index')); ?>
  • 20 |
  • 21 |
  • Html->link(__('Status'), array('controller' => 'stats', 'action' => 'index')); ?>
  • 22 |
23 |
    24 |
  • 25 |
    26 |
    27 |
    28 | 29 | 30 |
    31 |
    32 |
    33 |
  • 34 |
35 |
-------------------------------------------------------------------------------- /app/View/Elements/scripts.ctp: -------------------------------------------------------------------------------- 1 | Html->script('//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js'); 11 | echo $this->Html->script('foundation.min'); 12 | 13 | $this->Html->scriptBlock("$(document).foundation();", array('inline' => false)); 14 | 15 | // Force plugin description links to open in a new tab/window. 16 | $this->Html->scriptBlock(" 17 | $(document).ready(function() { 18 | $('.external-links a').attr('target', '_blank'); 19 | }); 20 | ", array('inline' => false)); 21 | 22 | echo $this->fetch('script'); -------------------------------------------------------------------------------- /app/View/Elements/sql_dump.ctp: -------------------------------------------------------------------------------- 1 | getLog(); 24 | } 25 | } 26 | 27 | if($noLogs || isset($_forced_from_dbo_)) { 28 | 29 | if(!empty($logs)) 30 | echo "

Database Query Statistics

\n"; 31 | 32 | foreach ($logs as $source => $logInfo) { 33 | $text = $logInfo['count'] > 1 ? 'queries' : 'query'; 34 | printf( 35 | '', 36 | preg_replace('/[^A-Za-z0-9_]/', '_', uniqid(time(), true)) 37 | ); 38 | printf('', $source, $logInfo['count'], $text, $logInfo['time']); 39 | 40 | echo "\n"; 41 | echo "\n"; 42 | 43 | foreach ($logInfo['log'] as $k => $i) { 44 | $i += array('error' => ''); 45 | if (!empty($i['params']) && is_array($i['params'])) { 46 | $bindParam = $bindType = null; 47 | if (preg_match('/.+ :.+/', $i['query'])) { 48 | $bindType = true; 49 | } 50 | foreach ($i['params'] as $bindKey => $bindVal) { 51 | if ($bindType === true) { 52 | $bindParam .= h($bindKey) ." => " . h($bindVal) . ", "; 53 | } else { 54 | $bindParam .= h($bindVal) . ", "; 55 | } 56 | } 57 | $i['query'] .= " , params[ " . rtrim($bindParam, ', ') . " ]"; 58 | } 59 | echo ""; 60 | echo ""; 61 | echo ""; 62 | echo ""; 63 | echo ""; 64 | echo ""; 65 | echo ""; 66 | echo "\n"; 67 | } 68 | 69 | echo "
(%s) %s %s took %s ms
#QueryErrorAffectedRowsTime
" . ($k + 1) . "" . h($i['query']) . "{$i['error']}{$i['affected']}{$i['numRows']}{$i['took']}
"; 70 | } 71 | 72 | } else { 73 | 74 | echo '

Encountered unexpected $logs cannot generate SQL log

'; 75 | 76 | } 77 | -------------------------------------------------------------------------------- /app/View/Emails/html/default.ctp: -------------------------------------------------------------------------------- 1 | 19 | ' . $line . '

'; 24 | endforeach; 25 | ?> -------------------------------------------------------------------------------- /app/View/Emails/text/default.ctp: -------------------------------------------------------------------------------- 1 | 19 | -------------------------------------------------------------------------------- /app/View/Errors/error400.ctp: -------------------------------------------------------------------------------- 1 | 10 |

11 | element('alert-error', array( 13 | 'message' => __('The requested address %s was not found on this server.', 14 | "'{$url}'"), 15 | 'close' => false, 16 | )); 17 | if(Configure::read('debug') > 0) 18 | { 19 | echo $this->element('exception_stack_trace'); 20 | } 21 | -------------------------------------------------------------------------------- /app/View/Errors/error500.ctp: -------------------------------------------------------------------------------- 1 | 10 |

11 | element('alert-error', array( 13 | 'message' => __('An internal server error has occurred, and has been logged. ') . 14 | __('Sorry for the interruption, we will try to fix this quickly.'), 15 | 'close' => false, 16 | )); 17 | if(Configure::read('debug') > 0) 18 | { 19 | echo $this->element('exception_stack_trace'); 20 | } 21 | -------------------------------------------------------------------------------- /app/View/Errors/fatal_error.ctp: -------------------------------------------------------------------------------- 1 | 10 |

11 | element('alert-error', array( 13 | 'message' => __('

%s

File: %s line %d

', 14 | $error->getMessage(), 15 | $error->getFile(), 16 | $error->getLine()), 17 | 'close' => false, 18 | )); 19 | if(Configure::read('debug') > 0) { // should be, but just in case... 20 | echo $this->element('exception_stack_trace'); 21 | } 22 | -------------------------------------------------------------------------------- /app/View/Errors/missing_view.ctp: -------------------------------------------------------------------------------- 1 | 10 |

11 | element('alert-error', array( 13 | 'message' => __('The view for %s was not found.
Confirm you have created the file: %s', 14 | '' . Inflector::camelize($this->request->controller) . 15 | 'Controller::' . $this->request->action . '()', substr($file, strlen(ROOT) + 1)), 16 | 'close' => false, 17 | )); 18 | if(Configure::read('debug') > 0) { // should be, but just in case... 19 | echo $this->element('exception_stack_trace'); 20 | } 21 | -------------------------------------------------------------------------------- /app/View/Helper/AppHelper.php: -------------------------------------------------------------------------------- 1 | tag('i', '', array('class' => implode(' ', $class))); 40 | } 41 | 42 | /** 43 | * Custom link handler supporting "icon" option for quick links with icons. 44 | * 45 | * @param string $title 46 | * @param null $url 47 | * @param array $options 48 | * @param bool $confirmMessage 49 | * 50 | * @return string 51 | */ 52 | public function link($title, $url = null, $options = array(), $confirmMessage = false) 53 | { 54 | $default = array('icon' => null, 'escape' => true); 55 | $options = array_merge($default, (array)$options); 56 | if ($options['icon']) { 57 | if ($options['escape']) { 58 | $title = h($title); 59 | } 60 | $title = $this->icon($options['icon']) . ' ' . $title; 61 | $options['escape'] = false; 62 | unset($options['icon']); 63 | } 64 | return parent::link($title, $url, $options, $confirmMessage); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /app/View/Helper/AppPaginatorHelper.php: -------------------------------------------------------------------------------- 1 | 'pagination-centered', 29 | 'units' => array('prev', 'numbers', 'next') 30 | ); 31 | 32 | $options += $default; 33 | 34 | $units = $options['units']; 35 | unset($options['units']); 36 | $class = $options['div']; 37 | unset($options['div']); 38 | 39 | $out = array(); 40 | foreach ($units as $unit) { 41 | if ($unit === 'numbers') { 42 | $out[] = $this->{$unit}($options); 43 | } else { 44 | $out[] = $this->{$unit}(null, $options); 45 | } 46 | } 47 | 48 | $list = $this->Html->tag('ul', implode("\n", $out), 49 | array('class' => 'pagination')); 50 | $counter = $this->Html->tag('p', $this->counter()); 51 | 52 | return $this->Html->div($class, $list . $counter); 53 | } 54 | 55 | /** 56 | * @param null $title 57 | * @param array $options 58 | * @param null $disabledTitle 59 | * @param array $disabledOptions 60 | * @return null|string 61 | */ 62 | public function prev($title = null, $options = array(), $disabledTitle = null, $disabledOptions = array()) 63 | { 64 | $default = array( 65 | 'title' => '«', 66 | 'tag' => 'li', 67 | 'model' => $this->defaultModel(), 68 | 'class' => 'arrow', 69 | 'disabled' => 'arrow unavailable', 70 | ); 71 | $options += $default; 72 | if (empty($title)) { 73 | $title = $options['title']; 74 | } 75 | unset($options['title']); 76 | 77 | $disabled = $options['disabled']; 78 | $params = (array)$this->params($options['model']); 79 | if ($disabled === 'hide' && !$params['prevPage']) { 80 | return null; 81 | } 82 | unset($options['disabled']); 83 | 84 | return parent::prev($title, $options, $this->Html->tag('a', $title), array_merge($options, array( 85 | 'escape' => false, 86 | 'class' => $disabled, 87 | ))); 88 | } 89 | 90 | /** 91 | * @param null $title 92 | * @param array $options 93 | * @param null $disabledTitle 94 | * @param array $disabledOptions 95 | * @return null|string 96 | */ 97 | public function next($title = null, $options = array(), $disabledTitle = null, $disabledOptions = array()) 98 | { 99 | $default = array( 100 | 'title' => '»', 101 | 'tag' => 'li', 102 | 'model' => $this->defaultModel(), 103 | 'class' => 'arrow', 104 | 'disabled' => 'arrow unavailable', 105 | ); 106 | $options += $default; 107 | if (empty($title)) { 108 | $title = $options['title']; 109 | } 110 | unset($options['title']); 111 | 112 | $disabled = $options['disabled']; 113 | $params = (array)$this->params($options['model']); 114 | if ($disabled === 'hide' && !$params['nextPage']) { 115 | return null; 116 | } 117 | unset($options['disabled']); 118 | 119 | return parent::next($title, $options, $this->Html->tag('a', $title), array_merge($options, array( 120 | 'escape' => false, 121 | 'class' => $disabled, 122 | ))); 123 | } 124 | 125 | /** 126 | * @param array $options 127 | * @return mixed 128 | */ 129 | public function numbers($options = array()) 130 | { 131 | $defaults = array( 132 | 'tag' => 'li', 133 | 'before' => null, 134 | 'after' => null, 135 | 'model' => $this->defaultModel(), 136 | 'class' => null, 137 | 'modulus' => 6, 138 | 'separator' => false, 139 | 'first' => 1, 140 | 'last' => 1, 141 | 'ellipsis' => '
  • ', 142 | 'currentClass' => 'current', 143 | 'currentTag' => 'a' 144 | ); 145 | $options += $defaults; 146 | return parent::numbers($options); 147 | } 148 | 149 | /** 150 | * @param array $options 151 | * @return string 152 | */ 153 | public function counter($options = array()) 154 | { 155 | if(!isset($options['format'])) { 156 | $options['format'] = __('Page {:page} of {:pages}, showing {:current} of {:count} total.'); 157 | } 158 | 159 | return parent::counter($options); 160 | } 161 | 162 | } 163 | -------------------------------------------------------------------------------- /app/View/Helper/SettingsFormHelper.php: -------------------------------------------------------------------------------- 1 | _modelScope = false; 34 | } 35 | if ($setScope === true) { 36 | $this->_modelScope = $entity; 37 | } 38 | $parts = array_values(Hash::filter(explode('.', $entity))); 39 | if (empty($parts)) { 40 | return; 41 | } 42 | 43 | if ($parts[0] != '_Token') { 44 | $entity = $this->_modelScope . '.' . $entity; 45 | } 46 | 47 | $this->_association = null; 48 | $this->_entityPath = $entity; 49 | } 50 | 51 | /** 52 | * Returns false if given form field described by the current entity has no errors. 53 | * Otherwise it returns the validation message 54 | * 55 | * @return mixed Either false when there are no errors, or an array of error 56 | * strings. An error string could be ''. 57 | * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::tagIsInvalid 58 | */ 59 | public function tagIsInvalid() { 60 | $entity = $this->entity(); 61 | $model = array_shift($entity); 62 | $errors = array(); 63 | if (!empty($entity) && isset($this->validationErrors[$model])) { 64 | $errors = $this->validationErrors[$model]; 65 | } 66 | if (!empty($entity) && empty($errors)) { 67 | $errors = $this->_introspectModel($model, 'errors'); 68 | } 69 | if (empty($errors) || empty($errors[implode('.', $entity)])) { 70 | return false; 71 | } 72 | $errors = $errors[implode('.', $entity)]; 73 | return $errors === null ? false : $errors; 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /app/View/Layouts/Emails/html/default.ctp: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | 22 | 23 | <?php echo $title_for_layout; ?> 24 | 25 | 26 | 27 | fetch('content'); ?> 28 | 29 |

    This email was sent using the CakePHP Framework

    30 | 31 | 32 | -------------------------------------------------------------------------------- /app/View/Layouts/Emails/text/default.ctp: -------------------------------------------------------------------------------- 1 | 19 | 20 | fetch('content'); ?> 21 | 22 | This email was sent using the CakePHP Framework, http://cakephp.org. 23 | -------------------------------------------------------------------------------- /app/View/Layouts/ajax.ctp: -------------------------------------------------------------------------------- 1 | fetch('content'); -------------------------------------------------------------------------------- /app/View/Layouts/default.ctp: -------------------------------------------------------------------------------- 1 | Session->flash(); 14 | echo $this->fetch('content'); 15 | return; 16 | } 17 | 18 | ?> 19 | 20 | 21 | 22 | element('head', compact('title_for_layout')); ?> 23 | 24 |
    25 | 26 |
    27 |
    28 |
    29 | Session->flash(); ?> 30 | fetch('content'); ?> 31 |
    32 |
    33 | element('footer'); ?> 34 | element('scripts'); ?> 35 | 36 | -------------------------------------------------------------------------------- /app/View/Layouts/flash.ctp: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | element('head', compact('title_for_layout')); 15 | 16 | if (Configure::read('debug') == 0) 17 | { 18 | $this->start('meta'); 19 | echo $this->Html->meta('', "$pause;url=$url", array('http-equiv' => 'refresh')); 20 | $this->end(); 21 | } 22 | ?> 23 | 24 |
    25 | 26 |
    27 |
    28 |
    29 | Session->flash(); ?> 30 |

    31 |

    32 |
    33 |
    34 | element('footer'); ?> 35 | element('scripts'); ?> 36 | 37 | -------------------------------------------------------------------------------- /app/View/Layouts/js/default.ctp: -------------------------------------------------------------------------------- 1 | 16 | 17 | -------------------------------------------------------------------------------- /app/View/Layouts/rss/default.ctp: -------------------------------------------------------------------------------- 1 | Rss->document( 21 | $this->Rss->channel( 22 | array(), $channel, $this->fetch('content') 23 | ) 24 | ); 25 | -------------------------------------------------------------------------------- /app/View/Layouts/xml/default.ctp: -------------------------------------------------------------------------------- 1 | fetch('content'); -------------------------------------------------------------------------------- /app/View/Pages/about.ctp: -------------------------------------------------------------------------------- 1 | extend('/Common/sidebar'); 13 | 14 | $title_for_layout = __('Adding a New Guide'); 15 | $this->set('title_for_layout', $title_for_layout); 16 | 17 | ?> 18 | 19 |

    20 | 21 |

    22 | We love hearing about new ways developers, designers, and administrators are 23 | using the Plugin Mirror repositories. If you have found a new way to really 24 | take advantage of these repos, and want to let everyone else in on the fun, 25 | feel free to use the Plugin Developer Guide 26 | as a template for a new guide 27 | (you must be registered and logged into GitHub). Write up your guide, 28 | submit a pull request, and we'll be happy to work with you to get it posted 29 | on the home page. 30 |

    -------------------------------------------------------------------------------- /app/View/Pages/home.ctp: -------------------------------------------------------------------------------- 1 | extend('/Common/sidebar'); 13 | 14 | ?> 15 | 16 |
    17 |

    18 | Say hello to fully automated GitHub mirrors of every plugin in the 19 | WordPress.org plugin repository. These aren't your typical plugin Git 20 | repositories. These mirrors can be used for fast, efficient, and 21 | automated plugin updates using Composer, and don't require "sync 22 | scripts" or separate Subversion checkouts for plugin development. They 23 | also offer a way for plugin developers to make the move to Git even 24 | while others continue working on the same plugin using Subversion 25 | uninterrupted. 26 |

    27 |
    28 |
    29 |
    30 |
    31 | Html->link(__('Browse Plugins'), 33 | array('controller' => 'plugins', 'action' => 'index'), 34 | array('class' => 'button expand radius', 'icon' => 'list-alt lg fw')); 35 | ?> 36 |
    37 |
    38 | Html->link(__('Get Involved'), 40 | 'https://github.com/bluehost/pluginmirror', 41 | array('class' => 'button expand radius secondary', 'icon' => 'github lg fw')); 42 | ?> 43 |
    44 |
    45 |
    46 |
    47 |
    48 | 49 |

    Guides

    50 | 51 |
    52 |

    53 | Html->link(__('Plugin Developer Guide'), array( 54 | 'controller' => 'pages', 'action' => 'display', 'plugin-developer-guide')); ?> 55 | - The black art of using Git with a SVN repository. 56 | Published in April 2013 by Bryan Petty 57 |

    58 |
    59 | 60 |
    61 |

    62 | Html->link(__('Add New Guide'), 63 | array('controller' => 'pages', 'action' => 'display', 'add-new-guide'), 64 | array('icon' => 'plus-circle fw')); ?> 65 | - How are you using the plugin mirror? 66 | Published in November 2013 by Bryan Petty 67 |

    68 |
    69 | -------------------------------------------------------------------------------- /app/View/Pages/plugin-developer-guide.ctp: -------------------------------------------------------------------------------- 1 | extend('/Common/sidebar'); 13 | 14 | $title_for_layout = __('Plugin Developer Guide'); 15 | $this->set('title_for_layout', $title_for_layout); 16 | 17 | ?> 18 | 19 |

    20 | 21 |

    22 | These repositories are traditional git-svn mirrors. This means 23 | they can be used for making commits directly back to the WordPress.org 24 | Plugins Subversion repository. After rebasing any new commits on top of the 25 | desired branch you wish to commit to (either "master" for the SVN "trunk", 26 | or any other branch), performing a git svn dcommit will use 27 | your existing SVN credentials to push those commits up to the WordPress.org 28 | Plugins SVN repo. You will need Subversion and git-svn 29 | installed, however, you won't need a SVN checkout of your plugin or any 30 | "GitHub sync" scripts to do this. 31 |

    32 | 33 |

    Getting Started

    34 | 35 |

    36 | In order for this to work properly, you will need to tell your Git clone 37 | that there is a SVN repository this was cloned from and where it is. You can 38 | do this by running the following commands from within your Git clone, while 39 | replacing my-plugin-slug with your plugin slug: 40 |

    41 | 42 |
    git config svn-remote.svn.url https://plugins.svn.wordpress.org
     43 | git config svn-remote.svn.fetch my-plugin-slug/trunk:refs/remotes/origin/master
     44 | git config svn-remote.svn.branches my-plugin-slug/branches/*:refs/remotes/origin/*
     45 | 
    46 | 47 |

    48 | For every branch you checkout, including the "master" branch you checked out 49 | when you cloned, Git will need to update the SVN metadata it stores for 50 | working with SVN. This takes very little time to do, and can be triggered 51 | simply by running: 52 |

    53 | 54 |
    git svn info
    55 | 56 |

    57 | This should also happen automatically when you run 58 | git svn dcommit as well, but it's nice to get it out of the 59 | way first to make sure you have everything configured correctly. 60 |

    61 | 62 |

    Working Within Git

    63 | 64 |

    65 | Since we are required to continue working with SVN on WordPress.org, there 66 | are some general rules and guidelines for how you must use Git in order to 67 | stay compatible with the SVN workflow. 68 |

    69 | 70 |

    71 | First: Remember to always rebase your new commits on top of the latest head 72 | commit from the upstream mirror on GitHub before pushing commits to SVN. 73 | You can do this in two different ways. The most efficient way is to 74 | perform a remote update on the upstream mirror, and rebase your local 75 | branch on top of the upstream remote branch. However, another way you 76 | could do this is to run git svn rebase on your local 77 | branch. This grabs the latest commits directly from the WordPress.org 78 | Plugins SVN repo, which can be very time consuming, but works the same 79 | way. 80 |

    81 | 82 |

    83 | Second: Do not dcommit Git merge commits to the Subversion 84 | repository. Subversion doesn't handle merges in the same way as Git, and 85 | this will cause problems. This means you should keep your Git 86 | development history linear (i.e., no merging from other branches, just 87 | rebasing). 88 |

    89 | 90 |

    91 | Third: Do not amend, reorder, or otherwise change commits that have been 92 | commited to Subversion. This is essentially the same rule as not 93 | changing Git commits that have been pushed to public repositories. 94 | Subversion cannot handle modifying or reordering commits. 95 |

    96 | 97 |

    Branching and Tagging

    98 | 99 |

    100 | While it's possible to create branches and tags directly on the SVN server 101 | using SVN clients without checking out the code, you might still find it 102 | easier to create them directly from within your Git repository. 103 |

    104 | -------------------------------------------------------------------------------- /app/View/Plugins/index.ctp: -------------------------------------------------------------------------------- 1 | 13 |
    14 |
    15 |

    16 | 17 | 18 |
    19 |
    20 |
    21 |

    Html->link( 22 | $plugin['Plugin']['display_name'], 23 | array('action' => 'view', 'slug' => $plugin['Plugin']['slug']), 24 | array('escape' => false)); 25 | ?>

    26 | 27 |
    28 |
    29 | Html->tag('p', 31 | __('Version: %s', h($plugin['Plugin']['version']))); ?> 32 |
    33 |
    34 | Html->tag('p', 36 | __('Requires: %s', h($plugin['Plugin']['requires']))); ?> 37 |
    38 |
    39 | Html->tag('p', 41 | __('Tested up to: %s', h($plugin['Plugin']['tested']))); ?> 42 |
    43 |
    44 |
    45 |
    46 | Html->link(__('GitHub Mirror'), 49 | sprintf(Configure::read('App.plugin_github_url'), $plugin['Plugin']['slug']), 50 | array('class' => 'button expand success radius', 'icon' => 'github fw')); 51 | } else if(in_array('cloning', Hash::extract($plugin, 'PluginsState.{n}.State.name'))) { 52 | echo $this->Html->link(__('Cloning'), 'javascript:void(0);', 53 | array('class' => 'button expand radius disabled', 'icon' => 'refresh spin fw')); 54 | } else { 55 | echo $this->Html->link(__('Clone'), 56 | array('action' => 'mirror', 'slug' => $plugin['Plugin']['slug']), 57 | array('class' => 'button expand radius', 'icon' => 'refresh fw')); 58 | } 59 | if(!empty($plugin['Plugin']['wp_updated'])) { 60 | echo $this->Html->tag('p', sprintf('%s
    %s', 61 | __('Updated'), h($plugin['Plugin']['wp_updated'])), 62 | array('class' => 'text-center hide-for-small')); 63 | } 64 | ?> 65 |
    66 |
    67 |
    68 | 69 | 70 | Paginator->pagination(); ?> 71 |
    72 | 73 |
    74 | 80 |
    81 |
    -------------------------------------------------------------------------------- /app/View/Plugins/view.ctp: -------------------------------------------------------------------------------- 1 | 13 |
    14 | 34 |
    35 | Html->link(__('GitHub Mirror'), 38 | sprintf(Configure::read('App.plugin_github_url'), $plugin['Plugin']['slug']), 39 | array('class' => 'button large expand success radius', 'icon' => 'github lg fw')); 40 | } else if(in_array('cloning', Hash::extract($plugin, 'PluginsState.{n}.State.name'))) { 41 | echo $this->Html->link(__('Cloning'), 'javascript:void(0);', 42 | array('class' => 'button large expand disabled radius', 'icon' => 'refresh lg spin fw')); 43 | } else { 44 | echo $this->Html->link(__('Clone'), 45 | array('action' => 'mirror', 'slug' => $plugin['Plugin']['slug']), 46 | array('class' => 'button large expand radius', 'icon' => 'refresh lg fw')); 47 | } 48 | ?> 49 | 120 |
    121 |
    -------------------------------------------------------------------------------- /app/View/Settings/manage.ctp: -------------------------------------------------------------------------------- 1 | 10 |
    11 |
    12 |

    13 | Form->create('Setting', array('class' => 'form-horizontal')); ?> 14 |
    15 | 16 |
    17 |
    18 | Form->input('App.name', array('type' => 'text', 'label' => __('Site Name'), 19 | 'size' => 40, 'class' => 'large-4')); ?> 20 |
    21 |
    22 |
    23 |
    24 |
    25 | Form->submit(__('Save Settings'), array('div' => false, 'class' => 'radius')); ?> 26 |
    27 |
    28 | Form->end(); ?> 29 |
    30 |
    -------------------------------------------------------------------------------- /app/View/Stats/index.ctp: -------------------------------------------------------------------------------- 1 | start('css'); 15 | echo $this->Html->css('rickshaw.min'); 16 | ?> 17 | 46 | end(); 48 | 49 | $this->start('script'); 50 | echo $this->Html->script( 51 | array( 52 | '//ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js', 53 | 'd3.v2.min', 'rickshaw.min' 54 | ) 55 | ); 56 | ?> 57 | 130 | end(); 132 | 133 | unset($latest_stat['Stat']['id']); 134 | unset($latest_stat['Stat']['created']); 135 | unset($latest_stat['Stat']['created_iso8601']); 136 | $headers = array_map(array('Inflector', 'humanize'), array_keys($latest_stat['Stat'])); 137 | $values = array_map('number_format', array_values($latest_stat['Stat'])); 138 | 139 | ?> 140 |
    141 |
    142 |

    143 | 144 | 145 | Html->tableHeaders($headers); ?> 146 | 147 | 148 | Html->tableCells($values); ?> 149 | 150 |
    151 |
    152 |
    153 |
    154 |
    155 |
    156 |
    157 |
    158 |
    159 |
    160 |

    161 |
      162 |
    • Total: Number of plugins in the WordPress.org SVN repository.
    • 163 |
    • Cloned: Number of plugins cloned up to GitHub.
    • 164 |
    • Removed: Plugins not listed on WordPress.org (these can still be cloned).
    • 165 |
    • Refreshing: Plugins whose information needs to be updated from the WordPress.org Plugin API.
    • 166 |
    • Cloning: Plugins requested to be cloned that have not been processed yet.
    • 167 |
    • Updating: Number of cloned plugins with changes in SVN that still need to be pushed up to GitHub.
    • 168 |
    169 |
    170 |
    -------------------------------------------------------------------------------- /app/View/Stats/json/index.ctp: -------------------------------------------------------------------------------- 1 | 2 | RewriteEngine On 3 | RewriteCond %{REQUEST_FILENAME} !-d 4 | RewriteCond %{REQUEST_FILENAME} !-f 5 | RewriteRule ^(.*)$ index.php [QSA,L] 6 | 7 | -------------------------------------------------------------------------------- /app/webroot/css/application.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Application-specific styles. 3 | * 4 | * @copyright Copyright 2013 Bluehost (http://www.bluehost.com/) 5 | * @package app.webroot.css 6 | * @license GNU General Public License (http://www.gnu.org/licenses/gpl-2.0.txt) 7 | */ 8 | 9 | ul, ol, dl { 10 | margin-left: 0.50em; 11 | list-style-position: inside; 12 | } 13 | 14 | /* Font Awesome: add "icon" prefix to pull-* classes. */ 15 | .fa-pull-right { 16 | float: right; 17 | margin-left: .3em; 18 | } 19 | .fa-pull-left { 20 | float: left; 21 | margin-right: .3em; 22 | } 23 | 24 | .top-bar ul { 25 | margin-left: 0; 26 | } 27 | 28 | .top-bar-section ul li>a:hover, .top-bar-section ul li>a:focus { 29 | color: #2795b6; 30 | } 31 | 32 | .panel .lead { 33 | padding: 0.5em; 34 | } 35 | 36 | blockquote.guide { 37 | padding: 0.8em 1em; 38 | background: #f2f2f2; 39 | border: 1px solid #d9d9d9; 40 | -webkit-border-radius: 4px; 41 | border-radius: 4px; 42 | } 43 | blockquote.guide p { 44 | margin: 0; 45 | } 46 | blockquote.guide cite { 47 | color: #999; 48 | } 49 | 50 | .no-bottom-padding { 51 | padding-bottom: 0.25em; 52 | } 53 | 54 | ul.sidebar-details { 55 | margin: 0 0 1.25em 0; 56 | padding: 0 0 0.5em 0; 57 | list-style-type: none; 58 | background: #eeeeee; 59 | } 60 | ul.sidebar-details li { 61 | margin: 0.0em 1em; 62 | font-size: 0.875em; 63 | } 64 | ul.sidebar-details li.header { 65 | margin: 0.5em 0; 66 | padding: 8px 16px; 67 | background: #dfdfdf; 68 | color: #999; 69 | font-size: 0.8125em; 70 | font-weight: bold; 71 | text-transform: uppercase; 72 | text-shadow: 0 1px 0 rgba(255,255,255,0.5); 73 | } 74 | 75 | /* Custom alert-box styles. */ 76 | .alert-box { 77 | line-height: 125%; 78 | } 79 | .alert-box h4 { 80 | margin-top: 0; 81 | margin-bottom: 0.3em; 82 | color: white; 83 | } 84 | .alert-box.warning { 85 | background-color: #ff6c3c; 86 | border-color: #ff4609; 87 | } 88 | 89 | legend { 90 | margin: 1em 1em 0.5em; 91 | line-height: 1; 92 | } 93 | 94 | .pagination-centered { 95 | margin: 2em 0; 96 | } 97 | .pagination-centered p { 98 | color: #555; 99 | font-size: 0.875em; 100 | } 101 | .pagination ul { 102 | margin: 0; 103 | margin-bottom: 0.6em; 104 | } 105 | .pagination li a { 106 | padding: 0.2em 0.6em; 107 | color: #555; 108 | background: #e6e6e6; 109 | } 110 | .pagination li a:hover, .pagination li a:active { 111 | color: #fff; 112 | background: #333; 113 | } 114 | .pagination li.unavailable a { 115 | color: #999; 116 | background: none; 117 | } 118 | 119 | footer { 120 | margin: 1.5em 0; 121 | text-align: center; 122 | } 123 | 124 | .clearfix { 125 | *zoom: 1; 126 | } 127 | .clearfix:before, 128 | .clearfix:after { 129 | display: table; 130 | line-height: 0; 131 | content: ""; 132 | } 133 | .clearfix:after { 134 | clear: both; 135 | } 136 | 137 | 138 | /* Preformatted Code Styles */ 139 | 140 | code, pre { 141 | padding: 0 3px 2px; 142 | font-family: Consolas, "Liberation Mono", Courier, monospace; 143 | font-weight: normal; 144 | font-size: 13px; 145 | color: #444; 146 | -webkit-border-radius: 3px; 147 | -moz-border-radius: 3px; 148 | border-radius: 3px; 149 | } 150 | code { 151 | padding: 3px 4px 0px; 152 | vertical-align: 5%; 153 | color: #444; 154 | white-space: nowrap; 155 | background-color: #f2f2f2; 156 | border: 1px solid #ccc; 157 | } 158 | pre { 159 | display: block; 160 | padding: 0.5em 0.5em 0.4em 0.5em; 161 | margin: 0.5em 0 1.25em; 162 | font-size: 13px; 163 | line-height: 20px; 164 | word-break: break-all; 165 | word-wrap: break-word; 166 | white-space: pre; 167 | white-space: pre-wrap; 168 | background-color: #f2f2f2; 169 | border: 1px solid #ccc; 170 | -webkit-border-radius: 4px; 171 | -moz-border-radius: 4px; 172 | border-radius: 4px; 173 | } 174 | pre code { 175 | padding: 0; 176 | color: inherit; 177 | white-space: pre; 178 | white-space: pre-wrap; 179 | background-color: transparent; 180 | border: 0; 181 | } 182 | .scrollable { 183 | max-height: 340px; 184 | overflow-y: scroll; 185 | } 186 | @media print { 187 | pre { 188 | page-break-inside: avoid; 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /app/webroot/css/normalize.min.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v2.1.1 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden]{display:none}html{background:#fff;color:#000;font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{font-size:2em;margin:.67em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}button,input{line-height:normal}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0} -------------------------------------------------------------------------------- /app/webroot/css/rickshaw.min.css: -------------------------------------------------------------------------------- 1 | .rickshaw_graph .detail{pointer-events:none;position:absolute;top:0;z-index:2;background:rgba(0,0,0,.1);bottom:0;width:1px;transition:opacity .25s linear;-moz-transition:opacity .25s linear;-o-transition:opacity .25s linear;-webkit-transition:opacity .25s linear}.rickshaw_graph .detail.inactive{opacity:0}.rickshaw_graph .detail .item.active{opacity:1}.rickshaw_graph .detail .x_label{font-family:Arial,sans-serif;border-radius:3px;padding:6px;opacity:.5;border:1px solid #e0e0e0;font-size:12px;position:absolute;background:#fff;white-space:nowrap}.rickshaw_graph .detail .item{position:absolute;z-index:2;border-radius:3px;padding:.25em;font-size:12px;font-family:Arial,sans-serif;opacity:0;background:rgba(0,0,0,.4);color:#fff;border:1px solid rgba(0,0,0,.4);margin-left:1em;margin-top:-1em;white-space:nowrap}.rickshaw_graph .detail .item.active{opacity:1;background:rgba(0,0,0,.8)}.rickshaw_graph .detail .item:before{content:"\25c2";position:absolute;left:-.5em;color:rgba(0,0,0,.7);width:0}.rickshaw_graph .detail .dot{width:4px;height:4px;margin-left:-4px;margin-top:-3px;border-radius:5px;position:absolute;box-shadow:0 0 2px rgba(0,0,0,.6);background:#fff;border-width:2px;border-style:solid;display:none;background-clip:padding-box}.rickshaw_graph .detail .dot.active{display:block}.rickshaw_graph{position:relative}.rickshaw_graph svg{display:block;overflow:hidden}.rickshaw_graph .x_tick{position:absolute;top:0;bottom:0;width:0;border-left:1px dotted rgba(0,0,0,.2);pointer-events:none}.rickshaw_graph .x_tick .title{position:absolute;font-size:12px;font-family:Arial,sans-serif;opacity:.5;white-space:nowrap;margin-left:3px;bottom:1px}.rickshaw_annotation_timeline{height:1px;border-top:1px solid #e0e0e0;margin-top:10px;position:relative}.rickshaw_annotation_timeline .annotation{position:absolute;height:6px;width:6px;margin-left:-2px;top:-3px;border-radius:5px;background-color:rgba(0,0,0,.25)}.rickshaw_graph .annotation_line{position:absolute;top:0;bottom:-6px;width:0;border-left:2px solid rgba(0,0,0,.3);display:none}.rickshaw_graph .annotation_line.active{display:block}.rickshaw_graph .annotation_range{background:rgba(0,0,0,.1);display:none;position:absolute;top:0;bottom:-6px;z-index:-10}.rickshaw_graph .annotation_range.active{display:block}.rickshaw_graph .annotation_range.active.offscreen{display:none}.rickshaw_annotation_timeline .annotation .content{background:#fff;color:#000;opacity:.9;padding:5px 5px;box-shadow:0 0 2px rgba(0,0,0,.8);border-radius:3px;position:relative;z-index:20;font-size:12px;padding:6px 8px 8px;top:18px;left:-11px;width:160px;display:none;cursor:pointer}.rickshaw_annotation_timeline .annotation .content:before{content:"\25b2";position:absolute;top:-11px;color:#fff;text-shadow:0 -1px 1px rgba(0,0,0,.8)}.rickshaw_annotation_timeline .annotation.active,.rickshaw_annotation_timeline .annotation:hover{background-color:rgba(0,0,0,.8);cursor:none}.rickshaw_annotation_timeline .annotation .content:hover{z-index:50}.rickshaw_annotation_timeline .annotation.active .content{display:block}.rickshaw_annotation_timeline .annotation:hover .content{display:block;z-index:50}.rickshaw_graph .y_axis,.rickshaw_graph .x_axis_d3{fill:none}.rickshaw_graph .y_ticks .tick,.rickshaw_graph .x_ticks_d3 .tick{stroke:rgba(0,0,0,.16);stroke-width:2px;shape-rendering:crisp-edges;pointer-events:none}.rickshaw_graph .y_grid .tick,.rickshaw_graph .x_grid_d3 .tick{z-index:-1;stroke:rgba(0,0,0,.20);stroke-width:1px;stroke-dasharray:1 1}.rickshaw_graph .y_grid path,.rickshaw_graph .x_grid_d3 path{fill:none;stroke:none}.rickshaw_graph .y_ticks path,.rickshaw_graph .x_ticks_d3 path{fill:none;stroke:#808080}.rickshaw_graph .y_ticks text,.rickshaw_graph .x_ticks_d3 text{opacity:.5;font-size:12px;pointer-events:none}.rickshaw_graph .x_tick.glow .title,.rickshaw_graph .y_ticks.glow text{fill:black;color:#000;text-shadow:-1px 1px 0 rgba(255,255,255,.1),1px -1px 0 rgba(255,255,255,.1),1px 1px 0 rgba(255,255,255,.1),0px 1px 0 rgba(255,255,255,.1),0px -1px 0 rgba(255,255,255,.1),1px 0 0 rgba(255,255,255,.1),-1px 0 0 rgba(255,255,255,.1),-1px -1px 0 rgba(255,255,255,.1)}.rickshaw_graph .x_tick.inverse .title,.rickshaw_graph .y_ticks.inverse text{fill:white;color:#fff;text-shadow:-1px 1px 0 rgba(0,0,0,.8),1px -1px 0 rgba(0,0,0,.8),1px 1px 0 rgba(0,0,0,.8),0px 1px 0 rgba(0,0,0,.8),0px -1px 0 rgba(0,0,0,.8),1px 0 0 rgba(0,0,0,.8),-1px 0 0 rgba(0,0,0,.8),-1px -1px 0 rgba(0,0,0,.8)}.rickshaw_legend{font-family:Arial;font-size:12px;color:#fff;background:#404040;display:inline-block;padding:12px 5px;border-radius:2px;position:relative}.rickshaw_legend:hover{z-index:10}.rickshaw_legend .swatch{width:10px;height:10px;border:1px solid rgba(0,0,0,.2)}.rickshaw_legend .line{clear:both;line-height:140%;padding-right:15px}.rickshaw_legend .line .swatch{display:inline-block;margin-right:3px;border-radius:2px}.rickshaw_legend .label{margin:0;white-space:nowrap;display:inline;font-size:inherit;background-color:transparent;color:inherit;font-weight:400;line-height:normal;padding:0;text-shadow:none}.rickshaw_legend .action:hover{opacity:.6}.rickshaw_legend .action{margin-right:.2em;font-size:10px;opacity:.2;cursor:pointer;font-size:14px}.rickshaw_legend .line.disabled{opacity:.4}.rickshaw_legend ul{list-style-type:none;margin:0;padding:0;margin:2px;cursor:pointer}.rickshaw_legend li{padding:0 0 0 2px;min-width:80px;white-space:nowrap}.rickshaw_legend li:hover{background:rgba(255,255,255,.08);border-radius:3px}.rickshaw_legend li:active{background:rgba(255,255,255,.2);border-radius:3px} -------------------------------------------------------------------------------- /app/webroot/css/testsuite.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Unit testing styles for the HtmlReporter. 3 | * 4 | * @copyright Copyright 2013 Bluehost (http://www.bluehost.com/) 5 | * @package app.webroot.css 6 | * @license GNU General Public License (http://www.gnu.org/licenses/gpl-2.0.txt) 7 | */ 8 | 9 | /***** Test Results *****/ 10 | 11 | ul.tests { 12 | margin: 0; 13 | font-size: 90%; 14 | } 15 | ul.tests li { 16 | list-style: none; 17 | margin: 1em 0; 18 | } 19 | /* test result header */ 20 | ul.tests li span { 21 | font-size: 110%; 22 | text-transform: uppercase; 23 | font-weight: bold; 24 | } 25 | 26 | ul.tests li.pass span, 27 | ul.tests li.skipped span { 28 | display: inline; 29 | } 30 | 31 | ul.tests li.fail span { 32 | color: red; 33 | } 34 | ul.tests li.pass span { 35 | color: green; 36 | } 37 | ul.tests li.skipped span { 38 | color: navy; 39 | } 40 | ul.tests li.error span { 41 | color : #d15d00; 42 | } 43 | 44 | ul.tests li.pass, 45 | ul.tests li.error, 46 | ul.tests li.skipped, 47 | ul.tests li.fail { 48 | background: #fff2f2; 49 | border: 1px solid red; 50 | padding: 1em; 51 | -webkit-border-radius: 4px; 52 | border-radius: 4px; 53 | } 54 | ul.tests li.pass { 55 | background: #f2fff2; 56 | border-color: green; 57 | } 58 | ul.tests li.skipped { 59 | background: #edf1ff; 60 | border-color: navy; 61 | } 62 | ul.tests li.error { 63 | background: #ffffe5; 64 | border-color: #df6300; 65 | } 66 | 67 | ul.tests li div { 68 | margin: 1em 0 0; 69 | } 70 | 71 | /***** Coverage Reports *****/ 72 | 73 | .coverage-toggle { 74 | float: right; 75 | margin-top: 10px; 76 | font-size: 12px; 77 | } 78 | 79 | div.code-coverage-results div { 80 | color: #555; 81 | } 82 | div.code-coverage-results div:hover { 83 | background: rgb(225, 225, 225); 84 | } 85 | 86 | div.code-coverage-results div.covered { 87 | background: rgba(65, 187, 25, 0.30); 88 | } 89 | div.code-coverage-results div.uncovered { 90 | background: rgba(245, 15, 67, 0.30); 91 | } 92 | div.code-coverage-results div.ignored { 93 | color: #999; 94 | } 95 | 96 | div.code-coverage-results div.covered:hover { 97 | background: rgba(65, 187, 25, 0.50); 98 | } 99 | div.code-coverage-results div.uncovered:hover { 100 | background: rgba(245, 15, 67, 0.50); 101 | } 102 | 103 | div.code-coverage-results span.line-num { 104 | display: block; 105 | float: left; 106 | width: 36px; 107 | text-align: right; 108 | margin-right: 8px; 109 | } 110 | 111 | /***** Test Suite Footer *****/ 112 | 113 | .phpunit-version { 114 | margin: 1.5em; 115 | text-align: center; 116 | } 117 | 118 | td.sql-query { 119 | font-family: Monaco, Menlo, Consolas, "Courier New", monospace; 120 | line-height: 1.4; 121 | padding: 7px 5px 4px 5px; 122 | } -------------------------------------------------------------------------------- /app/webroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluehost/pluginmirror/40014aee6e110b0dce29c62dd3d1623de9d46336/app/webroot/favicon.ico -------------------------------------------------------------------------------- /app/webroot/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluehost/pluginmirror/40014aee6e110b0dce29c62dd3d1623de9d46336/app/webroot/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /app/webroot/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluehost/pluginmirror/40014aee6e110b0dce29c62dd3d1623de9d46336/app/webroot/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /app/webroot/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluehost/pluginmirror/40014aee6e110b0dce29c62dd3d1623de9d46336/app/webroot/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /app/webroot/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluehost/pluginmirror/40014aee6e110b0dce29c62dd3d1623de9d46336/app/webroot/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /app/webroot/index.php: -------------------------------------------------------------------------------- 1 | dispatch( 95 | new CakeRequest(), 96 | new CakeResponse(array('charset' => Configure::read('App.encoding'))) 97 | ); 98 | -------------------------------------------------------------------------------- /app/webroot/test.php: -------------------------------------------------------------------------------- 1 | 8 | * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) 9 | * 10 | * Licensed under The MIT License 11 | * Redistributions of files must retain the above copyright notice 12 | * 13 | * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org) 14 | * @link http://book.cakephp.org/2.0/en/development/testing.html 15 | * @package app.webroot 16 | * @since CakePHP(tm) v 1.2.0.4433 17 | * @license MIT License (http://www.opensource.org/licenses/mit-license.php) 18 | */ 19 | set_time_limit(0); 20 | ini_set('display_errors', 1); 21 | /** 22 | * Use the DS to separate the directories in other defines 23 | */ 24 | if (!defined('DS')) { 25 | define('DS', DIRECTORY_SEPARATOR); 26 | } 27 | 28 | /** 29 | * These defines should only be edited if you have cake installed in 30 | * a directory layout other than the way it is distributed. 31 | * When using custom settings be sure to use the DS and do not add a trailing DS. 32 | */ 33 | 34 | /** 35 | * The full path to the directory which holds "app", WITHOUT a trailing DS. 36 | * 37 | */ 38 | if (!defined('ROOT')) { 39 | define('ROOT', dirname(dirname(dirname(__FILE__)))); 40 | } 41 | 42 | /** 43 | * The actual directory name for the "app". 44 | * 45 | */ 46 | if (!defined('APP_DIR')) { 47 | define('APP_DIR', basename(dirname(dirname(__FILE__)))); 48 | } 49 | 50 | /** 51 | * The absolute path to the "Cake" directory, WITHOUT a trailing DS. 52 | * 53 | * For ease of development CakePHP uses PHP's include_path. If you 54 | * need to cannot modify your include_path, you can set this path. 55 | * 56 | * Leaving this constant undefined will result in it being defined in Cake/bootstrap.php 57 | */ 58 | define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . 'cakephp' . DS . 'lib'); 59 | 60 | /** 61 | * Editing below this line should not be necessary. 62 | * Change at your own risk. 63 | * 64 | */ 65 | if (!defined('WEBROOT_DIR')) { 66 | define('WEBROOT_DIR', basename(dirname(__FILE__))); 67 | } 68 | if (!defined('WWW_ROOT')) { 69 | define('WWW_ROOT', dirname(__FILE__) . DS); 70 | } 71 | 72 | if (!defined('CAKE_CORE_INCLUDE_PATH')) { 73 | if (function_exists('ini_set')) { 74 | ini_set('include_path', ROOT . DS . 'lib' . PATH_SEPARATOR . ini_get('include_path')); 75 | } 76 | if (!include 'Cake' . DS . 'bootstrap.php') { 77 | $failed = true; 78 | } 79 | } else { 80 | if (!include CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'bootstrap.php') { 81 | $failed = true; 82 | } 83 | } 84 | if (!empty($failed)) { 85 | trigger_error("CakePHP core could not be found. Check the value of CAKE_CORE_INCLUDE_PATH in APP/webroot/index.php. It should point to the directory containing your " . DS . "cake core directory and your " . DS . "vendors root directory.", E_USER_ERROR); 86 | } 87 | 88 | if (Configure::read('debug') < 1) { 89 | die(__d('cake_dev', 'Debug setting does not allow access to this url.')); 90 | } 91 | 92 | if (!defined('IN_TESTS')) { 93 | define('IN_TESTS', true); 94 | } 95 | 96 | require_once CAKE . 'TestSuite' . DS . 'CakeTestSuiteDispatcher.php'; 97 | 98 | CakeTestSuiteDispatcher::run(); 99 | -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bluehost/pluginmirror", 3 | "homepage": "http://www.pluginmirror.com/", 4 | "description": "Provides a fully automated git-svn mirror of any plugins hosted on WordPress.org.", 5 | "keywords": ["wordpress", "plugin", "github", "mirror", "git-svn"], 6 | "license": "GPL-2.0+", 7 | "authors": [ 8 | { 9 | "name": "Bryan Petty", 10 | "email": "bryan@ibaku.net" 11 | } 12 | ], 13 | "repositories": [ 14 | { 15 | "type": "package", 16 | "package": { 17 | "name": "cakephp/cakephp", 18 | "version": "dev-pluginmirror", 19 | "type": "cakephp-plugin", 20 | "description": "The Rapid Development Framework for PHP", 21 | "keywords": [ "cakephp", "framework" ], 22 | "homepage": "http://cakephp.org/", 23 | "license": "MIT", 24 | "support": { 25 | "issues": "https://cakephp.lighthouseapp.com", 26 | "source": "https://github.com/cakephp/cakephp" 27 | }, 28 | "require": { 29 | "php": ">=5.3.0", 30 | "composer/installers": "*" 31 | }, 32 | "source": { 33 | "url": "https://github.com/cakephp/cakephp.git", 34 | "type": "git", 35 | "reference": "2.3.10" 36 | } 37 | } 38 | } 39 | ], 40 | "require": { 41 | "knplabs/github-api": "*", 42 | "cakephp/cakephp": "dev-pluginmirror", 43 | "cakephp/debug_kit": "~2.2.0" 44 | }, 45 | "minimum-stability": "dev", 46 | "extra": { 47 | "installer-paths": { 48 | "app/Plugin/DebugKit": [ "cakephp/debug_kit" ], 49 | "cakephp": [ "cakephp/cakephp" ] 50 | } 51 | } 52 | } 53 | --------------------------------------------------------------------------------