├── .DS_Store ├── README.md ├── composer.json ├── config.php ├── core.php ├── custom-post-type-tables.php ├── lib ├── .DS_Store ├── AdminFilters.php ├── Db.php ├── QueryFilters.php ├── SettingsPage.php ├── Table.php └── Triggers.php ├── templates ├── access-denied.php └── settings.php └── vendor ├── autoload.php └── composer ├── ClassLoader.php ├── LICENSE ├── autoload_classmap.php ├── autoload_namespaces.php ├── autoload_psr4.php ├── autoload_real.php ├── autoload_static.php └── installed.json /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hannahtinkler/wordpress-custom-post-type-tables/b5d94761d902f52ef3bd6c67e3cfb2bfc8022669/.DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Custom Post Tables 2 | 3 | Wordpress stores custom post types in the default posts table (typically `wp_posts`), which is fine for most setups. In the majority of use cases, Wordpress sites are not used to store in excess of thousands of posts, and so this sort of setup doesn't place much additional load on servers. 4 | 5 | In cases where the site generates a significant amount of posts across multiple post types though, queries can become very expensive - especially where meta generating plugins such as Advanced Custom Fields are involved. Where a Wordpress site is expected to generate thousands of posts (and subsequently, many thousands of rows of post meta) queries can be sped up significantly by splitting out data into separate tables. This plugin splits out data by post type, creating additional tables for each custom post type used. A 'product' custom post type for example will have its posts stored in `product` and its meta in `product_meta`. 6 | 7 | ## Implementation 8 | Each new post and meta table is created to the same structure as the Wordpress default post and meta tables. This streamlines the storage process and means that Wordpress is capable of interpreting the data wherever it would normally use a `wp_posts` row, e.g. on the admin edit post pages, admin post listing pages, and in the `wp-posts` functions (e.g. `get_post()`). 9 | 10 | When new posts are created, a row is inserted into the `wp_posts` table (as normal) and an automatic MySQL trigger is used to copy this data into the new custom table. Queries to the wp_posts and wp_postmeta table are then rewritten to use the custom table, so that all future lookups and updates made by Wordpress and its plugins are made to the new tables. The original `wp_posts` row is retained for lookup purposes, so that we can determine the post type (and therefore custom table) when there is only a post ID available to work with. Since these lookups are (usually) only necessary in the Wordpress admin and exclusively use the primary key, they do not significantly increase the load of the request. Additionally, each ID lookup is made a maximum of once per request and the result is cached on a per-request basis. 11 | 12 | To minimise unecessary lookups when writing your own queries, specify the post type you are looking for whenever possible. This will allow the plugin to simply parse the table from the query without having to lookup the post type in the `wp_posts` table. 13 | 14 | ## Filter Hooks 15 | ### custom_post_type_tables:settings_capability: 16 | Customise what capability the settings page should be limited to. Default is 'manage_options'. 17 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hannahtinkler/custom-post-tables", 3 | "description": "Facilitates storing custom post types and meta in their own tables", 4 | "license": "MIT", 5 | "authors": [ 6 | { 7 | "name": "Hannah Tinkler", 8 | "email": "hannah.tinkler@gmail.com" 9 | } 10 | ], 11 | "config": { 12 | "optimize-autoloader": true 13 | }, 14 | "autoload": { 15 | "psr-4": { 16 | "CptTables\\": "" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /config.php: -------------------------------------------------------------------------------- 1 | array_map(function ($postType) { 7 | return esc_html($postType); 8 | }, unserialize(get_option('ctp_tables:tables_enabled')) ?: []), 9 | 'default_post_table' => env('DB_PREFIX', $wpdb->prefix) . 'posts', 10 | 'default_meta_table' => env('DB_PREFIX', $wpdb->prefix) . 'postmeta', 11 | ]; 12 | -------------------------------------------------------------------------------- /core.php: -------------------------------------------------------------------------------- 1 | db = new Db; 32 | $self->config = require(__DIR__ . '/config.php'); 33 | 34 | $self->setupAdminFilters(); 35 | $self->setupQueryFilters(); 36 | $self->setupSettingsPage(); 37 | } 38 | 39 | /** 40 | * @return void 41 | */ 42 | private function setupAdminFilters() 43 | { 44 | new AdminFilters; 45 | } 46 | 47 | /** 48 | * @return void 49 | */ 50 | private function setupQueryFilters() 51 | { 52 | new QueryFilters($this->db, $this->config); 53 | } 54 | 55 | /** 56 | * @return void 57 | */ 58 | private function setupSettingsPage() 59 | { 60 | new SettingsPage( 61 | new Table($this->db, $this->config), 62 | new Triggers($this->db, $this->config) 63 | ); 64 | } 65 | 66 | /** 67 | * @return void 68 | */ 69 | public function activate() 70 | { 71 | flush_rewrite_rules(); 72 | } 73 | 74 | /** 75 | * @return void 76 | */ 77 | public function deactivate() 78 | { 79 | flush_rewrite_rules(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /custom-post-type-tables.php: -------------------------------------------------------------------------------- 1 | isAdminPage($url)) { 24 | $url .= sprintf( 25 | '&post_type=%s', 26 | $_POST['post_type'] ?? $_GET['post_type'] ?? '' 27 | ); 28 | } 29 | 30 | return $url; 31 | } 32 | 33 | /** 34 | * Returns true is the current page is in the Wordpress admin 35 | * @param string $url 36 | * @return boolean 37 | */ 38 | public function isAdminPage(string $url) : bool 39 | { 40 | $match = get_site_url(null, 'wp-admin/', 'admin') . 'post.php?'; 41 | 42 | return strpos($url, $match) !== false; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib/Db.php: -------------------------------------------------------------------------------- 1 | db = $wpdb; 22 | } 23 | 24 | /** 25 | * Returns a single column value from the query 26 | * 27 | * @param string $query 28 | * @param any $args 29 | * @return any 30 | */ 31 | public function value(string $query, ...$args) 32 | { 33 | $results = $this->query($query, ...$args); 34 | 35 | if (empty($results[0]) || !is_array($results[0])) { 36 | return; 37 | } 38 | 39 | return array_shift($results[0]); 40 | } 41 | 42 | /** 43 | * Executes the query and returns the result from it as an array 44 | * 45 | * @param string $query 46 | * @param array $args 47 | * @return array 48 | */ 49 | public function query(string $query, ...$args) : ?array 50 | { 51 | $query = $this->formatQueryForWpdb($query); 52 | 53 | if ($args) { 54 | $results = $this->db->get_results( 55 | $this->db->prepare($query, ...$args) 56 | ); 57 | } else { 58 | $results = $this->db->get_results($query); 59 | } 60 | 61 | if ($this->db->last_error) { 62 | throw new Exception($this->db->last_error); 63 | } 64 | 65 | return json_decode(json_encode($results), true); 66 | } 67 | 68 | public function formatQueryForWpdb(string $query) : string 69 | { 70 | return str_replace(["'?'", '?'], "'%s'", $query); 71 | } 72 | 73 | /** 74 | * Escapes variables for inclusion in queries where they are not values 75 | * 76 | * @param any $var 77 | * @return any 78 | */ 79 | public function escape($var) 80 | { 81 | return esc_sql($var); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /lib/QueryFilters.php: -------------------------------------------------------------------------------- 1 | db = $db; 26 | $this->config = $config; 27 | 28 | add_filter('query', [$this, 'updateQueryTables']); 29 | } 30 | 31 | /** 32 | * If the query is for a post type that has custom tables set up, replace 33 | * the post and meta tables with the custom ones 34 | * 35 | * @param string $query 36 | * @return string 37 | */ 38 | public function updateQueryTables(string $query) : string 39 | { 40 | $table = $this->determineTable($query); 41 | 42 | if ($table && in_array($table, $this->config['post_types'])) { 43 | $table = str_replace('-', '_', $table); 44 | 45 | $query = str_replace($this->config['default_post_table'], $table, $query); 46 | $query = str_replace($this->config['default_meta_table'], $table . '_meta', $query); 47 | 48 | } 49 | 50 | return $query; 51 | } 52 | 53 | /** 54 | * Tries to parse the post type from the query. If not possible, parses the 55 | * ID and uses it to look up the post type in the wp_posts table 56 | * 57 | * @param string $query 58 | * @return string 59 | */ 60 | private function determineTable(string $query) 61 | { 62 | if ($table = $this->getPostTypeFromQuery($query)) { 63 | return $table; 64 | } 65 | 66 | if ($table = $this->lookupPostTypeInDatabase($query)) { 67 | return $table; 68 | } 69 | } 70 | 71 | /** 72 | * Tries to parse the post type from the query 73 | * 74 | * @param string $query 75 | * @return bool|string 76 | */ 77 | public function getPostTypeFromQuery(string $query) 78 | { 79 | preg_match("/`?post_type`?\s*=\s*'([a-zA-Z]*)'/", $query, $postType); 80 | 81 | if ($postType = array_pop($postType)) { 82 | return $postType; 83 | } 84 | } 85 | 86 | /** 87 | * Grabs the post id from the query and looks up the post type for this id 88 | * in the wp_posts table 89 | * 90 | * @param string $query 91 | * @return string|null 92 | */ 93 | public function lookupPostTypeInDatabase(string $query) 94 | { 95 | if ($ids = $this->getPostIdsFromQuery($query)) { 96 | return $this->getPostTypeById($ids); 97 | } 98 | } 99 | 100 | /** 101 | * Tries to parse the post id(s) from the query 102 | * 103 | * @param string $query 104 | * @return bool|string 105 | */ 106 | public function getPostIdsFromQuery(string $query) : ?string 107 | { 108 | preg_match(sprintf( 109 | "/(?:SELECT.*FROM\s(?:%s|%s)\s*WHERE.*(?:ID|post_id)+\s*IN\s\(+\s*'?([\d\s,]*)'?\)" 110 | . "|SELECT.*FROM\s(?:%s|%s)\s*WHERE.*(?:ID|post_id)+\s*=+\s*'?(\d*)'?" 111 | . "|UPDATE.*(?:%s|%s).*WHERE.*`?(?:ID|post_id)+`?\s*=+\s*'?(\d*)'?" 112 | . "|INSERT INTO.*\s`?%s`?\s\(`post_id`, `meta_key`, `meta_value`\){1,1}\s*VALUES\s*\((\d*)," 113 | . ")/", 114 | $this->config['default_post_table'], 115 | $this->config['default_meta_table'], 116 | $this->config['default_post_table'], 117 | $this->config['default_meta_table'], 118 | $this->config['default_post_table'], 119 | $this->config['default_meta_table'], 120 | $this->config['default_meta_table'] 121 | ), $query, $ids); 122 | 123 | if (!isset($ids)) { 124 | return false; 125 | } 126 | 127 | return array_pop($ids); 128 | } 129 | 130 | /** 131 | * Looks up post type in wp_posts. Caches the response, and if more than one id 132 | * is provided, also cache the result against each individual ID. 133 | * 134 | * @param string $ids 135 | * @return string 136 | */ 137 | public function getPostTypeById($ids) : ?string 138 | { 139 | $key = __METHOD__ . $ids; 140 | 141 | if (!$cached = wp_cache_get($key)) { 142 | $ids = explode(',', $ids); 143 | 144 | $cached = $this->db->value( 145 | sprintf( 146 | "SELECT post_type, ID as identifier FROM %s HAVING identifier IN (%s) LIMIT 1", 147 | $this->db->escape($this->config['default_post_table']), 148 | implode(',', array_fill(0, count($ids), '?')) 149 | ), 150 | ...$ids 151 | ); 152 | 153 | wp_cache_set($key, $cached); 154 | 155 | if (count($ids)) { 156 | foreach ((array) $ids as $id) { 157 | wp_cache_set(__METHOD__ . $id, $cached); 158 | } 159 | } 160 | } 161 | 162 | return $cached; 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /lib/SettingsPage.php: -------------------------------------------------------------------------------- 1 | table = $table; 53 | $this->triggers = $triggers; 54 | 55 | if (isset($_POST['cpt_tables:submitted'])) { 56 | $this->saveSettings(); 57 | exit; 58 | } 59 | 60 | add_filter('admin_menu', [$this, 'addSettingsPage']); 61 | } 62 | 63 | /** 64 | * Add settings page to admin settings menu 65 | */ 66 | public function addSettingsPage() 67 | { 68 | $this->capability = apply_filters($this->filter, 'manage_options'); 69 | 70 | add_options_page( 71 | $this->name, 72 | $this->name, 73 | $this->capability, 74 | $this->slug, 75 | [$this, 'showSettingsPage'] 76 | ); 77 | } 78 | 79 | /** 80 | * Shows the settings page or a 404 if the user does not have access 81 | * 82 | * @return void 83 | */ 84 | public function showSettingsPage() 85 | { 86 | if (!current_user_can(apply_filters($this->capability, 'manage_options'))) { 87 | require_once __DIR__ . '/../templates/access-denied.php'; 88 | wp_die(); 89 | } 90 | 91 | $postTypes = $this->getAllPostTypes(); 92 | $enabled = $this->getEnabledPostTypes(); 93 | 94 | require_once __DIR__ . '/../templates/settings.php'; 95 | } 96 | 97 | /** 98 | * Save the new settings to the options table and then update the db to add 99 | * new tables and rebuild the triggers 100 | * 101 | * @return void 102 | */ 103 | public function saveSettings() 104 | { 105 | $oldPostTypes = $this->getEnabledPostTypes(); 106 | $newPostTypes = $_POST['custom_post_type_tables_enable'] ?: []; 107 | 108 | if ($oldPostTypes != $newPostTypes) { 109 | $this->updateDatabaseSchema($newPostTypes); 110 | update_option($this->enabledOption, serialize($newPostTypes), null, true); 111 | } 112 | 113 | wp_redirect($_SERVER['REQUEST_URI'] . '&success=true'); 114 | } 115 | 116 | /** 117 | * Create new tables and rebuild triggers 118 | * 119 | * @param array $postTypes 120 | * @return void 121 | */ 122 | private function updateDatabaseSchema(array $postTypes) 123 | { 124 | foreach ($postTypes as $postType) { 125 | $this->table->create($postType); 126 | } 127 | 128 | $this->triggers->create($postTypes); 129 | } 130 | 131 | /** 132 | * Gets the option that stores enabled post type tables and unserializes it 133 | * @return array 134 | */ 135 | public function getEnabledPostTypes() : array 136 | { 137 | return unserialize(get_option($this->enabledOption)) ?: []; 138 | } 139 | 140 | /** 141 | * Parses the public WP post types object into an array with the name 142 | * and the slug in. Then order alphabetically. 143 | * 144 | * @return array 145 | */ 146 | public function getAllPostTypes() : array 147 | { 148 | $postTypes = array_map( 149 | function ($postType) { 150 | return ['name' => $postType['labels']['name'], 'slug' => $postType['name']]; 151 | }, 152 | json_decode(json_encode(get_post_types(['public' => true], 'object')), true) 153 | ); 154 | 155 | $postTypes = array_filter($postTypes, function ($item) { 156 | return !in_array($item['slug'], $this->exclude); 157 | }); 158 | 159 | usort($postTypes, function ($a, $b) { 160 | return strcmp($a['name'], $b['name']); 161 | }); 162 | 163 | return $postTypes; 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /lib/Table.php: -------------------------------------------------------------------------------- 1 | db = $db; 26 | $this->config = $config; 27 | } 28 | 29 | /** 30 | * Executes the methods required to add the necessary tables 31 | * @param string $table 32 | * @return void 33 | */ 34 | public function create(string $table) 35 | { 36 | $table = str_replace('-', '_', $table); 37 | 38 | $this->createPostTable($table); 39 | $this->createMetaTable($table); 40 | } 41 | 42 | /** 43 | * Creates the new post table for the custom post type, basing the structure 44 | * on wp_posts 45 | * 46 | * @param array $table 47 | * @return void 48 | */ 49 | private function createPostTable(string $table) 50 | { 51 | $this->db->query( 52 | sprintf( 53 | "CREATE TABLE IF NOT EXISTS %s LIKE %s", 54 | $this->db->escape($table), 55 | $this->db->escape($this->config['default_post_table']) 56 | ) 57 | ); 58 | } 59 | 60 | /** 61 | * Creates the new postmeta table for the custom post type, basing the 62 | * structure on wp_postmeta 63 | * 64 | * @param array $table 65 | * @return void 66 | */ 67 | private function createMetaTable(string $table) 68 | { 69 | $this->db->query( 70 | sprintf( 71 | "CREATE TABLE IF NOT EXISTS %s LIKE %s", 72 | $this->db->escape($table . '_meta'), 73 | $this->db->escape($this->config['default_meta_table']) 74 | ) 75 | ); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /lib/Triggers.php: -------------------------------------------------------------------------------- 1 | db = $db; 36 | $this->config = $config; 37 | } 38 | 39 | /** 40 | * Executes the methods required to set up all necessary triggers 41 | * @param array $tables 42 | * @return void 43 | */ 44 | public function create(array $tables) 45 | { 46 | $this->createPostTrigger($tables); 47 | $this->createMetaTrigger($tables); 48 | } 49 | 50 | /** 51 | * Creates a trigger on the new custom post type table that copies each new 52 | * row of data from the posts table to the custom table 53 | * 54 | * @param array $tables 55 | * @return void 56 | */ 57 | private function createPostTrigger(array $tables) 58 | { 59 | $this->db->value("DROP TRIGGER IF EXISTS " . $this->db->escape($this->postsTrigger)); 60 | 61 | $params = []; 62 | $query = sprintf( 63 | "CREATE TRIGGER %s 64 | AFTER INSERT ON %s FOR EACH ROW BEGIN ", 65 | $this->db->escape($this->postsTrigger), 66 | $this->db->escape($this->config['default_post_table']) 67 | ); 68 | 69 | foreach ($tables as $i => $postType) { 70 | $table = str_replace('-', '_', $postType); 71 | 72 | if ($i) { 73 | $query .= 'ELSE'; 74 | } 75 | 76 | $query .= sprintf( 77 | "IF (? = NEW.post_type) THEN 78 | REPLACE INTO %s (ID, post_author, post_date, post_date_gmt, post_content, post_title, post_excerpt, post_status, comment_status, ping_status, post_password, post_name, to_ping, pinged, post_modified, post_modified_gmt, post_content_filtered, post_parent, guid, menu_order, post_type, post_mime_type, comment_count) 79 | VALUES (NEW.ID, NEW.post_author, NEW.post_date, NEW.post_date_gmt, NEW.post_content, NEW.post_title, NEW.post_excerpt, NEW.post_status, NEW.comment_status, NEW.ping_status, NEW.post_password, NEW.post_name, NEW.to_ping, NEW.pinged, NEW.post_modified, NEW.post_modified_gmt, NEW.post_content_filtered, NEW.post_parent, NEW.guid, NEW.menu_order, NEW.post_type, NEW.post_mime_type, NEW.comment_count); 80 | ", 81 | $this->db->escape($table) 82 | ); 83 | 84 | $params[] = $postType; 85 | } 86 | 87 | $query .= "END IF; END"; 88 | 89 | $this->db->query($query, ...$params); 90 | } 91 | 92 | /** 93 | * Creates a trigger on the new custom post type meta table that copies each 94 | * new row of data from the post meta table to the custom meta table 95 | * 96 | * @param array $tables 97 | * @return void 98 | */ 99 | private function createMetaTrigger(array $tables) 100 | { 101 | $this->db->value("DROP TRIGGER IF EXISTS " . $this->db->escape($this->metaTrigger)); 102 | 103 | $params = []; 104 | $query = sprintf( 105 | "CREATE TRIGGER %s 106 | AFTER INSERT ON %s FOR EACH ROW BEGIN ", 107 | $this->db->escape($this->metaTrigger), 108 | $this->db->escape($this->config['default_meta_table']) 109 | ); 110 | 111 | foreach ($tables as $i => $postType) { 112 | $table = str_replace('-', '_', $postType); 113 | 114 | if ($i) { 115 | $query .= 'ELSE'; 116 | } 117 | 118 | $query .= sprintf( 119 | "IF ((SELECT post_type FROM %s WHERE ID = NEW.post_id) = ?) THEN 120 | REPLACE INTO %s (meta_id, post_id, meta_key, meta_value) 121 | VALUES (NEW.meta_id, NEW.post_id, NEW.meta_key, NEW.meta_value); 122 | ", 123 | $this->db->escape($this->config['default_post_table']), 124 | $this->db->escape($table . '_meta') 125 | ); 126 | 127 | $params[] = $postType; 128 | } 129 | 130 | $query .= "END IF; END"; 131 | 132 | $this->db->query($query, ...$params); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /templates/access-denied.php: -------------------------------------------------------------------------------- 1 | 8 | 9 |
10 |

