├── .gitignore ├── Change Log.txt ├── README.md ├── channel_data └── libraries │ └── Channeldata │ ├── base │ ├── BaseModel.php │ └── ChannelModel.php │ ├── channeldata.php │ ├── components │ ├── ChannelCollection.php │ ├── ChannelEntriesApi.php │ ├── ChannelEntriesParser.php │ ├── ChannelQueryBuilder.php │ ├── Collection.php │ ├── QueryBuilder.php │ └── QueryString.php │ ├── models │ ├── Action.php │ ├── Channel.php │ ├── ChannelData.php │ ├── ChannelEntry.php │ ├── ChannelField.php │ ├── ChannelTitle.php │ ├── Member.php │ └── MemberField.php │ └── responses │ ├── ChannelResponse.php │ └── QueryResponse.php └── license.txt /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.DS_Store 3 | -------------------------------------------------------------------------------- /Change Log.txt: -------------------------------------------------------------------------------- 1 | /** 2 | * Channel Data 3 | * Author: Justin Kimbrell (Objective HTML) 4 | * @version 1.0.0-rc3 5 | * @build 2014-03-03 6 | * Copyright 2013 - All rights reserved 7 | * http://objectivehtml.com 8 | */ 9 | 10 | #### 2014-03-03 11 | ##### 1.0.0-rc3 12 | 13 | - Added get() method to QueryResponse 14 | - Added toArray() method to QueryResponse 15 | - Added fixedOrder parameter to entries() method in Channel Response 16 | - Added findByUsername() to Member 17 | - Added label() method to ChannelField 18 | - Added findByName() method to ChannelField 19 | - Added findByName() method to ChannelField 20 | - Added groupBy() method to QueryBuilder 21 | - Added prefix() method to ChannelData 22 | - Added entries() method to ChannelModel 23 | - Added new ChannelEntriesParser class 24 | - Bug fixes in QueryString class 25 | - Bug fixes in QueryBuilder class 26 | - Bug fixes in ChannelEntriesApi class 27 | 28 | #### 2013-12-16 29 | ##### 1.0.0-rc2 30 | 31 | - Decoupled Channel Data into it’s own “module”. 32 | - Added more models and helper methods 33 | 34 | 35 | #### 2013-12-10 36 | ##### 1.0.0-rc1 37 | 38 | - Complete rewrite of entire API. All new docs and syntax based on Eloquent. 39 | 40 | 41 | Version 0.8.16 - 12/15/2012 42 | -------------------------- 43 | 44 | - Fixed a bug that caused OR operators to not work properly 45 | 46 | Version 0.8.15 - 12/15/2012 47 | -------------------------- 48 | - Fixed a bug created in the last version. 49 | 50 | Version 0.8.14 - 12/15/2012 51 | -------------------------- 52 | - Fixed a bug that prevented the conditionals from getting prepared correctly. 53 | 54 | Version 0.8.13 - 12/13/2012 55 | -------------------------- 56 | - Added error tolerance to Channel Data JOIN's. Now accepts arrays, index arrays, and strings. 57 | 58 | Version 0.8.12 - 12/01/2012 59 | -------------------------- 60 | - Added the ability to perform multiple joins. 61 | 62 | Version 0.8.11 - 11/06/2012 63 | -------------------------- 64 | - Fixed a bug in the parse_path_variables method. 65 | 66 | Version 0.8.10 - 10/28/2012 67 | -------------------------- 68 | - Fixed a bug in the tmpl parser that caused errors if module tags were nested within certain tag pairs. 69 | 70 | Version 0.8.9 - 10/26/2012 71 | -------------------------- 72 | - Added ability to parse custom date fields 73 | - Added ability to parse path variables 74 | 75 | Version 0.8.8 - 10/21/2012 76 | -------------------------- 77 | - Fixed a bug that caused the strip_logic method to incorrectly change variable names. 78 | 79 | Version 0.8.7 - 10/04/2012 80 | -------------------------- 81 | - Fixed the last known issue that prevented dependent classes from initializing. 82 | 83 | Version 0.8.6 - 10/04/2012 84 | -------------------------- 85 | - Fixed more parsing bugs. Trying to get the FT parsing nailed in this release. 86 | 87 | Version 0.8.5 - 10/03/2012 88 | -------------------------- 89 | - Fixed bugs that prevent template parse from parsing alt field type methods. 90 | 91 | Version 0.8.4 - 09/19/2012 92 | -------------------------- 93 | - Fixed bugs in the template parser 94 | 95 | Version 0.8.3 - 09/04/2012 96 | -------------------------- 97 | - Fixed bugs in the template parser 98 | 99 | Version 0.8.2 - 08/28/2012 100 | -------------------------- 101 | - Fixed a bug that omitted certain fields from the prepare_entry method. 102 | - Fixed a bug in the check_ambiguity method that return and improper value. 103 | - Fixed a bug in build_where method that prevented compound conditionals from working. 104 | - Addded new methods parse_array(), parse_string(), and parse() to the tmpl driver. 105 | - Fixed bugs in the new template parsing methods. 106 | - Added new methods to the tmpl driver to make parsing easier. 107 | 108 | Version 0.8.1 - 08/27/2012 109 | -------------------------- 110 | - Fixed a bug that prevented the default select vars from working in the get_channel_entries method. 111 | 112 | Version 0.8.0 - 08/20/2012 113 | -------------------------- 114 | - Rewrote SQL generate with several new abstract methods. The idea is that channel data 115 | can be used to make all your own model method consistent and polymorphic. 116 | - Better OR handling, and now supports compound clauses 117 | - General bug fixes with SQL generator 118 | 119 | Version 0.7.0 - 07/11/2012 120 | -------------------------- 121 | - Added new tmpl driver that makes parsing FT tags much easier 122 | - (Bug Fix) Fixed a number of issues in the prepare_entry() method. Added more default values. 123 | - (Bug Fix) Fixed an API inconsistency in the submit_entry() and update_entry() methods. 124 | - (Big Fix) Fixed a bug in the get_channel_entries method if queries with conditionals other than the default '='. 125 | 126 | Version 0.6.13 - 06/19/2012 127 | --------------------------- 128 | - Attempted to fix another PHP 5.4 issue that wasn't fixed in the last update. 129 | - Added a new reindex method that will convert an indexed array to an associative array by "re-indexing" it. 130 | 131 | Version 0.6.12 - 06/19/2012 132 | --------------------------- 133 | - Fixed a PHP 5.4 issue with the isset function not working correctly with variable variables. 134 | 135 | Version 0.6.11 - 05/18/2012 136 | --------------------------- 137 | - Added categories fields to the get_category_entries() method to be consistent with get_channel_entries() and get_members(). The get_categories method was maintained for legacy support. 138 | - Added prepare_entry(), submit_entry(), and update_entry() convenience methods to the data manipulation utility 139 | - Fixed bug with the get_channel_entries returning invalid field names for ambigious fields 140 | 141 | Version 0.6.10 - 04/18/2012 142 | --------------------------- 143 | - Properly escaped the WHERE and HAVING values for single quotes and SQL injection attacks. 144 | 145 | Version 0.6.9 - 04/05/2012 146 | ------------------------- 147 | - Fixed a pretty critical bug that prevented multiple WHERE clauses from working in the get_channel_entries method. 148 | 149 | Version 0.6.8 - 03/30/2012 150 | ------------------------- 151 | - HAVING clauses now have all the same capabilities as WHERE clauses. 152 | - Added a new method to the utility classes that merges two results_arrays into one array ready for template parsing. 153 | 154 | 155 | Version 0.6.7 - 2/28/2012 156 | ------------------------- 157 | Fixed an issue with polymorphic parameters not searching arguments in the correct order. Also added ability to search same parameter in associative array by added an index. 158 | 159 | 160 | Version 0.6.6 - 2/24/2012 161 | ------------------------- 162 | Fixed an issue with the add_prefix() method that prevents it from working correctly if the prefix was NULL. 163 | 164 | 165 | Version 0.6.5 - 2/11/2012 166 | ------------------------- 167 | Bug fix with get_channel_entries() method. Added new utility driver with add_prefix() method. 168 | 169 | 170 | Version 0.6.4 - 2/11/2012 171 | ------------------------- 172 | Bug fixes. 173 | 174 | 175 | Version 0.6.3 - 1/25/2012 176 | ------------------------- 177 | Fixed an issue with LIKE searches not working correctly. 178 | 179 | 180 | Version 0.6.2 - 1/15/2012 181 | ------------------------- 182 | Added two new methods: get_field_group, get_fields_groups() 183 | 184 | 185 | Version 0.6.1 - 12/30/2011 186 | -------------------------- 187 | Added a get_fields_by_group() convenience method. Fixed a couple API inconsistencies with methods nothing properly using polymorphism. Fixed an ambiguity error in the new get_members() method. 188 | 189 | 190 | Version 0.6.0 - 12/28/2011 191 | -------------------------- 192 | Just added get_members(), get_member(), get_member_fields(), get_member_field(), get_member_field_by_name(), get_member_groups(), get_member_group(), get_member_group_by_title(). Member queries are joined with the custom member fields just like the get_channel_entries() method. 193 | 194 | 195 | Version 0.5.4 - 12/28/2011 196 | -------------------------- 197 | Added another convenience method, get_channel_statuses(). I tried to ensure all get_channel_xxxxx($channel_id) methods are consistent, as grabbing data in relation to a channel_id is extremely common. Also updated the documentation slightly. 198 | 199 | 200 | Version 0.5.3 - 12/27/2011 201 | -------------------------- 202 | Added new convenience method 203 | 204 | 205 | Version 0.5.2 - 12/25/2011 206 | -------------------------- 207 | Added new convenience method 208 | 209 | 210 | Version 0.5.1 - 12/18/2011 211 | -------------------------- 212 | Fixed a bug that caused field names with "or" in them - like "author_id" - to improperly get replaced. 213 | 214 | 215 | Version 0.5.0 - 12/17/2011 216 | -------------------------- 217 | Changed the api slightly. get_channel_fields($group_id) has been changed more appropriately to get_channel_fields($channel_id). The get_channel_fields($group_id) more closely imitated the first part API which are the roots of the Channel Data api. Since the first party dependencies have been eliminated, this API change was necessary to move forward. 218 | 219 | 220 | Version 0.4.3 - 12/15/2011 221 | -------------------------- 222 | Bug fixed that cased SELECT parameter to create invalid queries in the event the user didn't define a SELECT parameter. 223 | 224 | 225 | Version 0.4.2 - 12/14/2011 226 | -------------------------- 227 | Paying a lot of attention to the polymorphic parameters and removing any bugs I can find. Also added complex conditionals and added "AND/OR" clauses to WHERE statements. 228 | 229 | 230 | Version 0.4.1 - 12/13/2011 231 | -------------------------- 232 | Rewrote the logic behind the where conditional element and how it's passed to Active Record. Fixed bugs that prevented OR and AND clauses from working correctly. 233 | 234 | 235 | Version 0.4.0 - 12/09/2011 236 | -------------------------- 237 | Officially appended a BSD license to the library making it free and open to use for the life of the project. 238 | 239 | 240 | Version 0.3.7 - 12/08/2011 241 | -------------------------- 242 | Bug fixed that prevented the polymorphic parameters from working when the select and where parameters aren't present. 243 | 244 | 245 | Version 0.3.6 - 12/08/2011 246 | -------------------------- 247 | Added two new methods: get_actions() and get_action_id() to quickly get one or more action ids. 248 | 249 | 250 | Version 0.3.5 - 11/30/2011 251 | -------------------------- 252 | Lots of bug fixes and code optimization. Stable release 1.0 release is starting to take shape. No major API changes for a while, and doesn't appear to need any. Every method has been tested at least once, but bugs could still be present. 253 | 254 | 255 | Version 0.3.4 - 11/15/2011 256 | -------------------------- 257 | Bug fixes 258 | 259 | 260 | Version 0.3.3 - 11/11/2011 261 | -------------------------- 262 | Bug fixed that prevented the get_channel_entry() method from working correctly 263 | 264 | 265 | Version 0.3.2 - 11/08/2011 266 | -------------------------- 267 | Bug fixes within some of the polymorphic properties 268 | 269 | 270 | Version 0.3.1 - 11/07/2011 271 | -------------------------- 272 | Added a new method: get_channel_by_name(). I got tired of typing a long syntax for something I wanted to very frequently. Also updated the documentation, hopefully it's a litter easier to read. 273 | 274 | 275 | Version 0.3.0 - 11/02/2011 276 | ------------------------- 277 | Changed the library significantly yet again in favor of a more modular approach based on CodeIgniter's driver object/class schema. 278 | 279 | 280 | This also made some headway to implement a Third Party API framework. Developers can now add an API that is easily distinguishable and manageable. This API is designed to interact directly with modules programmatically. 281 | 282 | 283 | Version 0.2.0 - 10/25/2011 284 | -------------------------- 285 | Completely rewrote the Channel Data API in favor a more polymorphic solution. The original API has been deprecated. This project is still clearly very beta. 286 | 287 | 288 | Version 0.1.0 - 10/07/2011 289 | -------------------------- 290 | Initial beta release. Here goes nothing... 291 | 292 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Channel Data 2 | 3 | ##### Version 1.0-rc2 (2013-12-16) 4 | 5 | Created By [Objective HTML](https://objectivehtml.com) 6 | 7 | --- 8 | 9 | ## Table of Contents 10 | 11 | 1. [Overview](#overview) 12 | 2. [System Requirements](#system-requirements) 13 | 3. [Getting Started](#getting-started) 14 | 4. [QueryBuilder](#querybuilder) 15 | 4. [QueryResponse](#queryresponse) 16 | 5. [QueryString](#querystring) 17 | 5. [Collections](#collections) 18 | 6. [Models](#models) 19 | 6. [Channel Models](#channel-models) 20 | 21 | --- 22 | 23 | ## Overview 24 | 25 | Channel Data was created to provide a universal and abstract set of models for you to use within your [ExpressionEngine](http://ellislab.com/expressionengine) applications and addons. Channel Data is now based on the Eloquent ORM, so the syntax should be familiar to those that have used it. 26 | 27 | Why didn't we just port Eloquent to ExpressionEngine? Others have done so, and it's definitely possible. However, after a lot of consideration, it was decided to rewrite the code from scratch specifically for ExpressionEngine. This will make it easier to integrate Channel Data into existing applications and maintain the codebase as ExpressionEngine evolves. 28 | 29 | --- 30 | 31 | ## System Requirements 32 | 33 | PHP 5.3+ 34 | 35 | ExpressionEngine 2.4+ 36 | 37 | *(Earlier versions of ExpressionEngine may work, but are untested)* 38 | 39 | --- 40 | 41 | ## Getting Started 42 | 43 | To get started using Channel Data, you need to copy `channel_data` into your `system/expressionengine/third_party` directory. Channel Data is packages as its own *module* so you an reuse the same libary with all of your add-ons. This is also convenient when you upgrade ExpressionEngine since you don't have to worry about override files stored in the system directories. 44 | 45 | Channel Data includes some core modules for you to use. Core models belong to the `ChannelData\Model` namespace, and can be reused within your application. You can create your own models using the following structure: 46 | 47 | 48 | ##### Instantiate Channel Data 49 | 50 | The key thing to note when instantiating Channel Data is that you need to do 3 things. 51 | 52 | /** 53 | * Required Steps 54 | * 55 | * 1. Load the Channel Data package into your add-on 56 | * 2. Load the Channel Data driver from the package 57 | * 3. Tell Channel Data where the auto loader should look for your files. 58 | **/ 59 | 60 | ee()->load->add_package_path(PATH_THIRD . 'your_addon_name'); 61 | 62 | // Load the driver and directories at once 63 | ee()->load->driver('ChannelData', array( 64 | 'directories' => array( 65 | PATH_THIRD . 'your_addon_name/models' 66 | ) 67 | )); 68 | 69 | // Or use the autoload() method to pass a directory path 70 | ee()->channeldata->autoload(PATH_THIRD . 'your_addon_name/models'); 71 | 72 | // You can also pass an array of directories 73 | ee()->channeldata->autoload(array( 74 | PATH_THIRD . 'your_addon_name/models', 75 | PATH_THIRD . 'your_addon_name/models/channels' 76 | )); 77 | 78 | 79 | *Note, Channel Data is a CodeIgniter driver, not a library. You must load it using the `driver` method.* 80 | 81 | ---- 82 | 83 | ## QueryBuilder 84 | 85 | QueryBuilder is a standalone class that provides a clean syntax for building SQL statements based on the Eloquent ORM. QueryBuilder can be used as a standalone class, or within the [Models](#models) themselves. 86 | 87 | ### Instantiate 88 | 89 | $builder = new QueryBuilder(); 90 | 91 | ### Response 92 | 93 | After you are finished building your query, you need to instantiate a `QueryResponse` object by running the `get()` method. 94 | 95 | $response = $builder->get(); 96 | 97 | Or you can skip the response and just grab the results. If a model has been defined, a `Collection` will be returned. Otherwise, an array of standard objects will be returned. 98 | 99 | $response = $builder->result(); 100 | 101 | ### Select 102 | 103 | // Select all 104 | $builder->select('*'); 105 | 106 | // Select columns from a specific table 107 | $builder->select('members.member_id'); 108 | 109 | // Select multiple columns with an array 110 | $builder->select(array('username', 'email', 'screen_name')); 111 | 112 | // Select columns with an alias 113 | $builder->select('members.email', 'email_address'); 114 | 115 | // Select columns with a closure 116 | $builder->select(function($table) { 117 | $table->select('email'); 118 | $table->select('username'); 119 | }); 120 | 121 | // Select data using a raw query string 122 | $builder->select(QueryString::raw('`username` as \'user\'')); 123 | 124 | ### From 125 | 126 | // Specify a table name 127 | $builder->from('members'); 128 | 129 | // Specify data using a raw query string 130 | $builder->select(QueryString::raw('`exp_members` as \'member\'')); 131 | 132 | ### Where 133 | 134 | // A basic conditional with operator 135 | $builder->where('username', '=', 'Justin'); 136 | 137 | // A basic conditional with out operator 138 | $builder->where('username', 'Justin'); 139 | 140 | // Add an "OR" conditional 141 | $builder->orWhere('username', 'Justin'); 142 | 143 | // Add an "and" conditional (this is an alias to where()) 144 | $builder->andWhere('username', 'Justin'); 145 | 146 | // Perform a "WHERE IN" conditional against an array 147 | $builder->whereIn('member_is', array(1, 2, 3)); 148 | $builder->andWhereIn('member_is', array(1, 2, 3)); 149 | $builder->orWhereIn('member_is', array(1, 2, 3)); 150 | 151 | // Perform nested conditionals with a closure 152 | $builder->where(function($table) { 153 | $table->where('screen_name', 'Justin Kimbrell'); 154 | $table->orWhere('screen_name', 'Objective HTML'); 155 | }); 156 | 157 | ### Having 158 | 159 | // A basic conditional with operator 160 | $builder->having('username', '=', 'Justin'); 161 | 162 | // A basic conditional with out operator 163 | $builder->having('username', 'Justin'); 164 | 165 | // Add an "OR" conditional 166 | $builder->orHaving('username', 'Justin'); 167 | 168 | // Add an "and" conditional (this is an alias to where()) 169 | $builder->andHaving('username', 'Justin'); 170 | 171 | // Perform a "WHERE IN" conditional against an array 172 | $builder->havingIn('member_is', array(1, 2, 3)); 173 | $builder->andHavingIn('member_is', array(1, 2, 3)); 174 | $builder->orHavingIn('member_is', array(1, 2, 3)); 175 | 176 | // Perform nested conditionals with a closure 177 | $builder->having(function($table) { 178 | $table->having('screen_name', 'Justin Kimbrell'); 179 | $table->orHaving('screen_name', 'Objective HTML'); 180 | }); 181 | 182 | ### Join 183 | 184 | // Basic 185 | $builder->join('table2', 'table1.id', '=', 'table2.id'); 186 | 187 | // Left 188 | $builder->leftJoin('table2', 'table1.id', '=', 'table2.id'); 189 | 190 | // Right 191 | $builder->rightJoin('table2', 'table1.id', '=', 'table2.id'); 192 | 193 | // Outer 194 | $builder->outerJoin('table2', 'table1.id', '=', 'table2.id'); 195 | 196 | // Inner 197 | $builder->innerJoin('table2', 'table1.id', '=', 'table2.id'); 198 | 199 | // Raw String 200 | $builder->join(QueryString::raw('table2 ON table1.id = table2.id')); 201 | 202 | ### Order By 203 | 204 | // Basic 205 | $builder->orderBy('id', 'asc') 206 | 207 | // Raw String 208 | $builder->orderBy(QueryString::raw('id ASC')); 209 | 210 | ### Sort 211 | 212 | $builder->sort('ASC'); 213 | 214 | ### Limit 215 | 216 | // Limit with offset at 0 217 | $builder->limit(10); 218 | 219 | // Limit with offset at 10 220 | $builder->limit(10, 10); 221 | 222 | ### Offset 223 | 224 | $builder->offset(5); 225 | 226 | ---- 227 | 228 | ## QueryResponse 229 | 230 | `QueryResponse` is a class that is instantiated when the `get` method is ran on the `QueryResponse` object. 231 | 232 | ### count() 233 | 234 | Returns the total number of items in the response 235 | 236 | $response = $builder->get(); 237 | $response->count(); 238 | 239 | ### each() 240 | 241 | This method loops through the entire collection and passes each item to a closure. 242 | 243 | $response = $builder->get(); 244 | 245 | $response->each(function($i, $row) { 246 | $row->some_field = 'Some new value'; 247 | }); 248 | 249 | ### first() 250 | 251 | This method returns the first row in the result array 252 | 253 | $response = $builder->get(); 254 | 255 | $row = $response->first(); 256 | 257 | ### last() 258 | 259 | This method returns the last row in the result array 260 | 261 | $response = $builder->get(); 262 | 263 | $row = $response->last(); 264 | 265 | ### index() 266 | 267 | This method returns a row in the result by index, or if no index is exists, NULL will be returned. 268 | 269 | $response = $builder->get(); 270 | 271 | $row = $response->index(2); 272 | 273 | ### next() 274 | 275 | This method returns the next row in the result set. 276 | 277 | $response = $builder->get(); 278 | 279 | $row = $response->next(); 280 | 281 | ### prev() 282 | 283 | This method returns the previous row in the result set. 284 | 285 | $response = $builder->get(); 286 | 287 | $row = $response->next(); 288 | 289 | ### result() 290 | 291 | This method returns the result array 292 | 293 | $response = $builder->get(); 294 | 295 | $row = $response->result(); 296 | 297 | ### row() 298 | 299 | This method returns the first row in the result array 300 | 301 | $response = $builder->get(); 302 | 303 | $row = $response->row(); 304 | 305 | 306 | ---- 307 | 308 | ## QueryString 309 | 310 | `QueryString` is a class that can be passed into any parameter that will output a raw string. `QueryString` also has a number of static helper methods to manipulate strings for common uses within SQL. 311 | 312 | ### Instantiate 313 | 314 | $rawString = new QueryString('This is a raw string'); 315 | 316 | var_dump((string) $rawString); 317 | 318 | ### QueryString::protect($str, $table = FALSE) 319 | 320 | This method will attempt to protect strings from SQL syntax and formatting errors. It will encapsulate table and field names with backticks. 321 | 322 | // Returns `field` 323 | QueryString::protect('field'); 324 | 325 | // Returns `exp_table`.`field` 326 | QueryString::protect('field', 'table'); 327 | 328 | // Returns `exp_table`.`field` 329 | QueryString::protect('table.field'); 330 | 331 | ### QueryString::raw($str) 332 | 333 | This method will instantiate a QueryString object. 334 | 335 | // Returns QueryString object 336 | QueryString::raw('This is a test'); 337 | 338 | 339 | ### QueryString::table($str) 340 | 341 | This method will convert a string into a properly prefixed table name. 342 | 343 | // Returns 'exp_table_name' 344 | QueryString::table('table_name'); 345 | 346 | 347 | ### QueryString::strip($str) 348 | 349 | This method will strip unnecessary formatting from strings. It's important to note, this will also strip numeric prefixes that can be used in indexes within arrays (to make them unique). 350 | 351 | // Returns 'table_name' 352 | QueryString::strip('`table_name`'); 353 | 354 | // Returns 'table_name' 355 | QueryString::strip('{1} `table_name`'); 356 | 357 | // Returns 'table_name' 358 | QueryString::strip('{2} `table_name`'); 359 | 360 | 361 | ### QueryString::clean($str) 362 | 363 | This method will trim and clean excess conditional keywords from strings 364 | 365 | // Returns 'field1 OR field2' 366 | QueryString::clean(' AND field1 OR field2 '); 367 | 368 | --- 369 | 370 | ## Collections 371 | 372 | When a model processes QueryBuilder objects, it will take those results and instantiate the respected objects and pass an array of items to the `Collection` class. 373 | 374 | ### each($closure) 375 | 376 | This method loops through the entire collection and passes each item to a closure. 377 | 378 | $members = Member::all(); 379 | 380 | $members->each(function($i, Member $member) { 381 | $member->some_field = 'Some new value'; 382 | $member->save(); 383 | }); 384 | 385 | ### items() 386 | 387 | This method returns an array of instantiated model objects. 388 | 389 | $members = Member::all(); 390 | 391 | foreach($members->$items() as $i => $member) 392 | { 393 | $member->some_field = 'Some new value'; 394 | $member->save(); 395 | } 396 | 397 | ### first() 398 | 399 | This method returns the first model in the collection. 400 | 401 | $members = Member::all(); 402 | 403 | $member = $members->first() 404 | 405 | ### last() 406 | 407 | This method returns the last model in the collection. 408 | 409 | $members = Member::all(); 410 | 411 | $member = $members->last() 412 | 413 | ### get($index = FALSE, $default = NULL) 414 | 415 | This method returns an item in the collection by index, or if no index is exists, all items will be returned. 416 | 417 | $member = Member::all()->get(2); 418 | $member = Member::all()->get(12, 'some default value'); 419 | 420 | ### count() 421 | 422 | Returns the total number of items in the collection 423 | 424 | $count = Member::all()->count(); 425 | 426 | ---- 427 | 428 | ## Models 429 | 430 | Models are really the key component behind Channel Data. Each model is assigned to a database table and comes complete with a full CRUD controller. Models can be instantiated and be accessed statically. All models should extend the `BaseModel` class, and are located in the `models` directory within `ChannelData`, within the `models` directory inside your add-on, or in the global `models` directory. 431 | 432 | where(...); 521 | 522 | ### MyModel::all() 523 | 524 | Return all the results in the model 525 | 526 | $members = Member::all(); 527 | 528 | ### MyModel::find($id) 529 | 530 | Find a model by ID 531 | 532 | $members = Member::find(1); 533 | 534 | ### MyModel::findByUid($id) 535 | 536 | Find a model by UID. The `uidField` inmust be defined in your model class to use this method. 537 | 538 | $members = Member::findByUid('ak20f-2dajd-2adawwad-zjadafj3'); 539 | 540 | ### MyModel::query() 541 | 542 | Instantiate a `QueryBuilder` object. 543 | 544 | $query = Member::query()->where(...); 545 | 546 | ### MyModel::table() 547 | 548 | Return the table that is being searched 549 | 550 | $table = Member::table(); 551 | 552 | ##### Instance Methods 553 | 554 | ### id() 555 | 556 | Returns the id of the model 557 | 558 | $memberId = $member->id(); 559 | 560 | ### uid() 561 | 562 | Returns the uid of the model. This field required the `uidField` property to be set in the model. 563 | 564 | $memberId = $member->id(); 565 | 566 | ### getAttributes() 567 | 568 | Returns all the attributes for the model. 569 | 570 | $attributes = $member->getAttributes(); 571 | 572 | ### getAttribute($name) 573 | 574 | Returns a single the attributes for the model. 575 | 576 | $attribute = $member->getAttribute('username'); 577 | 578 | ### setAttributes($data) 579 | 580 | Sets an array of attributes. Ignores the security filters. 581 | 582 | $member->setAttributes(array( 583 | 'username' => 'Justin Kimbre', 584 | 'company' => 'Objective HTML' 585 | )); 586 | 587 | ### setAttribute($prop, $value) 588 | 589 | Sets an single attribute. Ignores the security filters. 590 | 591 | $member->setAttributes('company', 'Objective HTML'); 592 | 593 | ### fill($data = array()) 594 | 595 | Fill the model with an array data. Respects the security filters. 596 | 597 | $member->fill(array) 598 | 599 | ### save($data = array()) 600 | 601 | Save the model data. If an array is passed, the model data is passed to the `fill` method. 602 | 603 | $member->save(); 604 | 605 | ### update($data = array()) 606 | 607 | Update the model data. If an array is passed, the model data is passed to the `fill` method. 608 | 609 | $member->update(); 610 | 611 | ### delete() 612 | 613 | Delete the model. 614 | 615 | $member->delete(); 616 | 617 | ### toArray() 618 | 619 | Output the model as an associative array 620 | 621 | $member->toArray(); 622 | 623 | ### toJson() 624 | 625 | Output the model as a JSON string 626 | 627 | $member->toJson(); 628 | 629 | ---- 630 | 631 | ## Channel Models 632 | 633 | Channel Models extend the `BaseModel` class and are specifically built to work with Channel Entries. 634 | 635 | field_name 667 | 668 | 5 => 'your_field_name' 669 | ); 670 | 671 | 672 | ##### Instance Methods 673 | 674 | #### getErrors() 675 | 676 | Get the array of errors in the `$errors` property (which is protected). 677 | 678 | 679 | ##### Static Methods 680 | 681 | #### MyModel::findByUrlTitle() 682 | 683 | Get the entry by the `url_title`. 684 | 685 | 686 | #### MyModel::channelId() 687 | 688 | Get the `channel_id` of the model. -------------------------------------------------------------------------------- /channel_data/libraries/Channeldata/base/BaseModel.php: -------------------------------------------------------------------------------- 1 | columns() as $column) 35 | { 36 | if(!property_exists($this, $column)) 37 | { 38 | $this->$column = NULL; 39 | } 40 | } 41 | 42 | $this->fill($data); 43 | 44 | if($setId && isset($data->{$this->idField})) 45 | { 46 | if($this->idField) 47 | { 48 | $this->setAttribute($this->idField, $data->{$this->idField}); 49 | } 50 | 51 | 52 | if($this->uidField && isset($data->{$this->uidField})) 53 | { 54 | $this->setAttribute($this->uidField, $data->{$this->uidField}); 55 | } 56 | } 57 | 58 | if($this->getAttribute($this->idField)) 59 | { 60 | $this->exists = TRUE; 61 | } 62 | else 63 | { 64 | $this->setAttribute($this->uidField, md5(uniqid())); 65 | } 66 | } 67 | 68 | public function __call($method, $args) 69 | { 70 | $prefix = $this->prefix ? $this->prefix : NULL; 71 | 72 | if(isset($this->{$prefix.$method})) 73 | { 74 | return $this->{$prefix.$method}; 75 | } 76 | 77 | throw new \Exception('"'.$method.'" is not a valid method', 1); 78 | 79 | return NULL; 80 | } 81 | 82 | public function __get($property) 83 | { 84 | if (property_exists($this, $property)) 85 | { 86 | return $this->$property; 87 | } 88 | else 89 | { 90 | $class = self::caller(); 91 | 92 | throw new \Exception("The {$property} property does not exist within the {$class} class."); 93 | } 94 | } 95 | 96 | public function fill($data) 97 | { 98 | if(is_object($data)) 99 | { 100 | $data = (array) $data; 101 | } 102 | 103 | if(is_array($data) && count($data) > 0) 104 | { 105 | foreach($data as $index => $value) 106 | { 107 | if($this->prefix && property_exists($this, $this->prefix.$index)) 108 | { 109 | $index = $this->prefix.$index; 110 | } 111 | 112 | if( in_array($index, $this->fillable) || 113 | in_array($index, $this->required)) 114 | { 115 | $this->setAttribute($index, $value); 116 | } 117 | } 118 | } 119 | } 120 | 121 | public function save($data = FALSE) 122 | { 123 | if($data) 124 | { 125 | $this->fill($data); 126 | } 127 | 128 | if(!$this->exists) 129 | { 130 | return $this->_createRecord($data); 131 | } 132 | else 133 | { 134 | return $this->_updateRecord($data); 135 | } 136 | } 137 | 138 | public function toArray() 139 | { 140 | $array = array(); 141 | 142 | foreach($this->columns() as $index) 143 | { 144 | if(!in_array($index, $this->hidden)) 145 | { 146 | $array[$index] = $this->getAttribute($index); 147 | } 148 | } 149 | 150 | return $array; 151 | } 152 | 153 | public function toJson() 154 | { 155 | return json_encode($this->toArray()); 156 | } 157 | 158 | public function update($array = FALSE) 159 | { 160 | if($array) 161 | { 162 | $this->fill($array); 163 | } 164 | 165 | return $this->save(); 166 | } 167 | 168 | public function delete() 169 | { 170 | if($this->exists) 171 | { 172 | ee()->db->where($this->idField, $this->id()); 173 | ee()->db->delete($this->table); 174 | 175 | $this->exists = FALSE; 176 | $this->deleted = TRUE; 177 | } 178 | 179 | return $this; 180 | } 181 | 182 | public function getAttributes() 183 | { 184 | $return = array(); 185 | 186 | foreach($this as $prop => $index) 187 | { 188 | if(property_exists($this, $prop)) 189 | { 190 | $return[$prop] = $this->getAttribute($prop); 191 | } 192 | } 193 | 194 | return $return; 195 | } 196 | 197 | public function getAttribute($name) 198 | { 199 | if(property_exists($this, $name)) 200 | { 201 | return $this->$name; 202 | } 203 | 204 | return NULL; 205 | } 206 | 207 | public function setAttributes($data) 208 | { 209 | foreach($data as $index => $value) 210 | { 211 | $this->setAttribute($index, $value); 212 | } 213 | } 214 | 215 | public function setAttribute($prop, $value) 216 | { 217 | if(!empty($prop)) 218 | { 219 | $this->$prop = $value; 220 | } 221 | } 222 | 223 | protected function _createRecord($data = array()) 224 | { 225 | if(count($data)) 226 | { 227 | $this->fill($data); 228 | } 229 | 230 | $data = $this->data(); 231 | 232 | if($this->uidField) 233 | { 234 | $data[$this->uidField] = md5(uniqid()); 235 | } 236 | 237 | ee()->db->insert($this->table, $data); 238 | 239 | $this->exists = TRUE; 240 | $this->setAttribute($this->idField, ee()->db->insert_id()); 241 | 242 | return $this; 243 | } 244 | 245 | protected function _updateRecord($data = array()) 246 | { 247 | if(count($data)) 248 | { 249 | $this->fill($data); 250 | } 251 | 252 | ee()->db->where($this->idField, $this->id()); 253 | ee()->db->update($this->table, $this->data()); 254 | 255 | return $this; 256 | } 257 | 258 | public function id() 259 | { 260 | if($id = $this->{$this->idField}) 261 | { 262 | return $id; 263 | } 264 | 265 | return NULL; 266 | } 267 | 268 | public function uid() 269 | { 270 | if(property_exists($this, 'uidField')) 271 | { 272 | $uid = $this->{$this->uidField}; 273 | 274 | if($uid !== NULL) 275 | { 276 | return $uid; 277 | } 278 | } 279 | 280 | return NULL; 281 | } 282 | 283 | public function data() 284 | { 285 | $data = array(); 286 | 287 | foreach($this->columns() as $field) 288 | { 289 | $value = $this->getAttribute($field); 290 | 291 | if($value !== NULL && !in_array($field, $this->guarded)) 292 | { 293 | $data[$field] = $value; 294 | } 295 | } 296 | 297 | return $data; 298 | } 299 | 300 | public function columns() 301 | { 302 | if($this->columns) 303 | { 304 | return $this->columns; 305 | } 306 | 307 | return $this->columns = ee()->db->list_fields($this->table); 308 | } 309 | 310 | public static function create($array) 311 | { 312 | $class = get_called_class(); 313 | $obj = new $class($array); 314 | 315 | $obj->save(); 316 | 317 | return $obj; 318 | } 319 | 320 | public static function find($id) 321 | { 322 | $class = self::caller(); 323 | $obj = self::instantiate(); 324 | 325 | return $class::where($obj->table.'.'.$obj->idField, $id)->get()->first(); 326 | } 327 | 328 | public static function findByUid($uid) 329 | { 330 | $class = self::caller(); 331 | $obj = self::instantiate(); 332 | 333 | return $class::where($obj->uidField, $uid)->get()->first(); 334 | } 335 | 336 | public static function all() 337 | { 338 | $class = self::caller(); 339 | 340 | return $class::query()->result(); 341 | } 342 | 343 | public static function select() 344 | { 345 | $class = self::caller(); 346 | 347 | return $class::call($class::query(), 'select', func_get_args()); 348 | } 349 | 350 | public static function where($subject, $operator = NULL, $value = NULL, $concat = 'AND') 351 | { 352 | $class = self::caller(); 353 | 354 | return $class::query()->where($subject, $operator, $value, $concat); 355 | } 356 | 357 | public static function whereIn($subject, $value = NULL) 358 | { 359 | $class = self::caller(); 360 | 361 | return $class::query()->whereIn($subject, $value); 362 | } 363 | 364 | public static function orWhereIn($subject, $value = NULL) 365 | { 366 | $class = self::caller(); 367 | 368 | return $class::query()->orWhereIn($subject, $value); 369 | } 370 | 371 | public static function andWhereIn($subject, $value = NULL) 372 | { 373 | $class = self::caller(); 374 | 375 | return $class::query()->andWhereIn($subject, $value); 376 | } 377 | 378 | public static function orWhere($subject, $operator = NULL, $value = NULL) 379 | { 380 | $class = self::caller(); 381 | 382 | return $class::where($subject, $operator, $value, 'OR'); 383 | } 384 | 385 | public static function andWhere($subject, $operator = NULL, $value = NULL) 386 | { 387 | $class = self::caller(); 388 | 389 | return $class::where($subject, $operator, $value, 'AND'); 390 | } 391 | 392 | public static function having($subject, $operator = NULL, $value = NULL, $concat = 'AND') 393 | { 394 | $class = self::caller(); 395 | 396 | return $class::query()->having($subject, $operator, $value, $concat); 397 | } 398 | 399 | public static function orHaving($subject, $operator = NULL, $value = NULL) 400 | { 401 | $class = self::caller(); 402 | 403 | return $class::having($subject, $operator, $value, 'OR'); 404 | } 405 | 406 | public static function andHaving($subject, $operator = NULL, $value = NULL) 407 | { 408 | $class = self::caller(); 409 | 410 | return $class::having($subject, $operator, $value, 'AND'); 411 | } 412 | 413 | public static function call($obj, $method, $args = array()) 414 | { 415 | return call_user_func_array(array($obj, $method), $args); 416 | } 417 | 418 | public static function query() 419 | { 420 | $class = self::instantiate(); 421 | 422 | $query = new QueryBuilder(); 423 | $query->model = get_class($class); 424 | 425 | $query->from($class::table()); 426 | $query->select('*'); 427 | 428 | return $query; 429 | } 430 | 431 | public static function init($result) 432 | { 433 | $class = self::caller(); 434 | 435 | if($result->num_rows() == 0) 436 | { 437 | return NULL; 438 | } 439 | 440 | $return = new $class(); 441 | $return->exists = TRUE; 442 | $return->setAttributes($result->row()); 443 | 444 | return $return; 445 | } 446 | 447 | public static function table() 448 | { 449 | $class = self::caller(); 450 | 451 | return $class::instantiate()->table; 452 | } 453 | 454 | public static function caller() 455 | { 456 | return get_called_class(); 457 | } 458 | 459 | public static function instantiate() 460 | { 461 | $class = self::caller(); 462 | 463 | return new $class(); 464 | } 465 | } -------------------------------------------------------------------------------- /channel_data/libraries/Channeldata/base/ChannelModel.php: -------------------------------------------------------------------------------- 1 | lang->loadfile('content'); 70 | 71 | $this->uidField = $this->prefix.'uid'; 72 | $this->required[] = $this->prefix.'uid'; 73 | 74 | $this->fillable = array_merge($this->fillable, $this->fields()); 75 | 76 | parent::__construct($data); 77 | } 78 | 79 | public function __get($property) 80 | { 81 | if(property_exists($this, $this->prefix.$property)) 82 | { 83 | return $this->{$this->prefix.$property}; 84 | } 85 | 86 | throw new \Exception("Invalid property \'".$property."\'", 1); 87 | } 88 | 89 | public function __set($property, $value) 90 | { 91 | if(property_exists($this, $this->prefix.$property)) 92 | { 93 | $property = $this->prefix.$property; 94 | } 95 | 96 | $this->$property = $value; 97 | 98 | if($property == 'title') 99 | { 100 | $this->url_title = QueryString::url_title(strtolower($this->title)); 101 | } 102 | } 103 | 104 | public function getErrors() 105 | { 106 | return $this->errors; 107 | } 108 | 109 | public function hasErrors() 110 | { 111 | return count($this->errors) ? TRUE : FALSE; 112 | } 113 | 114 | public function channel() 115 | { 116 | if(!$this->channel) 117 | { 118 | return FALSE; 119 | } 120 | 121 | $channel = Channel::findByName($this->channel); 122 | 123 | if(!$channel) 124 | { 125 | show_error('The '.$this->channel.' id set in the config is incorrect'); 126 | } 127 | 128 | return $channel; 129 | } 130 | 131 | public function delete() 132 | { 133 | if($this->exists) 134 | { 135 | ee()->load->library('api'); 136 | ee()->api->instantiate('channel_entries'); 137 | ee()->api_channel_entries->delete_entry(array($this->entry_id)); 138 | 139 | $this->deleted = TRUE; 140 | $this->exists = FALSE; 141 | } 142 | 143 | return $this; 144 | } 145 | 146 | protected function _createRecord($data = array()) 147 | { 148 | if(count($data)) 149 | { 150 | $this->fill($data); 151 | } 152 | 153 | $this->apiResponse = ChannelEntriesApi::submit_entry($this->channel()->channel_id, $this->data()); 154 | $this->setAttribute($this->idField, $this->apiResponse); 155 | 156 | if(!is_int($this->apiResponse)) 157 | { 158 | $this->errors = $this->apiResponse; 159 | } 160 | else 161 | { 162 | $this->exists = TRUE; 163 | } 164 | 165 | return $this; 166 | } 167 | 168 | protected function _updateRecord($data) 169 | { 170 | if(count($data)) 171 | { 172 | $this->fill($data); 173 | } 174 | 175 | $this->apiResponse = ChannelEntriesApi::update_entry($this->channel_id, $this->entry_id, $this->data()); 176 | 177 | if(!is_int($this->apiResponse)) 178 | { 179 | $this->errors = $this->apiResponse; 180 | } 181 | 182 | return $this; 183 | } 184 | 185 | public function data() 186 | { 187 | $channel = Channel::findByName($this->channel); 188 | 189 | $data = parent::data(); 190 | 191 | foreach($channel->fields()->items() as $row) 192 | { 193 | if(isset($data[$row->field_name]) && $value = $data[$row->field_name]) 194 | { 195 | unset($data[$row->field_name]); 196 | } 197 | else 198 | { 199 | $value = NULL; 200 | } 201 | 202 | $data['field_id_'.$row->field_id] = $value; 203 | $data['field_ft_'.$row->field_id] = $row->field_fmt; 204 | } 205 | 206 | return $data; 207 | } 208 | 209 | public function columns() 210 | { 211 | return array_merge( 212 | ee()->db->list_fields('channel_titles'), 213 | $this->fields() 214 | ); 215 | } 216 | 217 | public function fields() 218 | { 219 | if($this->fields) 220 | { 221 | return $this->fields; 222 | } 223 | 224 | if($channel = $this->channel()) 225 | { 226 | foreach($channel->fields()->items() as $field) 227 | { 228 | $this->fields[$field->field_id] = $field->field_name; 229 | } 230 | } 231 | else 232 | { 233 | foreach(ChannelField::all()->items() as $field) 234 | { 235 | $this->fields[$field->field_id] = $field->field_name; 236 | } 237 | } 238 | 239 | return $this->fields; 240 | } 241 | 242 | public static function findOpen($entry_id) 243 | { 244 | return self::where('channel_data.entry_id', '=', $entry_id) 245 | ->where('status', '=', 'open') 246 | ->get() 247 | ->first(); 248 | } 249 | 250 | public static function findByAuthorId($author_id) 251 | { 252 | return self::where('author_id', '=', $author_id)->get(); 253 | } 254 | 255 | public static function findByUrlTitle($urlTitle) 256 | { 257 | if($urlTitle === FALSE) 258 | { 259 | return NULL; 260 | } 261 | 262 | return self::where('url_title', '=', $urlTitle)->get()->first(); 263 | } 264 | 265 | public static function channelId() 266 | { 267 | $class = new static; 268 | 269 | if(!$class->channel) 270 | { 271 | return FALSE; 272 | } 273 | 274 | return Channel::findByName($class->channel)->id(); 275 | } 276 | 277 | public static function table() 278 | { 279 | return 'channel_titles'; 280 | } 281 | 282 | public static function query() 283 | { 284 | $class = new static; 285 | 286 | $query = new ChannelQueryBuilder(); 287 | $query->model = get_class($class); 288 | 289 | $query->from('channel_titles'); 290 | $query->leftJoin('channel_data', 'channel_titles.entry_id', '=', 'channel_data.entry_id'); 291 | $query->select('*', NULL, 'channel_titles'); 292 | 293 | foreach($class->fields() as $field_id => $field_name) 294 | { 295 | $query->select('field_id_'.$field_id, $field_name, 'channel_data'); 296 | } 297 | 298 | if($class->channelId()) 299 | { 300 | $query->where('channel_data.channel_id', '=', $class->channelId()); 301 | } 302 | 303 | return $query; 304 | } 305 | 306 | public function entries() 307 | { 308 | $parser = new ChannelEntriesParser(); 309 | 310 | return $parser->entries(array( 311 | 'entry_id' => $this->id() 312 | )); 313 | } 314 | } 315 | -------------------------------------------------------------------------------- /channel_data/libraries/Channeldata/channeldata.php: -------------------------------------------------------------------------------- 1 | channeldata)) 41 | { 42 | foreach(ee()->channeldata->directories() as $directory) 43 | { 44 | $filePath = $directory . '/' . $fileName; 45 | 46 | if(file_exists($filePath)) 47 | { 48 | require_once($filePath); 49 | } 50 | } 51 | } 52 | } 53 | 54 | } 55 | 56 | if(!function_exists('is_closure')) 57 | { 58 | function is_closure($t) 59 | { 60 | return is_object($t) && ($t instanceof Closure); 61 | } 62 | } 63 | 64 | /** 65 | * ChannelData CodeIgniter Driver 66 | * 67 | * Dummy class to trigger autoloading, and give access to helper methods 68 | * 69 | * @return void 70 | */ 71 | 72 | 73 | use ChannelData\Model\Channel; 74 | use ChannelData\Model\ChannelField; 75 | 76 | class ChannelData { 77 | 78 | protected $directories = array(); 79 | 80 | public function __construct($data = array()) 81 | { 82 | foreach($data as $index => $value) 83 | { 84 | $this->$index = $value; 85 | } 86 | } 87 | 88 | public function autoload($file) 89 | { 90 | if(!is_array($file)) 91 | { 92 | $file = array($file); 93 | } 94 | 95 | $this->directories[] = $file; 96 | } 97 | 98 | public function directories() 99 | { 100 | if(!is_array($this->directories)) 101 | { 102 | $this->directories = array($this->directories); 103 | } 104 | 105 | return $this->directories; 106 | } 107 | 108 | public static function prefix($prefix, $data, $delimeter = ':') 109 | { 110 | $new_data = array(); 111 | 112 | if(!empty($prefix)) 113 | { 114 | foreach($data as $data_index => $data_value) 115 | { 116 | if(is_array($data_value) && preg_match('/\d/', $data_index)) 117 | { 118 | if(isset($data_value[0]) && !is_array($data_value[0])) 119 | { 120 | $new_row = array(); 121 | 122 | foreach($data_value as $inner_index => $inner_value) 123 | { 124 | $new_row[$prefix . $delimeter . $inner_index] = $inner_value; 125 | } 126 | 127 | $new_data[$data_index] = $new_row; 128 | } 129 | else 130 | { 131 | $new_data[$data_index] = self::prefix($prefix, $data_value, $delimeter); 132 | } 133 | 134 | } 135 | else 136 | { 137 | $new_data[$prefix . $delimeter . $data_index] = $data_value; 138 | } 139 | } 140 | } 141 | else 142 | { 143 | $new_data = $data; 144 | } 145 | 146 | return $new_data; 147 | } 148 | } -------------------------------------------------------------------------------- /channel_data/libraries/Channeldata/components/ChannelCollection.php: -------------------------------------------------------------------------------- 1 | response->entries(); 8 | } 9 | 10 | } -------------------------------------------------------------------------------- /channel_data/libraries/Channeldata/components/ChannelEntriesApi.php: -------------------------------------------------------------------------------- 1 | load->library('api'); 16 | ee()->api->instantiate('channel_entries'); 17 | ee()->api->instantiate('channel_fields'); 18 | 19 | ee()->session->userdata['group_id'] = 1; 20 | 21 | ee()->api_channel_fields->setup_entry_settings($channel_id, $data); 22 | 23 | ee()->api_channel_entries->submit_new_entry($channel_id, $data); 24 | 25 | if(count(ee()->api_channel_entries->errors) > 0) 26 | { 27 | return ee()->api_channel_entries->errors; 28 | } 29 | 30 | return ee()->api_channel_entries->entry_id; 31 | } 32 | 33 | /** 34 | * Updates an entry using the channel entries API 35 | * 36 | * @access public 37 | * @param mixed The channel id 38 | * @param mixed The entry id 39 | * @param array The entry data 40 | * @return int 41 | */ 42 | public static function update_entry($channel_id, $entry_id, $data) 43 | { 44 | ee()->load->library('api'); 45 | ee()->api->instantiate('channel_entries'); 46 | ee()->api->instantiate('channel_fields'); 47 | 48 | $data['entry_id'] = $entry_id; 49 | $data['channel_id'] = $channel_id; 50 | 51 | ee()->session->userdata['group_id'] = 1; 52 | 53 | ee()->api_channel_fields->setup_entry_settings($channel_id, $data); 54 | 55 | ee()->api_channel_entries->update_entry($entry_id, $data); 56 | 57 | if(count(ee()->api_channel_entries->errors) > 0) 58 | { 59 | return ee()->api_channel_entries->errors; 60 | } 61 | 62 | return TRUE; 63 | } 64 | } -------------------------------------------------------------------------------- /channel_data/libraries/Channeldata/components/ChannelEntriesParser.php: -------------------------------------------------------------------------------- 1 | TMPL->no_results = $tagdata; 10 | } 11 | 12 | public function cache_no_results() 13 | { 14 | ee()->session->set_cache('entries_lib', 'no_results', ee()->TMPL->no_results); 15 | } 16 | 17 | public function reset_no_results($cache = TRUE) 18 | { 19 | if($cache) 20 | { 21 | $this->cache_no_results(); 22 | } 23 | 24 | ee()->TMPL->no_results = NULL; 25 | } 26 | 27 | public function restore_no_results() 28 | { 29 | if(isset(ee()->session->cache['entries_lib']['no_results'])) 30 | { 31 | $this->reset_no_results(FALSE); 32 | $this->set_no_results(ee()->session->cache['entries_lib']['no_results']); 33 | } 34 | 35 | ee()->session->set_cache('entries_lib', 'no_results', array()); 36 | 37 | return $this->get_params(); 38 | } 39 | 40 | public function no_results() 41 | { 42 | return $this->get_no_results(); 43 | } 44 | 45 | public function get_no_results() 46 | { 47 | return ee()->TMPL->no_results; 48 | } 49 | 50 | public function set_param($param, $value = FALSE) 51 | { 52 | $this->set_params(array( 53 | $param => $value 54 | )); 55 | } 56 | 57 | public function set_params($params = array()) 58 | { 59 | if(is_array($params)) 60 | { 61 | foreach($params as $param => $value) 62 | { 63 | if($value !== FALSE) 64 | { 65 | ee()->TMPL->tagparams[$param] = $value; 66 | } 67 | else 68 | { 69 | unset(ee()->TMPL->tagparams[$param]); 70 | } 71 | } 72 | } 73 | else 74 | { 75 | ee()->TMPL->tagparams = FALSE; 76 | } 77 | } 78 | 79 | public function get_params() 80 | { 81 | return ee()->TMPL->tagparams; 82 | } 83 | 84 | public function get_param($param) 85 | { 86 | return ee()->TMPL->fetch_param($param); 87 | } 88 | 89 | public function cache_params() 90 | { 91 | ee()->session->set_cache('entries_lib', 'params', $this->get_params()); 92 | } 93 | 94 | public function reset_params($cache = TRUE) 95 | { 96 | if($cache) 97 | { 98 | $this->cache_params(); 99 | } 100 | 101 | ee()->TMPL->tagparams = array(); 102 | } 103 | 104 | public function restore_params() 105 | { 106 | if(isset(ee()->session->cache['entries_lib']['params'])) 107 | { 108 | $this->reset_params(FALSE); 109 | $this->set_params(ee()->session->cache['entries_lib']['params'], TRUE); 110 | } 111 | 112 | ee()->session->set_cache('entries_lib', 'params', array()); 113 | 114 | return $this->get_params(); 115 | } 116 | 117 | public function cache_tagdata() 118 | { 119 | ee()->session->set_cache('entries_lib', 'tagdata', $this->get_tagdata()); 120 | } 121 | 122 | public function reset_tagdata() 123 | { 124 | $this->cache_tagdata(); 125 | 126 | ee()->TMPL->tagdata = FALSE; 127 | } 128 | 129 | public function restore_tagdata() 130 | { 131 | if(isset(ee()->session->cache['entries_lib']['tagdata'])) 132 | { 133 | $this->set_tagdata(ee()->session->cache['entries_lib']['tagdata']); 134 | } 135 | 136 | ee()->session->set_cache('entries_lib', 'tagdata', FALSE); 137 | 138 | return $this->get_tagdata(); 139 | } 140 | 141 | public function get_tagdata() 142 | { 143 | return ee()->TMPL->tagdata; 144 | } 145 | 146 | public function set_tagdata($tagdata) 147 | { 148 | ee()->TMPL->tagdata = $tagdata; 149 | } 150 | 151 | public function channel($params = array()) 152 | { 153 | require_once APPPATH.'modules/channel/mod.channel.php'; 154 | 155 | unset(ee()->channel); 156 | 157 | $channel = new \Channel(); 158 | 159 | $this->set_params($params); 160 | 161 | $this->channel = $channel; 162 | 163 | return $channel; 164 | } 165 | 166 | public function entries($params = array(), $channel = FALSE) 167 | { 168 | $default_params = array( 169 | 'dynamic' => 'no', 170 | 'disable' => 'member_data|categories|category_fields|pagination' 171 | ); 172 | 173 | if($enable = $this->get_param('enable')) 174 | { 175 | $enable = explode('|', $enable); 176 | 177 | 178 | $default_params['disable'] = str_replace($enable, '', $default_params['disable']); 179 | } 180 | 181 | foreach($default_params as $param => $value) 182 | { 183 | $user_param = $this->get_param($param); 184 | 185 | if($user_param) 186 | { 187 | $params[$param] = $user_param; 188 | } 189 | else 190 | { 191 | $params[$param] = $value; 192 | } 193 | } 194 | 195 | $tagdata = $this->get_tagdata(); 196 | 197 | $this->set_params($params); 198 | 199 | if($channel) 200 | { 201 | $this->channel = $channel; 202 | } 203 | else 204 | { 205 | $this->channel(); 206 | } 207 | 208 | if($prefix = $this->get_param('prefix')) 209 | { 210 | $this->set_tagdata(preg_replace('/(('.LD.'|\/)|(|if)\s)'.$prefix.'\d*/', '$1', $this->get_tagdata())); 211 | 212 | foreach(ee()->TMPL->var_single as $index => $value) 213 | { 214 | unset(ee()->TMPL->var_single[$index]); 215 | ee()->TMPL->var_single[str_replace($prefix, '', $index)] = str_replace($prefix, '', $value); 216 | } 217 | 218 | foreach(ee()->TMPL->var_pair as $index => $value) 219 | { 220 | unset(ee()->TMPL->var_pair[$index]); 221 | 222 | ee()->TMPL->var_pair[str_replace($prefix, '', $index)] = $value !== FALSE ? str_replace($prefix, '', $value) : FALSE; 223 | } 224 | 225 | $tagdata = ee()->TMPL->tagdata; 226 | 227 | foreach(ee()->TMPL->tag_data as $index => $tag_data) 228 | { 229 | $block = $tag_data['block']; 230 | //ee()->TMPL->tag_data[$index]['chunk'] = str_replace($block, $tagdata, $tag_data['chunk']); 231 | //ee()->TMPL->tag_data[$index]['block'] = $tagdata; 232 | } 233 | 234 | if(preg_match('/\\'.LD.'if no_results\\'.RD.'.*?\\'.LD.'\\/if\\'.RD.'/us', $this->get_tagdata(), $matches)) 235 | { 236 | ee()->TMPL->no_results = ee()->TMPL->parse_variables_row($matches[0], array( 237 | 'no_results' => 1 238 | )); 239 | } 240 | } 241 | 242 | $entries = trim($this->channel->entries()); 243 | 244 | $this->set_tagdata($tagdata); 245 | 246 | return $entries; 247 | } 248 | 249 | public static function noResults() 250 | { 251 | $obj = new static; 252 | 253 | $prefix = ''; 254 | 255 | if($obj->get_param('prefix')) 256 | { 257 | $prefix = $obj->get_param('prefix'); 258 | 259 | $obj->set_tagdata(preg_replace('/(('.LD.'|\/)|(|if)\s)'.$prefix.'\d*/', '$1', $obj->get_tagdata())); 260 | } 261 | 262 | if(preg_match('/\\'.LD.'if no_results\\'.RD.'.*?\\'.LD.'\\/if\\'.RD.'/us', $obj->get_tagdata(), $matches)) 263 | { 264 | ee()->TMPL->no_results = ee()->TMPL->parse_variables_row($matches[0], array( 265 | 'no_results' => 1 266 | )); 267 | } 268 | 269 | return ee()->TMPL->no_results(); 270 | } 271 | } -------------------------------------------------------------------------------- /channel_data/libraries/Channeldata/components/ChannelQueryBuilder.php: -------------------------------------------------------------------------------- 1 | where('entry_date', '>', $date); 17 | } 18 | 19 | public function past($date = FALSE) 20 | { 21 | if(!$date) 22 | { 23 | $date = time(); 24 | } 25 | 26 | return $this->where('entry_date', '<', $date); 27 | } 28 | 29 | public function expired($date = FALSE) 30 | { 31 | if(!$date) 32 | { 33 | $date = time(); 34 | } 35 | 36 | return $this->where('expired_entries', '<=', $date); 37 | } 38 | 39 | public function open() 40 | { 41 | return $this->where('status', 'open'); 42 | } 43 | 44 | public function closed() 45 | { 46 | return $this->where('status', 'closed'); 47 | } 48 | 49 | public function notClosed() 50 | { 51 | return $this->where('status', '!=', 'closed'); 52 | } 53 | 54 | public function notOpen() 55 | { 56 | return $this->where('status', '!=', 'open'); 57 | } 58 | 59 | public function get() 60 | { 61 | return new ChannelResponse($this, $this->model); 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /channel_data/libraries/Channeldata/components/Collection.php: -------------------------------------------------------------------------------- 1 | response = $response; 18 | $this->model = $model; 19 | 20 | foreach($data as $index => $row) 21 | { 22 | $this->items[] = new $this->model($row); 23 | } 24 | } 25 | 26 | public function ids() 27 | { 28 | $ids = array(); 29 | 30 | foreach($this->items as $item) 31 | { 32 | $ids[] = $item->id(); 33 | } 34 | 35 | return $ids; 36 | } 37 | 38 | public function reindex($index) 39 | { 40 | $return = array(); 41 | 42 | foreach($this->items() as $item) 43 | { 44 | $return[$item->$index] = $item->toArray(); 45 | } 46 | 47 | return $return; 48 | } 49 | 50 | public function each($closure) 51 | { 52 | if(is_closure($closure)) 53 | { 54 | foreach($this->items() as $index => $item) 55 | { 56 | $closure($index, $item); 57 | } 58 | } 59 | else 60 | { 61 | throw new Exception('Closure is expected, '.ucfirst(gettype($closure)).' given.', 1); 62 | 63 | } 64 | } 65 | public function items() 66 | { 67 | return $this->items; 68 | } 69 | 70 | public function first() 71 | { 72 | return $this->get(0); 73 | } 74 | 75 | public function last() 76 | { 77 | return $this->get($this->count() - 1); 78 | } 79 | 80 | public function all() 81 | { 82 | return $this->items(); 83 | } 84 | 85 | public function get($index = FALSE, $default = NULL) 86 | { 87 | return $index !== FALSE && isset($this->items[$index]) ? $this->items[$index] : NULL; 88 | } 89 | 90 | public function count() 91 | { 92 | return count($this->items); 93 | } 94 | 95 | public function toArray() 96 | { 97 | $response = array(); 98 | 99 | foreach($this->items as $item) 100 | { 101 | $response[] = $item->toArray(); 102 | } 103 | 104 | return $response; 105 | } 106 | } -------------------------------------------------------------------------------- /channel_data/libraries/Channeldata/components/QueryBuilder.php: -------------------------------------------------------------------------------- 1 | $prop)) 38 | { 39 | return $this->$prop; 40 | } 41 | } 42 | 43 | if(preg_match('/^set/', $method)) 44 | { 45 | $prop = strtolower(preg_replace('/^set/', '', $method)); 46 | 47 | if(isset($this->$prop)) 48 | { 49 | return $this->$prop = $args[0]; 50 | } 51 | } 52 | 53 | throw new \Exception("{$method} is not a valid method"); 54 | } 55 | 56 | public function groupBy($field) 57 | { 58 | $this->groupBy[] = QueryString::table($field); 59 | 60 | return $this; 61 | } 62 | 63 | public function from($table) 64 | { 65 | if(!is_object($table)) 66 | { 67 | $table = QueryString::table($table); 68 | } 69 | 70 | $this->from[] = (string) $table; 71 | } 72 | 73 | public function join($table, $subject = NULL, $operator = NULL, $value = NULL, $type = 'JOIN') 74 | { 75 | if(is_closure($table)) 76 | { 77 | $this->join[] = $this->_closure('join', $table, ' ', FALSE); 78 | } 79 | else if(is_object($table) && $subject === NULL && $operator === NULL) 80 | { 81 | $this->join[] = $type.' '.(string) $table; 82 | } 83 | else 84 | { 85 | $this->join[] = $type.' '. 86 | QueryString::table($table).' ON '. 87 | QueryString::table($subject).' '. 88 | QueryString::operator($operator).' '. 89 | QueryString::table($value); 90 | } 91 | 92 | return $this; 93 | } 94 | 95 | public function leftJoin($table, $subject = NULL, $operator = NULL, $value = NULL) 96 | { 97 | return $this->join($table, $subject, $operator, $value, 'LEFT JOIN'); 98 | } 99 | 100 | public function rightJoin($table, $subject = NULL, $operator = NULL, $value = NULL) 101 | { 102 | return $this->join($table, $subject, $operator, $value, 'RIGHT JOIN'); 103 | } 104 | 105 | public function innerJoin($table, $subject = NULL, $operator = NULL, $value = NULL) 106 | { 107 | return $this->join($table, $subject, $operator, $value, 'INNER JOIN'); 108 | } 109 | 110 | public function outerJoin($table, $subject = NULL, $operator = NULL, $value = NULL) 111 | { 112 | return $this->join($table, $subject, $operator, $value, 'OUTER JOIN'); 113 | } 114 | 115 | public function select($select, $as = NULL, $table = FALSE) 116 | { 117 | if(is_array($select)) 118 | { 119 | foreach($select as $field) 120 | { 121 | $this->select($this->protect($field), $as, $table); 122 | } 123 | } 124 | else if(is_closure($select)) 125 | { 126 | $this->select[] = $this->_closure('select', $select, ', '); 127 | } 128 | else 129 | { 130 | $select = $this->protect($select); 131 | 132 | if($table) 133 | { 134 | $select = $this->table($table) . '.' . $select; 135 | } 136 | 137 | if($as) 138 | { 139 | $select .= ' as '.$this->escape($as); 140 | } 141 | 142 | $this->select[] = $select; 143 | } 144 | 145 | return $this; 146 | } 147 | 148 | public function where($subject, $operator = NULL, $value = NULL, $concat = 'AND') 149 | { 150 | return $this->_conditional('where', $subject, $operator, $value, $concat); 151 | } 152 | 153 | public function whereIn($subject, $value = NULL) 154 | { 155 | return $this->where($subject, QueryString::raw('IN'), $value, 'AND'); 156 | } 157 | 158 | public function orWhereIn($subject, $value = NULL) 159 | { 160 | return $this->where($subject, QueryString::raw('IN'), $value, 'OR'); 161 | } 162 | 163 | public function andWhereIn($subject, $value = NULL) 164 | { 165 | return $this->where($subject, QueryString::raw('IN'), $value); 166 | } 167 | 168 | public function andWhere($subject, $operator = NULL, $value = NULL) 169 | { 170 | return $this->where($subject, $operator, $value); 171 | } 172 | 173 | public function orWhere($subject, $operator = NULL, $value = NULL) 174 | { 175 | return $this->where($subject, $operator, $value, 'OR'); 176 | } 177 | 178 | public function having($subject, $operator = NULL, $value = NULL, $concat = 'AND') 179 | { 180 | return $this->_conditional('having', $subject, $operator, $value, $concat); 181 | } 182 | 183 | public function havingIn($subject, $value = NULL) 184 | { 185 | return $this->having($subject, QueryString::raw('IN'), $value, 'AND'); 186 | } 187 | 188 | public function orHavingIn($subject, $value = NULL) 189 | { 190 | return $this->having($subject, QueryString::raw('IN'), $value, 'OR'); 191 | } 192 | 193 | public function andHavingIn($subject, $value = NULL) 194 | { 195 | return $this->having($subject, QueryString::raw('IN'), $value); 196 | } 197 | 198 | public function andHaving($subject, $operator, $value) 199 | { 200 | return $this->having($subject, $operator, $value); 201 | } 202 | 203 | public function orHaving($subject, $operator, $value) 204 | { 205 | return $this->having($subject, $operator, $value, 'OR'); 206 | } 207 | 208 | public function orderBy($field, $sort = FALSE) 209 | { 210 | $this->orderBy = $this->protect($field); 211 | 212 | if($sort) 213 | { 214 | $this->sort($sort); 215 | } 216 | 217 | return $this; 218 | } 219 | 220 | public function sort($sort) 221 | { 222 | $this->sort = !is_object($sort) ? strtoupper($sort) : (string) $sort; 223 | 224 | return $this; 225 | } 226 | 227 | public function limit($limit, $offset = FALSE) 228 | { 229 | $this->limit = $limit; 230 | 231 | if($offset !== FALSE) 232 | { 233 | $this->offset = $offset; 234 | } 235 | 236 | return $this; 237 | } 238 | 239 | public function offset($offset) 240 | { 241 | $this->offset = !is_object($offset) ? $offset : (string) $sort; 242 | 243 | return $this; 244 | } 245 | 246 | public function table($protect) 247 | { 248 | return QueryString::table($protect); 249 | } 250 | 251 | public function protect($protect) 252 | { 253 | return QueryString::protect($protect); 254 | } 255 | 256 | public function operator($operator) 257 | { 258 | return QueryString::operator($operator); 259 | } 260 | 261 | public function escape($value) 262 | { 263 | return QueryString::escape($value); 264 | } 265 | 266 | public function get() 267 | { 268 | return new QueryResponse($this, $this->model); 269 | } 270 | 271 | public function count() 272 | { 273 | return $this->get()->count(); 274 | } 275 | 276 | public function result() 277 | { 278 | return $this->get()->result(); 279 | } 280 | 281 | public function sql() 282 | { 283 | $query = array(); 284 | 285 | $select = $this->select; 286 | $from = NULL; 287 | $having = NULL; 288 | $where = NULL; 289 | $join = NULL; 290 | $orderBy = NULL; 291 | $groupBy = NULL; 292 | $limit = NULL; 293 | 294 | if(empty($this->select)) 295 | { 296 | $select = '*'; 297 | } 298 | else 299 | { 300 | $select = implode(', ', $this->select); 301 | } 302 | 303 | if(count($this->having)) 304 | { 305 | $having = 'HAVING '.QueryString::clean($this->having); 306 | } 307 | 308 | if(count($this->where)) 309 | { 310 | $where = 'WHERE '.QueryString::clean($this->where); 311 | } 312 | 313 | if(count($this->join)) 314 | { 315 | $join = QueryString::clean($this->join); 316 | } 317 | 318 | if($this->orderBy) 319 | { 320 | $orderBy = trim('ORDER BY '.$this->orderBy.' '.$this->sort); 321 | } 322 | 323 | if($this->groupBy) 324 | { 325 | $groupBy = trim('GROUP BY '.QueryString::clean($this->groupBy)); 326 | } 327 | 328 | if($this->limit) 329 | { 330 | $limit = trim('LIMIT '.$this->offset.', '.$this->limit); 331 | } 332 | 333 | if($this->from) 334 | { 335 | $from = 'FROM '.implode(' ', $this->from); 336 | } 337 | 338 | $sql = trim(' 339 | SELECT 340 | '.$select.' 341 | '.$from.' 342 | '.$join.' 343 | '.$where.' 344 | '.$having.' 345 | '.$groupBy.' 346 | '.$orderBy.' 347 | '.$limit.' 348 | '); 349 | 350 | return $sql; 351 | } 352 | 353 | public function _conditional($type, $subject, $operator = NULL, $value = NULL, $concat = 'AND') 354 | { 355 | if(is_closure($subject)) 356 | { 357 | $append = trim($concat) . ' ' . $this->_closure($type, $subject, ' '); 358 | } 359 | else if(is_array($subject)) 360 | { 361 | $append = NULL; 362 | 363 | if($operator === NULL) 364 | { 365 | $operator = '='; 366 | } 367 | 368 | foreach($subject as $field => $value) 369 | { 370 | $this->$type($field, $operator, $value, $concat); 371 | } 372 | } 373 | else if(is_object($subject) && $operator === NULL && $value === NULL) 374 | { 375 | $append = $concat.' ('.(string) $subject.')'; 376 | } 377 | else 378 | { 379 | if(is_string($value)) 380 | { 381 | if(strtoupper($value) == 'AND' || strtoupper($value) == 'OR') 382 | { 383 | $concat = $value; 384 | $value = NULL; 385 | } 386 | } 387 | 388 | if(!is_null($operator) && is_null($value)) 389 | { 390 | if($subject != 'entry_date') 391 | { } 392 | 393 | $value = $operator; 394 | $operator = $this->defaultOperator; 395 | } 396 | 397 | if(is_array($value)) 398 | { 399 | foreach($value as $index => $val) 400 | { 401 | $value[$index] = $this->escape($val); 402 | } 403 | 404 | $value = QueryString::raw('('.implode(', ', $value).')'); 405 | } 406 | 407 | $append = $concat.' ('. 408 | $this->protect($subject).' '. 409 | $this->operator($operator).' '. 410 | $this->escape($value).')'; 411 | } 412 | 413 | $this->$type = array_merge($this->$type, array($append)); 414 | 415 | return $this; 416 | } 417 | 418 | private function _closure($prop, $closure, $glue, $encapsulate = TRUE) 419 | { 420 | $builder = new QueryBuilder(); 421 | $method = 'get'.ucfirst($prop); 422 | 423 | $closure($builder); 424 | 425 | $return = QueryString::clean(implode($glue, $builder->$method())); 426 | 427 | if($encapsulate) 428 | { 429 | $return = '('.$return.')'; 430 | } 431 | 432 | return $return; 433 | } 434 | } -------------------------------------------------------------------------------- /channel_data/libraries/Channeldata/components/QueryString.php: -------------------------------------------------------------------------------- 1 | str = $str; 12 | } 13 | 14 | public function __toString() 15 | { 16 | return $this->str; 17 | } 18 | 19 | public static function url_title($str, $separator = 'dash', $lowercase = TRUE) 20 | { 21 | if (UTF8_ENABLED) 22 | { 23 | $CI =& get_instance(); 24 | $CI->load->helper('text'); 25 | 26 | $str = utf8_decode($str); 27 | $str = preg_replace_callback('/(.)/', 'convert_accented_characters', $str); 28 | } 29 | 30 | $separator = ($separator == 'dash') ? '-' : '_'; 31 | 32 | $trans = array( 33 | '&\#\d+?;' => '', 34 | '&\S+?;' => '', 35 | '\s+|/+' => $separator, 36 | '[^a-z0-9\-\._]' => '', 37 | $separator.'+' => $separator, 38 | '^[-_]+|[-_]+$' => '', 39 | '\.+$' => '' 40 | ); 41 | 42 | $str = strip_tags($str); 43 | 44 | foreach ($trans as $key => $val) 45 | { 46 | $str = preg_replace("#".$key."#i", $val, $str); 47 | } 48 | 49 | if ($lowercase === TRUE) 50 | { 51 | $str = strtolower($str); 52 | } 53 | 54 | return trim(stripslashes($str)); 55 | } 56 | 57 | public static function protect($str, $table = FALSE) 58 | { 59 | if(!is_object($str)) 60 | { 61 | $parts = explode('.', $str); 62 | 63 | foreach($parts as $index => $part) 64 | { 65 | $part = trim(self::strip($part)); 66 | 67 | if(!preg_match('/\*/', $part)) 68 | { 69 | $part = '`'.$part.'`'; 70 | } 71 | 72 | $parts[$index] = $part; 73 | } 74 | 75 | if(count($parts) > 1) 76 | { 77 | $parts[0] = self::table($parts[0]); 78 | } 79 | else if($table && count($parts)) 80 | { 81 | array_unshift($parts, self::table($table)); 82 | } 83 | 84 | return implode('.', $parts); 85 | } 86 | 87 | return (string) $str; 88 | } 89 | 90 | public static function raw($str) 91 | { 92 | return new QueryString($str); 93 | } 94 | 95 | public static function escape($str) 96 | { 97 | if(!is_object($str)) 98 | { 99 | return ee()->db->escape($str); 100 | } 101 | 102 | return (string) $str; 103 | } 104 | 105 | public static function operator($str) 106 | { 107 | if(!is_object($str)) 108 | { 109 | return $str; 110 | } 111 | 112 | return (string) $str; 113 | } 114 | 115 | public static function table($str) 116 | { 117 | if(is_string($str)) 118 | { 119 | $str = self::strip($str); 120 | 121 | if(!preg_match('/^exp_/', $str)) 122 | { 123 | $str = ee()->db->dbprefix($str); 124 | } 125 | 126 | return self::protect($str); 127 | } 128 | 129 | return (string) $str; 130 | } 131 | 132 | static function strip($str) 133 | { 134 | $str = preg_replace('/^\`|\`$/', '', $str); 135 | $str = preg_replace('/\{\d*\}/', '', $str); 136 | 137 | return $str; 138 | } 139 | 140 | public static function clean($sql) 141 | { 142 | if(is_array($sql)) 143 | { 144 | $sql = implode(' ', $sql); 145 | } 146 | 147 | $sql = trim($sql); 148 | 149 | foreach(array('AND', 'OR') as $value) 150 | { 151 | $sql = ltrim($sql, $value); 152 | } 153 | 154 | return trim($sql); 155 | } 156 | } -------------------------------------------------------------------------------- /channel_data/libraries/Channeldata/models/Action.php: -------------------------------------------------------------------------------- 1 | get(); 23 | } 24 | 25 | public static function findByMethod($method) 26 | { 27 | return self::where('method', '=', $method)->get(); 28 | } 29 | } -------------------------------------------------------------------------------- /channel_data/libraries/Channeldata/models/Channel.php: -------------------------------------------------------------------------------- 1 | channel_name; 65 | } 66 | 67 | public function fields() 68 | { 69 | return ChannelField::findByGroup($this->field_group); 70 | } 71 | 72 | public static function findByEntry($entry_id) 73 | { 74 | $title = ChannelTitle::find($entry_id); 75 | 76 | if(!$title) 77 | { 78 | return NULL; 79 | } 80 | 81 | return Channel::find($title->channel_id); 82 | } 83 | 84 | public static function findByName($name) 85 | { 86 | return self::query()->where('channel_name', $name)->get()->first(); 87 | } 88 | } -------------------------------------------------------------------------------- /channel_data/libraries/Channeldata/models/ChannelData.php: -------------------------------------------------------------------------------- 1 | fill($data); 20 | 21 | foreach(ChannelField::all()->items() as $item) 22 | { 23 | 24 | } 25 | } 26 | */ 27 | 28 | public static function findByChannel($channel) 29 | { 30 | $obj = new static; 31 | 32 | $fillable = array(); 33 | 34 | $query = $obj->query(); 35 | 36 | foreach(ChannelField::findByChannel($channel)->all() as $field) 37 | { 38 | $fillable[] = 'field_id_'.$field->id(); 39 | $query->select('field_id_'.$field->id(), $field->name()); 40 | } 41 | 42 | 43 | 44 | $obj->setAttribute('columns', $fillable); 45 | 46 | 47 | /* 48 | $return = $class::where('channel_data.channel_id', $channel) 49 | ->join('channel_titles', 'channel_data.entry_id', '=', 'channel_titles.entry_id'); 50 | */ 51 | 52 | 53 | var_dump($query->get()->result()->first()->toArray());exit(); 54 | 55 | return $return->get(); 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /channel_data/libraries/Channeldata/models/ChannelEntry.php: -------------------------------------------------------------------------------- 1 | toArray(), $data->toArray()); 22 | 23 | /* 24 | $channel = Channel::find($title->channel_id); 25 | $class = ucfirst($channel->name()); 26 | 27 | if(class_exists($class)) 28 | { 29 | exit('true'); 30 | } 31 | */ 32 | 33 | var_dump('false');exit(); 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /channel_data/libraries/Channeldata/models/ChannelField.php: -------------------------------------------------------------------------------- 1 | field_label; 48 | } 49 | 50 | public function name() 51 | { 52 | return $this->field_name; 53 | } 54 | 55 | public static function findByEntry($entry) 56 | { 57 | $channel = Channel::findByEntry($entry); 58 | 59 | if(!$channel) 60 | { 61 | return NULL; 62 | } 63 | 64 | return ChannelField::findByGroup($channel->field_group); 65 | } 66 | 67 | public static function findByChannel($channel) 68 | { 69 | $channel = Channel::find($channel); 70 | 71 | if(!$channel) 72 | { 73 | return NULL; 74 | } 75 | 76 | return self::findByGroup($channel->field_group); 77 | } 78 | 79 | public static function findByName($name) 80 | { 81 | return self::query()->where('field_name', $name)->get()->first(); 82 | } 83 | 84 | public static function findByGroup($groupId) 85 | { 86 | return self::query()->where('group_id', $groupId)->result(); 87 | } 88 | } -------------------------------------------------------------------------------- /channel_data/libraries/Channeldata/models/ChannelTitle.php: -------------------------------------------------------------------------------- 1 | each(function($i, $field) use($self, $data) { 39 | $self->setAttribute($field->name(), $data->{$field->name()}); 40 | }); 41 | 42 | parent::__construct($data); 43 | 44 | if(isset($data->member_id)) 45 | { 46 | $this->member_id = $data->member_id; 47 | } 48 | 49 | if(isset($data->group_id)) 50 | { 51 | $this->group_id = $data->group_id; 52 | } 53 | } 54 | 55 | public function memberFields() 56 | { 57 | $self = $this; 58 | $array = array(); 59 | 60 | MemberField::all()->each(function($i, $field) use($self, &$array) { 61 | $value = $self->getAttribute($field->name()); 62 | 63 | $array['m_field_id_'.$field->m_field_id] = $value; 64 | }); 65 | 66 | return $array; 67 | } 68 | 69 | protected function _createRecord($data = array()) 70 | { 71 | parent::_createRecord($data); 72 | 73 | if(count($this->memberFields())) 74 | { 75 | ee()->db->insert('member_data', array_merge( 76 | array('member_id' => $this->id()), 77 | $this->memberFields() 78 | )); 79 | } 80 | 81 | return $this; 82 | } 83 | 84 | protected function _updateRecord($data = array()) 85 | { 86 | parent::_updateRecord($data); 87 | 88 | if(count($this->memberFields())) 89 | { 90 | ee()->db->where($this->idField, $this->id()); 91 | ee()->db->update('member_data', $this->memberFields()); 92 | } 93 | 94 | return $this; 95 | } 96 | 97 | public static function findByUsername($name) 98 | { 99 | return self::where('username', '=', $name)->get()->first(); 100 | } 101 | 102 | public static function query() 103 | { 104 | $class = self::instantiate(); 105 | 106 | $query = new QueryBuilder(); 107 | $query->model = get_class($class); 108 | 109 | $query->select('*'); 110 | 111 | MemberField::all()->each(function($i, $field) use ($query) { 112 | $query->select('m_field_id_'.$field->id(), $field->m_field_name); 113 | }); 114 | 115 | $query->from($class::table()); 116 | $query->join('member_data', 'members.member_id', '=', 'member_data.member_id'); 117 | 118 | return $query; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /channel_data/libraries/Channeldata/models/MemberField.php: -------------------------------------------------------------------------------- 1 | result()->ids(); 15 | } 16 | 17 | public function entries($fixedOrder = FALSE) 18 | { 19 | $parser = new ChannelEntriesParser(); 20 | 21 | if($this->count() == 0) 22 | { 23 | return ChannelEntriesParser::noResults(); 24 | } 25 | 26 | $ids = implode('|', $this->entryIds()); 27 | 28 | $params = array( 29 | 'entry_id' => $ids 30 | ); 31 | 32 | if($fixedOrder) 33 | { 34 | $params['fixed_order'] = $ids; 35 | } 36 | 37 | return $parser->entries($params); 38 | } 39 | 40 | protected function _collection($data) 41 | { 42 | if($this->model) { 43 | return new ChannelCollection($data, $this, $this->model); 44 | } 45 | 46 | return $data; 47 | } 48 | } -------------------------------------------------------------------------------- /channel_data/libraries/Channeldata/responses/QueryResponse.php: -------------------------------------------------------------------------------- 1 | builder = $builder; 17 | $this->model = $model; 18 | 19 | $this->query = ee()->db->query($this->builder->sql()); 20 | } 21 | 22 | public function count() 23 | { 24 | return $this->query->num_rows(); 25 | } 26 | 27 | public function each($closure) 28 | { 29 | return $this->result()->each($closure); 30 | } 31 | 32 | public function first() 33 | { 34 | if($this->count()) 35 | { 36 | return $this->_model($this->query->first_row()); 37 | } 38 | 39 | return NULL; 40 | } 41 | 42 | public function index($index) 43 | { 44 | $data = $this->result(); 45 | 46 | return isset($data[$index]) ? $this->_model($data[$index]) : NULL; 47 | } 48 | 49 | public function last() 50 | { 51 | return $this->_model($this->query->last_row()); 52 | } 53 | 54 | public function next() 55 | { 56 | return $this->_model($this->query->next_row()); 57 | } 58 | 59 | public function prev() 60 | { 61 | return $this->_model($this->query->prev_row()); 62 | } 63 | 64 | public function result() 65 | { 66 | return $this->_collection($this->query->result()); 67 | } 68 | 69 | public function get() 70 | { 71 | return $this->_collection($this->query->result()); 72 | } 73 | 74 | public function row() 75 | { 76 | return $this->_model($this->query->row()); 77 | } 78 | 79 | public function toArray() 80 | { 81 | return $this->_model($this->query->row())->toArray(); 82 | } 83 | 84 | protected function _model($data) 85 | { 86 | if($this->model) { 87 | return new $this->model($data); 88 | } 89 | 90 | return $data; 91 | } 92 | 93 | protected function _collection($data) 94 | { 95 | if($this->model) { 96 | return new Collection($data, $this, $this->model); 97 | } 98 | 99 | return $data; 100 | } 101 | } -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Channel Data 2 | 3 | Copyright (c) 2012, Justin Kimbrell 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------