├── .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' => '',
27 | 'charset' => '',
28 | 'javascriptblock' => '',
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 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |