adding example apps, fixing powerup issues
[feisty_meow.git] / production / example_apps / zippy_maps / src / Model / Table / CategoriesTable.php
1 <?php
2 namespace App\Model\Table;
3
4 use Cake\Log\Log;
5 use Cake\ORM\Query;
6 use Cake\ORM\RulesChecker;
7 use Cake\ORM\Table;
8 use Cake\Validation\Validator;
9
10 /**
11  * Categories Model
12  *
13  * @method \App\Model\Entity\Category get($primaryKey, $options = [])
14  * @method \App\Model\Entity\Category newEntity($data = null, array $options = [])
15  * @method \App\Model\Entity\Category[] newEntities(array $data, array $options = [])
16  * @method \App\Model\Entity\Category|bool save(\Cake\Datasource\EntityInterface $entity, $options = [])
17  * @method \App\Model\Entity\Category patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
18  * @method \App\Model\Entity\Category[] patchEntities($entities, array $data, array $options = [])
19  * @method \App\Model\Entity\Category findOrCreate($search, callable $callback = null, $options = [])
20  *
21  * @mixin \Cake\ORM\Behavior\TimestampBehavior
22  */
23 class CategoriesTable extends Table
24 {
25
26     /**
27      * Initialize method
28      *
29      * @param array $config The configuration for the Table.
30      * @return void
31      */
32     public function initialize(array $config)
33     {
34         parent::initialize($config);
35
36         $this->setTable('categories');
37         $this->setDisplayField('name');
38         $this->setPrimaryKey('id');
39
40         $this->addBehavior('Timestamp');
41         
42         $this->belongsToMany('Locations',
43                         [
44                                         'targetForeignKey' => 'location_id',
45                                         'foreignKey' => 'category_id',
46                                         'joinTable' => 'categories_locations',
47                                         'through' => 'CategoriesLocations',
48                         ]);
49         
50     }
51
52     /**
53      * Default validation rules.
54      *
55      * @param \Cake\Validation\Validator $validator Validator instance.
56      * @return \Cake\Validation\Validator
57      */
58     public function validationDefault(Validator $validator)
59     {
60         $validator
61             ->integer('id')
62             ->allowEmpty('id', 'create');
63
64         $validator
65             ->requirePresence('name', 'create')
66             ->notEmpty('name')
67             ->add('name', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']);
68
69         $validator
70             ->integer('parent')
71             ->allowEmpty('parent');
72
73         return $validator;
74     }
75
76     /**
77      * Returns a rules checker object that will be used for validating
78      * application integrity.
79      *
80      * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
81      * @return \Cake\ORM\RulesChecker
82      */
83     public function buildRules(RulesChecker $rules)
84     {
85         $rules->add($rules->isUnique(['name']));
86
87         return $rules;
88     }
89     
90     /**
91      * returns a query that will find all the categories as a list.
92      */
93     public function getAllCategories() {
94         // find the full list of categories to show the user.
95         $categoriesList = $this->find ( 'list', [
96                         'keyField' => 'id',
97                         'valueField' => 'name',
98                         'order' => [
99                                         'name' => 'asc'
100                         ]
101         ] );
102                 return $categoriesList;
103     }
104     
105     /**
106      * returns a query that will locate all of the locations in the specified category with 'id'.
107      */
108     public function getLocationsInCategory($id)
109     {
110         // query all the locations belonging to this category.
111         $locationsInCategory = $this->CategoriesLocations->find('all', [
112                         'conditions' => [ 'category_id' => $id ],
113                         'contain' => ['Locations']
114         ]);
115         return $locationsInCategory;
116     }
117     
118     /**
119      * returns a query that finds all locations in the category that fit within the southwest and northeast
120      * corners specified.
121      */
122     public function getLocationsInCategoryInBox($id, $sw_lat, $sw_long, $ne_lat, $ne_long, $start = null, $end = null)
123     {
124         // query all the locations belonging to this category.
125         $locationsInCategory = $this->CategoriesLocations->find('all', [
126                         'conditions' => [ 'category_id' => $id ],
127                         'contain' => ['Locations', 'Categories']
128         ]);
129         
130         Log::Debug('bounds=' . $sw_lat . ', '.  $sw_long . ' to ' . $ne_lat . ', ' . $ne_long);
131         
132         $bounds = [ $sw_lat , $sw_long , $ne_lat , $ne_long ];
133         
134         if (! $bounds) {
135                 Log::Debug("failed to calculate the bounding box!");
136         } else {
137                 Log::Debug("bounding box: " . var_export($bounds, true));
138         }
139         
140         // use the boundaries to restrict the lookup.
141         // order: min_lat, min_long, max_lat, max_long.
142         $locationsInCategory = $locationsInCategory->where (
143                         function ($exp) use ($bounds) {
144                                 return $exp->gte ( 'lat', $bounds [0] )->gte ( 'lng', $bounds [1] )->lte ( 'lat', $bounds [2] )->lte ( 'lng', $bounds [3] );
145                         }
146                         );
147         
148         if (($start !== null) && ($end !== null)) {
149                 Log::debug('start of range = ' . $start . ' and end = ' . $end);
150                 $locationsInCategory= $locationsInCategory->order(['lat desc', 'lng desc']);
151                 $chunk = $end - $start + 1;
152                 $locationsInCategory= $locationsInCategory->limit($chunk);
153                 $page = 1 + (int)($start / $chunk);
154                 $locationsInCategory= $locationsInCategory->page($page);
155                 Log::debug('page = ' . $page . ' and chunk = ' . $chunk);
156         }       
157         
158         return $locationsInCategory;
159     }
160     
161     public function getChewedLocationsInCategoryInBox($id, $sw_lat, $sw_long, $ne_lat, $ne_long, $start = null, $end = null)
162     {
163         $locationsInCategory = $this->getLocationsInCategoryInBox($id, $sw_lat, $sw_long, $ne_lat, $ne_long, $start, $end);
164         
165         $locationsToSerialize = [];
166         
167         // make an array with the useful parts of the location data.
168         foreach ($locationsInCategory as $location) {                   
169                 $lat_and_long = $location->location->lat. ',' . $location->location->lng;
170                 if (array_key_exists ( $lat_and_long, $locationsToSerialize)) {
171                         continue;  // already got it.
172                 }
173                 
174 //Log::debug('got an icon value of: ' . $location->category->image);                    
175                 
176                 // we don't include lat and lng below since they are encoded as array key.
177                 $locationsToSerialize[$lat_and_long] = ['name' => $location->location->name,
178                                 'loc' => $location->location->location,
179                                 'icon' => $location->category->image,
180                                 'id' => $location->location_id,
181                 ];              
182         }
183         
184         return $locationsToSerialize;
185     }
186 }