Error 404

11 |

This page does not exist.

12 |
13 | -------------------------------------------------------------------------------- /templates/settings.php: -------------------------------------------------------------------------------- 1 | 8 | 9 |
10 |

Custom Post Type Tables

11 | 12 | 13 |
14 |

15 | Custom tables have been updated. 16 |

17 | 19 |
20 | 21 | 22 |
23 | 24 |
25 | Which custom post types would you like to enable custom tables for? 26 | 27 | 28 |

29 | 38 |

39 | 40 | 41 |
42 | 43 |
44 |
45 | -------------------------------------------------------------------------------- /vendor/autoload.php: -------------------------------------------------------------------------------- 1 | 7 | * Jordi Boggiano 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Composer\Autoload; 14 | 15 | /** 16 | * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. 17 | * 18 | * $loader = new \Composer\Autoload\ClassLoader(); 19 | * 20 | * // register classes with namespaces 21 | * $loader->add('Symfony\Component', __DIR__.'/component'); 22 | * $loader->add('Symfony', __DIR__.'/framework'); 23 | * 24 | * // activate the autoloader 25 | * $loader->register(); 26 | * 27 | * // to enable searching the include path (eg. for PEAR packages) 28 | * $loader->setUseIncludePath(true); 29 | * 30 | * In this example, if you try to use a class in the Symfony\Component 31 | * namespace or one of its children (Symfony\Component\Console for instance), 32 | * the autoloader will first look for the class under the component/ 33 | * directory, and it will then fallback to the framework/ directory if not 34 | * found before giving up. 35 | * 36 | * This class is loosely based on the Symfony UniversalClassLoader. 37 | * 38 | * @author Fabien Potencier 39 | * @author Jordi Boggiano 40 | * @see http://www.php-fig.org/psr/psr-0/ 41 | * @see http://www.php-fig.org/psr/psr-4/ 42 | */ 43 | class ClassLoader 44 | { 45 | // PSR-4 46 | private $prefixLengthsPsr4 = array(); 47 | private $prefixDirsPsr4 = array(); 48 | private $fallbackDirsPsr4 = array(); 49 | 50 | // PSR-0 51 | private $prefixesPsr0 = array(); 52 | private $fallbackDirsPsr0 = array(); 53 | 54 | private $useIncludePath = false; 55 | private $classMap = array(); 56 | 57 | private $classMapAuthoritative = false; 58 | 59 | public function getPrefixes() 60 | { 61 | if (!empty($this->prefixesPsr0)) { 62 | return call_user_func_array('array_merge', $this->prefixesPsr0); 63 | } 64 | 65 | return array(); 66 | } 67 | 68 | public function getPrefixesPsr4() 69 | { 70 | return $this->prefixDirsPsr4; 71 | } 72 | 73 | public function getFallbackDirs() 74 | { 75 | return $this->fallbackDirsPsr0; 76 | } 77 | 78 | public function getFallbackDirsPsr4() 79 | { 80 | return $this->fallbackDirsPsr4; 81 | } 82 | 83 | public function getClassMap() 84 | { 85 | return $this->classMap; 86 | } 87 | 88 | /** 89 | * @param array $classMap Class to filename map 90 | */ 91 | public function addClassMap(array $classMap) 92 | { 93 | if ($this->classMap) { 94 | $this->classMap = array_merge($this->classMap, $classMap); 95 | } else { 96 | $this->classMap = $classMap; 97 | } 98 | } 99 | 100 | /** 101 | * Registers a set of PSR-0 directories for a given prefix, either 102 | * appending or prepending to the ones previously set for this prefix. 103 | * 104 | * @param string $prefix The prefix 105 | * @param array|string $paths The PSR-0 root directories 106 | * @param bool $prepend Whether to prepend the directories 107 | */ 108 | public function add($prefix, $paths, $prepend = false) 109 | { 110 | if (!$prefix) { 111 | if ($prepend) { 112 | $this->fallbackDirsPsr0 = array_merge( 113 | (array) $paths, 114 | $this->fallbackDirsPsr0 115 | ); 116 | } else { 117 | $this->fallbackDirsPsr0 = array_merge( 118 | $this->fallbackDirsPsr0, 119 | (array) $paths 120 | ); 121 | } 122 | 123 | return; 124 | } 125 | 126 | $first = $prefix[0]; 127 | if (!isset($this->prefixesPsr0[$first][$prefix])) { 128 | $this->prefixesPsr0[$first][$prefix] = (array) $paths; 129 | 130 | return; 131 | } 132 | if ($prepend) { 133 | $this->prefixesPsr0[$first][$prefix] = array_merge( 134 | (array) $paths, 135 | $this->prefixesPsr0[$first][$prefix] 136 | ); 137 | } else { 138 | $this->prefixesPsr0[$first][$prefix] = array_merge( 139 | $this->prefixesPsr0[$first][$prefix], 140 | (array) $paths 141 | ); 142 | } 143 | } 144 | 145 | /** 146 | * Registers a set of PSR-4 directories for a given namespace, either 147 | * appending or prepending to the ones previously set for this namespace. 148 | * 149 | * @param string $prefix The prefix/namespace, with trailing '\\' 150 | * @param array|string $paths The PSR-4 base directories 151 | * @param bool $prepend Whether to prepend the directories 152 | * 153 | * @throws \InvalidArgumentException 154 | */ 155 | public function addPsr4($prefix, $paths, $prepend = false) 156 | { 157 | if (!$prefix) { 158 | // Register directories for the root namespace. 159 | if ($prepend) { 160 | $this->fallbackDirsPsr4 = array_merge( 161 | (array) $paths, 162 | $this->fallbackDirsPsr4 163 | ); 164 | } else { 165 | $this->fallbackDirsPsr4 = array_merge( 166 | $this->fallbackDirsPsr4, 167 | (array) $paths 168 | ); 169 | } 170 | } elseif (!isset($this->prefixDirsPsr4[$prefix])) { 171 | // Register directories for a new namespace. 172 | $length = strlen($prefix); 173 | if ('\\' !== $prefix[$length - 1]) { 174 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 175 | } 176 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 177 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 178 | } elseif ($prepend) { 179 | // Prepend directories for an already registered namespace. 180 | $this->prefixDirsPsr4[$prefix] = array_merge( 181 | (array) $paths, 182 | $this->prefixDirsPsr4[$prefix] 183 | ); 184 | } else { 185 | // Append directories for an already registered namespace. 186 | $this->prefixDirsPsr4[$prefix] = array_merge( 187 | $this->prefixDirsPsr4[$prefix], 188 | (array) $paths 189 | ); 190 | } 191 | } 192 | 193 | /** 194 | * Registers a set of PSR-0 directories for a given prefix, 195 | * replacing any others previously set for this prefix. 196 | * 197 | * @param string $prefix The prefix 198 | * @param array|string $paths The PSR-0 base directories 199 | */ 200 | public function set($prefix, $paths) 201 | { 202 | if (!$prefix) { 203 | $this->fallbackDirsPsr0 = (array) $paths; 204 | } else { 205 | $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; 206 | } 207 | } 208 | 209 | /** 210 | * Registers a set of PSR-4 directories for a given namespace, 211 | * replacing any others previously set for this namespace. 212 | * 213 | * @param string $prefix The prefix/namespace, with trailing '\\' 214 | * @param array|string $paths The PSR-4 base directories 215 | * 216 | * @throws \InvalidArgumentException 217 | */ 218 | public function setPsr4($prefix, $paths) 219 | { 220 | if (!$prefix) { 221 | $this->fallbackDirsPsr4 = (array) $paths; 222 | } else { 223 | $length = strlen($prefix); 224 | if ('\\' !== $prefix[$length - 1]) { 225 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 226 | } 227 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 228 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 229 | } 230 | } 231 | 232 | /** 233 | * Turns on searching the include path for class files. 234 | * 235 | * @param bool $useIncludePath 236 | */ 237 | public function setUseIncludePath($useIncludePath) 238 | { 239 | $this->useIncludePath = $useIncludePath; 240 | } 241 | 242 | /** 243 | * Can be used to check if the autoloader uses the include path to check 244 | * for classes. 245 | * 246 | * @return bool 247 | */ 248 | public function getUseIncludePath() 249 | { 250 | return $this->useIncludePath; 251 | } 252 | 253 | /** 254 | * Turns off searching the prefix and fallback directories for classes 255 | * that have not been registered with the class map. 256 | * 257 | * @param bool $classMapAuthoritative 258 | */ 259 | public function setClassMapAuthoritative($classMapAuthoritative) 260 | { 261 | $this->classMapAuthoritative = $classMapAuthoritative; 262 | } 263 | 264 | /** 265 | * Should class lookup fail if not found in the current class map? 266 | * 267 | * @return bool 268 | */ 269 | public function isClassMapAuthoritative() 270 | { 271 | return $this->classMapAuthoritative; 272 | } 273 | 274 | /** 275 | * Registers this instance as an autoloader. 276 | * 277 | * @param bool $prepend Whether to prepend the autoloader or not 278 | */ 279 | public function register($prepend = false) 280 | { 281 | spl_autoload_register(array($this, 'loadClass'), true, $prepend); 282 | } 283 | 284 | /** 285 | * Unregisters this instance as an autoloader. 286 | */ 287 | public function unregister() 288 | { 289 | spl_autoload_unregister(array($this, 'loadClass')); 290 | } 291 | 292 | /** 293 | * Loads the given class or interface. 294 | * 295 | * @param string $class The name of the class 296 | * @return bool|null True if loaded, null otherwise 297 | */ 298 | public function loadClass($class) 299 | { 300 | if ($file = $this->findFile($class)) { 301 | includeFile($file); 302 | 303 | return true; 304 | } 305 | } 306 | 307 | /** 308 | * Finds the path to the file where the class is defined. 309 | * 310 | * @param string $class The name of the class 311 | * 312 | * @return string|false The path if found, false otherwise 313 | */ 314 | public function findFile($class) 315 | { 316 | // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 317 | if ('\\' == $class[0]) { 318 | $class = substr($class, 1); 319 | } 320 | 321 | // class map lookup 322 | if (isset($this->classMap[$class])) { 323 | return $this->classMap[$class]; 324 | } 325 | if ($this->classMapAuthoritative) { 326 | return false; 327 | } 328 | 329 | $file = $this->findFileWithExtension($class, '.php'); 330 | 331 | // Search for Hack files if we are running on HHVM 332 | if ($file === null && defined('HHVM_VERSION')) { 333 | $file = $this->findFileWithExtension($class, '.hh'); 334 | } 335 | 336 | if ($file === null) { 337 | // Remember that this class does not exist. 338 | return $this->classMap[$class] = false; 339 | } 340 | 341 | return $file; 342 | } 343 | 344 | private function findFileWithExtension($class, $ext) 345 | { 346 | // PSR-4 lookup 347 | $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; 348 | 349 | $first = $class[0]; 350 | if (isset($this->prefixLengthsPsr4[$first])) { 351 | foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { 352 | if (0 === strpos($class, $prefix)) { 353 | foreach ($this->prefixDirsPsr4[$prefix] as $dir) { 354 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { 355 | return $file; 356 | } 357 | } 358 | } 359 | } 360 | } 361 | 362 | // PSR-4 fallback dirs 363 | foreach ($this->fallbackDirsPsr4 as $dir) { 364 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { 365 | return $file; 366 | } 367 | } 368 | 369 | // PSR-0 lookup 370 | if (false !== $pos = strrpos($class, '\\')) { 371 | // namespaced class name 372 | $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) 373 | . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); 374 | } else { 375 | // PEAR-like class name 376 | $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; 377 | } 378 | 379 | if (isset($this->prefixesPsr0[$first])) { 380 | foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { 381 | if (0 === strpos($class, $prefix)) { 382 | foreach ($dirs as $dir) { 383 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 384 | return $file; 385 | } 386 | } 387 | } 388 | } 389 | } 390 | 391 | // PSR-0 fallback dirs 392 | foreach ($this->fallbackDirsPsr0 as $dir) { 393 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 394 | return $file; 395 | } 396 | } 397 | 398 | // PSR-0 include paths. 399 | if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { 400 | return $file; 401 | } 402 | } 403 | } 404 | 405 | /** 406 | * Scope isolated include. 407 | * 408 | * Prevents access to $this/self from included files. 409 | */ 410 | function includeFile($file) 411 | { 412 | include $file; 413 | } 414 | -------------------------------------------------------------------------------- /vendor/composer/LICENSE: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: Composer 3 | Upstream-Contact: Jordi Boggiano 4 | Source: https://github.com/composer/composer 5 | 6 | Files: * 7 | Copyright: 2016, Nils Adermann 8 | 2016, Jordi Boggiano 9 | License: Expat 10 | 11 | Files: res/cacert.pem 12 | Copyright: 2015, Mozilla Foundation 13 | License: MPL-2.0 14 | 15 | Files: src/Composer/Util/RemoteFilesystem.php 16 | src/Composer/Util/TlsHelper.php 17 | Copyright: 2016, Nils Adermann 18 | 2016, Jordi Boggiano 19 | 2013, Evan Coury 20 | License: Expat and BSD-2-Clause 21 | 22 | License: BSD-2-Clause 23 | Redistribution and use in source and binary forms, with or without modification, 24 | are permitted provided that the following conditions are met: 25 | . 26 | * Redistributions of source code must retain the above copyright notice, 27 | this list of conditions and the following disclaimer. 28 | . 29 | * Redistributions in binary form must reproduce the above copyright notice, 30 | this list of conditions and the following disclaimer in the documentation 31 | and/or other materials provided with the distribution. 32 | . 33 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 34 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 35 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 36 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 37 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 38 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 39 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 40 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 41 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 42 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 43 | 44 | License: Expat 45 | Permission is hereby granted, free of charge, to any person obtaining a copy 46 | of this software and associated documentation files (the "Software"), to deal 47 | in the Software without restriction, including without limitation the rights 48 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 49 | copies of the Software, and to permit persons to whom the Software is furnished 50 | to do so, subject to the following conditions: 51 | . 52 | The above copyright notice and this permission notice shall be included in all 53 | copies or substantial portions of the Software. 54 | . 55 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 56 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 57 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 58 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 59 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 60 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 61 | THE SOFTWARE. 62 | 63 | License: MPL-2.0 64 | 1. Definitions 65 | -------------- 66 | . 67 | 1.1. "Contributor" 68 | means each individual or legal entity that creates, contributes to 69 | the creation of, or owns Covered Software. 70 | . 71 | 1.2. "Contributor Version" 72 | means the combination of the Contributions of others (if any) used 73 | by a Contributor and that particular Contributor's Contribution. 74 | . 75 | 1.3. "Contribution" 76 | means Covered Software of a particular Contributor. 77 | . 78 | 1.4. "Covered Software" 79 | means Source Code Form to which the initial Contributor has attached 80 | the notice in Exhibit A, the Executable Form of such Source Code 81 | Form, and Modifications of such Source Code Form, in each case 82 | including portions thereof. 83 | . 84 | 1.5. "Incompatible With Secondary Licenses" 85 | means 86 | . 87 | (a) that the initial Contributor has attached the notice described 88 | in Exhibit B to the Covered Software; or 89 | . 90 | (b) that the Covered Software was made available under the terms of 91 | version 1.1 or earlier of the License, but not also under the 92 | terms of a Secondary License. 93 | . 94 | 1.6. "Executable Form" 95 | means any form of the work other than Source Code Form. 96 | . 97 | 1.7. "Larger Work" 98 | means a work that combines Covered Software with other material, in 99 | a separate file or files, that is not Covered Software. 100 | . 101 | 1.8. "License" 102 | means this document. 103 | . 104 | 1.9. "Licensable" 105 | means having the right to grant, to the maximum extent possible, 106 | whether at the time of the initial grant or subsequently, any and 107 | all of the rights conveyed by this License. 108 | . 109 | 1.10. "Modifications" 110 | means any of the following: 111 | . 112 | (a) any file in Source Code Form that results from an addition to, 113 | deletion from, or modification of the contents of Covered 114 | Software; or 115 | . 116 | (b) any new file in Source Code Form that contains any Covered 117 | Software. 118 | . 119 | 1.11. "Patent Claims" of a Contributor 120 | means any patent claim(s), including without limitation, method, 121 | process, and apparatus claims, in any patent Licensable by such 122 | Contributor that would be infringed, but for the grant of the 123 | License, by the making, using, selling, offering for sale, having 124 | made, import, or transfer of either its Contributions or its 125 | Contributor Version. 126 | . 127 | 1.12. "Secondary License" 128 | means either the GNU General Public License, Version 2.0, the GNU 129 | Lesser General Public License, Version 2.1, the GNU Affero General 130 | Public License, Version 3.0, or any later versions of those 131 | licenses. 132 | . 133 | 1.13. "Source Code Form" 134 | means the form of the work preferred for making modifications. 135 | . 136 | 1.14. "You" (or "Your") 137 | means an individual or a legal entity exercising rights under this 138 | License. For legal entities, "You" includes any entity that 139 | controls, is controlled by, or is under common control with You. For 140 | purposes of this definition, "control" means (a) the power, direct 141 | or indirect, to cause the direction or management of such entity, 142 | whether by contract or otherwise, or (b) ownership of more than 143 | fifty percent (50%) of the outstanding shares or beneficial 144 | ownership of such entity. 145 | . 146 | 2. License Grants and Conditions 147 | -------------------------------- 148 | . 149 | 2.1. Grants 150 | . 151 | Each Contributor hereby grants You a world-wide, royalty-free, 152 | non-exclusive license: 153 | . 154 | (a) under intellectual property rights (other than patent or trademark) 155 | Licensable by such Contributor to use, reproduce, make available, 156 | modify, display, perform, distribute, and otherwise exploit its 157 | Contributions, either on an unmodified basis, with Modifications, or 158 | as part of a Larger Work; and 159 | . 160 | (b) under Patent Claims of such Contributor to make, use, sell, offer 161 | for sale, have made, import, and otherwise transfer either its 162 | Contributions or its Contributor Version. 163 | . 164 | 2.2. Effective Date 165 | . 166 | The licenses granted in Section 2.1 with respect to any Contribution 167 | become effective for each Contribution on the date the Contributor first 168 | distributes such Contribution. 169 | . 170 | 2.3. Limitations on Grant Scope 171 | . 172 | The licenses granted in this Section 2 are the only rights granted under 173 | this License. No additional rights or licenses will be implied from the 174 | distribution or licensing of Covered Software under this License. 175 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 176 | Contributor: 177 | . 178 | (a) for any code that a Contributor has removed from Covered Software; 179 | or 180 | . 181 | (b) for infringements caused by: (i) Your and any other third party's 182 | modifications of Covered Software, or (ii) the combination of its 183 | Contributions with other software (except as part of its Contributor 184 | Version); or 185 | . 186 | (c) under Patent Claims infringed by Covered Software in the absence of 187 | its Contributions. 188 | . 189 | This License does not grant any rights in the trademarks, service marks, 190 | or logos of any Contributor (except as may be necessary to comply with 191 | the notice requirements in Section 3.4). 192 | . 193 | 2.4. Subsequent Licenses 194 | . 195 | No Contributor makes additional grants as a result of Your choice to 196 | distribute the Covered Software under a subsequent version of this 197 | License (see Section 10.2) or under the terms of a Secondary License (if 198 | permitted under the terms of Section 3.3). 199 | . 200 | 2.5. Representation 201 | . 202 | Each Contributor represents that the Contributor believes its 203 | Contributions are its original creation(s) or it has sufficient rights 204 | to grant the rights to its Contributions conveyed by this License. 205 | . 206 | 2.6. Fair Use 207 | . 208 | This License is not intended to limit any rights You have under 209 | applicable copyright doctrines of fair use, fair dealing, or other 210 | equivalents. 211 | . 212 | 2.7. Conditions 213 | . 214 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 215 | in Section 2.1. 216 | . 217 | 3. Responsibilities 218 | ------------------- 219 | . 220 | 3.1. Distribution of Source Form 221 | . 222 | All distribution of Covered Software in Source Code Form, including any 223 | Modifications that You create or to which You contribute, must be under 224 | the terms of this License. You must inform recipients that the Source 225 | Code Form of the Covered Software is governed by the terms of this 226 | License, and how they can obtain a copy of this License. You may not 227 | attempt to alter or restrict the recipients' rights in the Source Code 228 | Form. 229 | . 230 | 3.2. Distribution of Executable Form 231 | . 232 | If You distribute Covered Software in Executable Form then: 233 | . 234 | (a) such Covered Software must also be made available in Source Code 235 | Form, as described in Section 3.1, and You must inform recipients of 236 | the Executable Form how they can obtain a copy of such Source Code 237 | Form by reasonable means in a timely manner, at a charge no more 238 | than the cost of distribution to the recipient; and 239 | . 240 | (b) You may distribute such Executable Form under the terms of this 241 | License, or sublicense it under different terms, provided that the 242 | license for the Executable Form does not attempt to limit or alter 243 | the recipients' rights in the Source Code Form under this License. 244 | . 245 | 3.3. Distribution of a Larger Work 246 | . 247 | You may create and distribute a Larger Work under terms of Your choice, 248 | provided that You also comply with the requirements of this License for 249 | the Covered Software. If the Larger Work is a combination of Covered 250 | Software with a work governed by one or more Secondary Licenses, and the 251 | Covered Software is not Incompatible With Secondary Licenses, this 252 | License permits You to additionally distribute such Covered Software 253 | under the terms of such Secondary License(s), so that the recipient of 254 | the Larger Work may, at their option, further distribute the Covered 255 | Software under the terms of either this License or such Secondary 256 | License(s). 257 | . 258 | 3.4. Notices 259 | . 260 | You may not remove or alter the substance of any license notices 261 | (including copyright notices, patent notices, disclaimers of warranty, 262 | or limitations of liability) contained within the Source Code Form of 263 | the Covered Software, except that You may alter any license notices to 264 | the extent required to remedy known factual inaccuracies. 265 | . 266 | 3.5. Application of Additional Terms 267 | . 268 | You may choose to offer, and to charge a fee for, warranty, support, 269 | indemnity or liability obligations to one or more recipients of Covered 270 | Software. However, You may do so only on Your own behalf, and not on 271 | behalf of any Contributor. You must make it absolutely clear that any 272 | such warranty, support, indemnity, or liability obligation is offered by 273 | You alone, and You hereby agree to indemnify every Contributor for any 274 | liability incurred by such Contributor as a result of warranty, support, 275 | indemnity or liability terms You offer. You may include additional 276 | disclaimers of warranty and limitations of liability specific to any 277 | jurisdiction. 278 | . 279 | 4. Inability to Comply Due to Statute or Regulation 280 | --------------------------------------------------- 281 | . 282 | If it is impossible for You to comply with any of the terms of this 283 | License with respect to some or all of the Covered Software due to 284 | statute, judicial order, or regulation then You must: (a) comply with 285 | the terms of this License to the maximum extent possible; and (b) 286 | describe the limitations and the code they affect. Such description must 287 | be placed in a text file included with all distributions of the Covered 288 | Software under this License. Except to the extent prohibited by statute 289 | or regulation, such description must be sufficiently detailed for a 290 | recipient of ordinary skill to be able to understand it. 291 | . 292 | 5. Termination 293 | -------------- 294 | . 295 | 5.1. The rights granted under this License will terminate automatically 296 | if You fail to comply with any of its terms. However, if You become 297 | compliant, then the rights granted under this License from a particular 298 | Contributor are reinstated (a) provisionally, unless and until such 299 | Contributor explicitly and finally terminates Your grants, and (b) on an 300 | ongoing basis, if such Contributor fails to notify You of the 301 | non-compliance by some reasonable means prior to 60 days after You have 302 | come back into compliance. Moreover, Your grants from a particular 303 | Contributor are reinstated on an ongoing basis if such Contributor 304 | notifies You of the non-compliance by some reasonable means, this is the 305 | first time You have received notice of non-compliance with this License 306 | from such Contributor, and You become compliant prior to 30 days after 307 | Your receipt of the notice. 308 | . 309 | 5.2. If You initiate litigation against any entity by asserting a patent 310 | infringement claim (excluding declaratory judgment actions, 311 | counter-claims, and cross-claims) alleging that a Contributor Version 312 | directly or indirectly infringes any patent, then the rights granted to 313 | You by any and all Contributors for the Covered Software under Section 314 | 2.1 of this License shall terminate. 315 | . 316 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 317 | end user license agreements (excluding distributors and resellers) which 318 | have been validly granted by You or Your distributors under this License 319 | prior to termination shall survive termination. 320 | . 321 | ************************************************************************ 322 | * * 323 | * 6. Disclaimer of Warranty * 324 | * ------------------------- * 325 | * * 326 | * Covered Software is provided under this License on an "as is" * 327 | * basis, without warranty of any kind, either expressed, implied, or * 328 | * statutory, including, without limitation, warranties that the * 329 | * Covered Software is free of defects, merchantable, fit for a * 330 | * particular purpose or non-infringing. The entire risk as to the * 331 | * quality and performance of the Covered Software is with You. * 332 | * Should any Covered Software prove defective in any respect, You * 333 | * (not any Contributor) assume the cost of any necessary servicing, * 334 | * repair, or correction. This disclaimer of warranty constitutes an * 335 | * essential part of this License. No use of any Covered Software is * 336 | * authorized under this License except under this disclaimer. * 337 | * * 338 | ************************************************************************ 339 | . 340 | ************************************************************************ 341 | * * 342 | * 7. Limitation of Liability * 343 | * -------------------------- * 344 | * * 345 | * Under no circumstances and under no legal theory, whether tort * 346 | * (including negligence), contract, or otherwise, shall any * 347 | * Contributor, or anyone who distributes Covered Software as * 348 | * permitted above, be liable to You for any direct, indirect, * 349 | * special, incidental, or consequential damages of any character * 350 | * including, without limitation, damages for lost profits, loss of * 351 | * goodwill, work stoppage, computer failure or malfunction, or any * 352 | * and all other commercial damages or losses, even if such party * 353 | * shall have been informed of the possibility of such damages. This * 354 | * limitation of liability shall not apply to liability for death or * 355 | * personal injury resulting from such party's negligence to the * 356 | * extent applicable law prohibits such limitation. Some * 357 | * jurisdictions do not allow the exclusion or limitation of * 358 | * incidental or consequential damages, so this exclusion and * 359 | * limitation may not apply to You. * 360 | * * 361 | ************************************************************************ 362 | . 363 | 8. Litigation 364 | ------------- 365 | . 366 | Any litigation relating to this License may be brought only in the 367 | courts of a jurisdiction where the defendant maintains its principal 368 | place of business and such litigation shall be governed by laws of that 369 | jurisdiction, without reference to its conflict-of-law provisions. 370 | Nothing in this Section shall prevent a party's ability to bring 371 | cross-claims or counter-claims. 372 | . 373 | 9. Miscellaneous 374 | ---------------- 375 | . 376 | This License represents the complete agreement concerning the subject 377 | matter hereof. If any provision of this License is held to be 378 | unenforceable, such provision shall be reformed only to the extent 379 | necessary to make it enforceable. Any law or regulation which provides 380 | that the language of a contract shall be construed against the drafter 381 | shall not be used to construe this License against a Contributor. 382 | . 383 | 10. Versions of the License 384 | --------------------------- 385 | . 386 | 10.1. New Versions 387 | . 388 | Mozilla Foundation is the license steward. Except as provided in Section 389 | 10.3, no one other than the license steward has the right to modify or 390 | publish new versions of this License. Each version will be given a 391 | distinguishing version number. 392 | . 393 | 10.2. Effect of New Versions 394 | . 395 | You may distribute the Covered Software under the terms of the version 396 | of the License under which You originally received the Covered Software, 397 | or under the terms of any subsequent version published by the license 398 | steward. 399 | . 400 | 10.3. Modified Versions 401 | . 402 | If you create software not governed by this License, and you want to 403 | create a new license for such software, you may create and use a 404 | modified version of this License if you rename the license and remove 405 | any references to the name of the license steward (except to note that 406 | such modified license differs from this License). 407 | . 408 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 409 | Licenses 410 | . 411 | If You choose to distribute Source Code Form that is Incompatible With 412 | Secondary Licenses under the terms of this version of the License, the 413 | notice described in Exhibit B of this License must be attached. 414 | . 415 | Exhibit A - Source Code Form License Notice 416 | ------------------------------------------- 417 | . 418 | This Source Code Form is subject to the terms of the Mozilla Public 419 | License, v. 2.0. If a copy of the MPL was not distributed with this 420 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 421 | . 422 | If it is not possible or desirable to put the notice in a particular 423 | file, then You may include the notice in a location (such as a LICENSE 424 | file in a relevant directory) where a recipient would be likely to look 425 | for such a notice. 426 | . 427 | You may add additional accurate notices of copyright ownership. 428 | . 429 | Exhibit B - "Incompatible With Secondary Licenses" Notice 430 | --------------------------------------------------------- 431 | . 432 | This Source Code Form is "Incompatible With Secondary Licenses", as 433 | defined by the Mozilla Public License, v. 2.0. 434 | -------------------------------------------------------------------------------- /vendor/composer/autoload_classmap.php: -------------------------------------------------------------------------------- 1 | $baseDir . '/core.php', 10 | 'CptTables\\Lib\\AdminFilters' => $baseDir . '/lib/AdminFilters.php', 11 | 'CptTables\\Lib\\Db' => $baseDir . '/lib/Db.php', 12 | 'CptTables\\Lib\\QueryFilters' => $baseDir . '/lib/QueryFilters.php', 13 | 'CptTables\\Lib\\SettingsPage' => $baseDir . '/lib/SettingsPage.php', 14 | 'CptTables\\Lib\\Table' => $baseDir . '/lib/Table.php', 15 | 'CptTables\\Lib\\Triggers' => $baseDir . '/lib/Triggers.php', 16 | ); 17 | -------------------------------------------------------------------------------- /vendor/composer/autoload_namespaces.php: -------------------------------------------------------------------------------- 1 | array($baseDir . '/'), 10 | ); 11 | -------------------------------------------------------------------------------- /vendor/composer/autoload_real.php: -------------------------------------------------------------------------------- 1 | $path) { 28 | $loader->set($namespace, $path); 29 | } 30 | 31 | $map = require __DIR__ . '/autoload_psr4.php'; 32 | foreach ($map as $namespace => $path) { 33 | $loader->setPsr4($namespace, $path); 34 | } 35 | 36 | $classMap = require __DIR__ . '/autoload_classmap.php'; 37 | if ($classMap) { 38 | $loader->addClassMap($classMap); 39 | } 40 | 41 | $loader->register(true); 42 | 43 | return $loader; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /vendor/composer/autoload_static.php: -------------------------------------------------------------------------------- 1 | 11 | array ( 12 | 'CptTables\\' => 10, 13 | ), 14 | ); 15 | 16 | public static $prefixDirsPsr4 = array ( 17 | 'CptTables\\' => 18 | array ( 19 | 0 => __DIR__ . '/../..' . '/', 20 | ), 21 | ); 22 | 23 | public static $classMap = array ( 24 | 'CptTables\\Core' => __DIR__ . '/../..' . '/core.php', 25 | 'CptTables\\Lib\\AdminFilters' => __DIR__ . '/../..' . '/lib/AdminFilters.php', 26 | 'CptTables\\Lib\\Db' => __DIR__ . '/../..' . '/lib/Db.php', 27 | 'CptTables\\Lib\\QueryFilters' => __DIR__ . '/../..' . '/lib/QueryFilters.php', 28 | 'CptTables\\Lib\\Table' => __DIR__ . '/../..' . '/lib/Table.php', 29 | 'CptTables\\Lib\\Trigger' => __DIR__ . '/../..' . '/lib/Trigger.php', 30 | ); 31 | 32 | public static function getInitializer(ClassLoader $loader) 33 | { 34 | return \Closure::bind(function () use ($loader) { 35 | $loader->prefixLengthsPsr4 = ComposerStaticInitba9e9f1afb2751cc540ab85fb72552ec::$prefixLengthsPsr4; 36 | $loader->prefixDirsPsr4 = ComposerStaticInitba9e9f1afb2751cc540ab85fb72552ec::$prefixDirsPsr4; 37 | $loader->classMap = ComposerStaticInitba9e9f1afb2751cc540ab85fb72552ec::$classMap; 38 | 39 | }, null, ClassLoader::class); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /vendor/composer/installed.json: -------------------------------------------------------------------------------- 1 | [] 2 | --------------------------------------------------------------------------------