/[drupal]/contributions/modules/mapapi/mapapi.module
ViewVC logotype

Contents of /contributions/modules/mapapi/mapapi.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.4 - (show annotations) (download) (as text)
Mon Jul 9 17:04:09 2007 UTC (2 years, 4 months ago) by dmitrig01
Branch: MAIN
CVS Tags: HEAD
Changes since 1.3: +2 -3 lines
File MIME type: text/x-php
Removing inappropriate message
1 <?php
2 //$Id: mapapi.module,v 1.3 2007/07/09 02:42:16 dmitrig01 Exp $
3 /*
4 * @file Creates and loads maps.
5 */
6
7 /*
8 * Throughout most of the API, we use
9 * a $status variable, which has several
10 * keys. These are useful for two things,
11 * first, knowing which parts of a command
12 * went through, and which ones failed.
13 * The other thing is that most $status
14 * messages contain lots of useful debug
15 * info, like the function name, line number
16 * and a small message that states what
17 * error occured. Eventually, we could make
18 * an error database which consists of error
19 * numbers, debug info, where the error occured,
20 * the function it occured in, and a user friendly
21 * message like "We are sorry, but a fatal error
22 * occurred"
23 *
24 * For now, the most keys you will ever get will be:
25 * @code
26 * $status = array(
27 * '#data', // This contains all the data.
28 * // If success is true, you don't need to
29 * // look at the other data
30 * '#message',
31 * '#function',
32 * '#line_number',
33 * '#success',
34 * // After that, there is the success of certain
35 * // components (e.g. on tile deletion, there is
36 * // the tile deletion success and the tile
37 * // content deletion success flag)
38 * )
39 * @endcode
40 */
41
42 function mapapi_default_status($function) {
43 $status = array(
44 '#data' => array(),
45 '#message' => '',
46 '#line_number' => NULL,
47 '#function' => '_mapapi_load',
48 '#success' => FALSE,
49 );
50 return $status;
51 }
52
53 /*
54 * Loads maps maps. Use this instead of _mapapi_load.
55 * @param $maps
56 * An array of maps
57 * A sample maps array would be
58 * @code
59 * $maps['multi_tile'] = array(
60 * 'mid' => 1,
61 * 'x' => 5, // Try negative values... you will see them adjust and always return
62 * 'y' => 5, // The correct box bounds (defined by length_x and length_y)
63 * 'length_x' => 10,
64 * 'length_y' => 9, // Doesn't have to be exactly square!
65 * 'tile_content' => TRUE // True/false on whether to load tile content or not.
66 * );
67 * $maps['single_tile'] = array(
68 * 'mid' => 1,
69 * 'x' => 5,
70 * 'y' => 5,
71 * 'length_x' => 10,
72 * 'length_y' => 9,
73 * 'tile_content' => TRUE,
74 * );
75 * @endcode
76 *
77 * @todo
78 * cache the maps loaded, since it can be expensive
79 */
80 function mapapi_load($maps) {
81 // This is the array in which maps are stored.
82 // The keys are the same as those of $maps
83 // But the content is the tiles.
84 $mapapi_array = array();
85 // Loop through each map, because $maps
86 // is an array of maps, not a single map
87 foreach($maps as $mapapi_name => $map) {
88 // Load the map, and insert it into $mapapi_array
89 // with the same key as $maps
90 $mapapi_array[$mapapi_name] = _mapapi_load($map);
91 }
92 // Return the array of maps
93 return $mapapi_array;
94 }
95 /*
96 * Loads a single map.
97 * Internal usage only. Use mapapi_load instead.
98 * This function does all limit / boundary
99 * calculation, as well as fetching the tiles.
100 */
101 function _mapapi_load($map) {
102 $status = mapapi_default_status('_mapapi_load');
103 // We need to get the limits of the map
104 // to make sure that the map array passed in's
105 // area is not more than itself's area.
106 // This needs to be done to eleminate errors
107 // and such.
108 if ($mapapi_limits_query = db_query("SELECT mid, name, limit_x, limit_y FROM {mapapi_map_definition} WHERE mid = %d", $map['mid'])) {
109 // The upper limits of the map
110 $mapapi_limits = db_fetch_array($mapapi_limits_query);
111 // Build the dimensions of the map, respecting the limits
112 // of the map defnition.
113 $limits = mapapi_build_dimensions($map, $mapapi_limits);
114 $status['#dimension_success'] = TRUE;
115 }
116 // If that query failed, we need to silently fail
117 // and don't execute the rest of the function, because
118 // it would be pointless.
119 else {
120 $status['#dimension_success'] = FALSE;
121 $status['#line_number'] = 109;
122 $status['#message'] = "The query <code>SELECT mid, name, limit_x, limit_y FROM {mapapi_map_definition} WHERE mid = %d</code> could not be executed, or didn't return any rows";
123 return $status;
124 }
125
126 $check_query_args = array();
127 $query = "SELECT tid, coord_x, coord_y, description FROM {mapapi_tile_definition} WHERE ";
128 // We need to respect the upper limits of the map
129 // in both x and y.
130 // If we don't do this, the query can select un-needed tiles
131 $query .= "coord_y <= %d AND "; $check_query_args[] = $mapapi_limits['limit_y'];
132 $query .= "coord_x <= %d AND "; $check_query_args[] = $mapapi_limits['limit_x'];
133 // We need to (quite obviously) follow the upper limits
134 // of the map requested.
135 // We need to follow both X and Y
136 $query .= "coord_y <= %d AND "; $check_query_args[] = $limits['y']['high'];
137 $query .= "coord_x <= %d AND "; $check_query_args[] = $limits['x']['high'];
138 // Ditto, but for lower limits this time
139 $query .= "coord_y >= %d AND "; $check_query_args[] = $limits['y']['low'];
140 $query .= "coord_x >= %d AND "; $check_query_args[] = $limit['x']['low'];
141 // Make sure we select from the proper map (!!!)
142 $query .= "mid = %d"; $check_query_args[] = $map['mid'];
143
144 // Execute the query
145 if ($result = db_query($query, $check_query_args)) {
146 // Return some basic information about the map,
147 // might be helpful in some circumstances
148 $data = array(
149 'map_info' => $mapapi_limits,
150 'dimensions' => $limits,
151 'map_query' => $query,
152 );
153
154 $data = array();
155 while($row = db_fetch_array($result)) {
156 $status['#tile_success'] = FALSE;
157 // Eventually, this will be the tile content, but for now, it is not
158 $row['content'] = array();
159 // Since the description can be an array, we serialize it
160 $row['description'] = unserialize($row['description']);
161 // We need the coordinates of the tile, to know where in the array to put them
162 $coord_y = $row['coord_y'];
163 $coord_x = $row['coord_x'];
164 // Insert the row into the tiles array
165 $tiles[$coord_x][$coord_y] = $row;
166 }
167 $data['map_tiles'] = $tiles;
168 $status['#data'] = $data;
169 return $status;
170 }
171 // If no tiles were found or the query failed, then return an empty array.
172 else {
173 $status['#success'] = FALSE;
174 $status['#line_number'] = 142;
175 $status['#message'] = "The query <code>". $query ."</code> could not be executed, or didn't return any rows";
176 return $status;
177 }
178 }
179
180 /**
181 * Figure out dimensions of a map, around the x and y.
182 */
183 function mapapi_build_dimensions($map, $limits) {
184 // Determine number of tiles to go to
185 // each direction away from the center.
186 // Up and down should be equal length
187 // as well as left and right
188 $x_spacer = floor($map['length_x'] / 2);
189 $y_spacer = floor($map['length_y'] / 2);
190
191 // Determine X boundaries
192 $x_low = $map['x'] - $x_spacer;
193 $x_high = $map['x'] + $x_spacer;
194
195 // Determine Y boundaries
196 $y_low = $map['y'] - $y_spacer;
197 $y_high = $map['y'] + $y_spacer;
198
199 // If the map's left boundary
200 // is below 0, then something
201 // needs to be done!
202 // The whole map needs to move
203 // right, so the width stays the
204 // same.
205 if ($x_low < 0) {
206 // Increase $x_high by the
207 // amount below 0 $x_low is
208 // So as an example
209 // if $x_low is -3
210 // and $x_high is 5
211 // then the height of the
212 // map is 8.
213 // So $x_low becomes 0
214 // and $x_high becomes 8.
215 // We also need to compensate
216 // for if the height of the
217 // new $x_high is higher than
218 // the limit of the map.
219 $x_high = min($x_high - $x_low, $limits['limit_x']);
220 $x_low = 0;
221 }
222 // Even if the boundaries are above 0
223 // we still need to make sure that the
224 // upper boundaries don't exceed the
225 // upper boundaries of the map.
226 if ($x_high > $limits['limit_x']) {
227 // This still needs to be above 0.
228 // That is why the max function is used
229 $x_low = max($x_low - ($x_high - $limits['limit_x']), 0);
230 $x_high = $limits['limit_x'];
231 }
232
233 // If the map's left boundary
234 // is below 0, then something
235 // needs to be done!
236 // The whole map needs to move
237 // right, so the width stays the
238 // same.
239 if ($y_low < 0) {
240 // Increase $y_high by the
241 // amount below 0 $y_low is
242 // So as an example
243 // if $y_low is -3
244 // and $y_high is 5
245 // then the height of the
246 // map is 8.
247 // So $y_low becomes 0
248 // and $y_high becomes 8.
249 // We also need to compensate
250 // for if the height of the
251 // new $y_high is higher than
252 // the limit of the map.
253 $y_high = min($y_high - $y_low, $limits['limit_y']);
254 $y_low = 0;
255 }
256 // Even if the boundaries are above 0
257 // we still need to make sure that the
258 // upper boundaries don't exceed the
259 // upper boundaries of the map.
260 if ($y_high > $limits['limit_y']) {
261 // This still needs to be above 0.
262 // That is why the may function is used
263 $y_low = max($y_low - ($y_high - $limits['limit_y']), 0);
264 $y_high = $limits['limit_y'];
265 }
266
267 $dimensions = array();
268 $dimensions['x'] = array('low' => $x_low , 'high' => $x_high);
269 $dimensions['y'] = array('low' => $y_low , 'high' => $y_high);
270 return $dimensions;
271 }
272
273 /*
274 * Wrapper function
275 * Call mapapi_save('tile', $data)
276 * to save a tile, mapapi_save('map', $data),
277 * etc.
278 */
279 function mapapi_save($type, $data) {
280 if(function_exists("mapapi_$type"."_save")) {
281 return call_user_func("mapapi_$type"."_save", $data);
282 }
283 else {
284 return false;
285 }
286 }
287
288 /**
289 * Internal usage only. Use mapapi_save('tile', $data);
290 * This function saves tiles.
291 *
292 * @param $data
293 * What to save
294 * @code
295 * $save_format = array(
296 * 'mid' => 1,
297 * 'tid' => 1,
298 * 'coord_x' => '5',
299 * 'coord_y' => '7',
300 * 'description' => array(),
301 * 'content' => array(),
302 * );
303 * @endcode
304 *
305 * @return mixed
306 */
307 function mapapi_tile_save($data, $args = array()) {
308 $status = mapapi_default_status();
309 $status['#tile'] = FALSE;
310 $status['#content'] = FALSE;
311
312 // Check if we have all required data
313 // We need to check the map ID, the x
314 // coordinate, and the y coordinate
315 if (!isset($data['mid']) || !isset($data['coord_x']) || !isset($data['coord_y'])) {
316 // The status is still all false, so return it.
317 // We need to set the message to "not enough parameters,"
318 // indicating not enough data was passed in.
319 $status['#message'] = "Not enough parameters. Parameters sent in were <pre>". $data ."</pre> ";
320 $status['#message'] .= "You need to pass in the mid of the map to be saved to, ";
321 $status['#message'] .= "and the x and y coordinates of the tile to save.";
322 return $status;
323 }
324 // If the x or y coordinates are less than 0, which
325 // is not allowed, throw an error
326 else if ($data['coord_x'] < 0 || $data['coord_y'] < 0) {
327 // Set a very descriptive status message.
328 // We need to alert the user on if both
329 // or one, and we need to include which one,
330 // of the parameters were lower than 0
331 if ($data['coord_x'] < 0 && $data['coord_y'] < 0) {
332 $status['message'] = "Both the x and y coordinates passed into the function were";
333 $status['message'] .= "less than 0, which is not allowed.";
334 }
335 else if ($data['coord_x'] < 0) {
336 $status['message'] = "The x coordinate passed into the function were";
337 $status['message'] .= "less than 0, which is not allowed.";
338 }
339 else if ($data['coord_y'] < 0) {
340 $status['message'] = "The y coordinate passed into the function were";
341 $status['message'] .= "less than 0, which is not allowed.";
342 }
343 return $status;
344 }
345 // Now we must test if mid is valid.
346 $test_mid_query = "SELECT mid FROM mapapi_map_definition WHERE mid = %d";
347 if ($result = db_query($test_mid_query, $data['mid'])){
348 if (db_num_rows($result) > 0){
349 // The map is valid so we don't do anything
350 }
351 else {
352 $status['message'] = "The mid is invalid";
353 // Not valid map! We musn't save anything
354 return $status;
355 }
356 }
357
358 // Check if tile exists
359 $query = "SELECT tid FROM {mapapi_tile_definition} WHERE "; $query_args = array();
360 $query .= "coord_x = %d "; $query_args[] = $data['coord_x'];
361 $query .= "AND coord_y = %d "; $query_args[] = $data['coord_y'];
362 $query .= "AND mid = %d "; $query_args[] = $data['mid'];
363
364 // If it exists, we update the tile instead of
365 // saving it.
366 if ($result = db_query($query, $query_args)) {
367 if (db_num_rows($result) > 0) {
368 $status['message'] = 'Tile found. Updating it. ';
369 $tid = db_fetch_array($result);
370 // Maybe tid was already passed, but we dont care beacuse $tid is guaranteed to always be more correct
371 $data['tid'] = $tid['tid'];
372 // No need to see if data definition or data content are set! That check is done inside the tile and content functions
373 // Update the tile
374 _mapapi_tile_update($data, $status);
375 // The tile content must also be saved
376 mapapi_content_save($data, $status);
377 }
378 else {
379 $status['message'] = 'Tile not found. Adding a new one. ';
380 // If this is a new tile then tid should not be set!
381 // In the admin UI there will be no way to set tid.
382 $data['tid'] = db_next_id("mapapi_tile_tid");
383 // No need to see if data definition or data content are set! That check is done inside the tile and content functions
384 // Insert the tile
385 // If it succeeds, save the content as well.
386 if(_mapapi_tile_insert($data, $status)){
387 mapapi_content_save($data, $status);
388 }
389 }
390 }
391 else {
392 $status['message'] = "The query to check of the tile is updated failed!";
393 }
394
395 return $status;
396 }
397
398 function _mapapi_tile_insert($data, &$status){
399 // We check if the tid and description are set.
400 // The other items are checked by mapapi_tile_save
401 if (!isset($data['tid']) || !isset($data['description'])) {
402 // We don't need to alter $status, because
403 // it is set to false by default.
404 // However, we do need to return false,
405 // so the if statement in mapapi_tile_save
406 // won't go through
407 return FALSE;
408 }
409
410 // This is the big query.
411 $query = "INSERT INTO {mapapi_tile_definition} (mid, tid, coord_x, coord_y, description) VALUES (%d, %d, %d, %d, '%s')";
412 $query_args = array();
413 $query_args[] = $data['mid'];
414 $query_args[] = $data['tid'];
415 $query_args[] = $data['coord_x'];
416 $query_args[] = $data['coord_y'];
417 // The description is serialized, because
418 // it can contain lots of information,
419 // like the terrain.
420 $query_args[] = serialize($data['description']);
421
422 if (db_query($query, $query_args)) {
423 $status['tile'] = TRUE;
424 return TRUE;
425 }
426 // The status does not need to be set to false,
427 // because it is false by default.
428 return FALSE;
429 }
430
431 // Updates tile description only! (because to update X or Y means that we just insert a new tile and should use _mapapi_tile_insert
432 function _mapapi_tile_update($data, &$status) {
433 // Check if the description is set.
434 // The other items are checked by mapapi_tile_save
435 if (!isset($data['description'])) {
436 // We don't need to alter $status['tile'],
437 // because it is set to false by default.
438 // $status['message'] does need to be
439 // set to something more descriptive.
440 // At this point, $status['message']
441 // needs to be appended to, because
442 // it already has some information
443 // in it.
444 // $status['function'] needs to be
445 // set to _mapapi_tile_update to
446 // alert the user that the error
447 // occered here.
448 // We need to return false,
449 // so the if statement in mapapi_tile_save
450 // won't go through.
451 $status['message'] .= "Not enough parameters. Parameters sent in were <pre>". $data ."</pre> ";
452 $status['message'] .= "You need to pass in the mid of the map to be saved to, ";
453 $status['message'] .= "and the x and y coordinates of the tile to save.";
454
455 $status['function'] = '_mapapi_tile_update';
456 return FALSE;
457 }
458 // The query itself...
459 $update_query = "UPDATE {mapapi_tile_definition} SET description = '%s' WHERE tid = %d";
460 if (db_query($update_query, serialize($data['description']), $data['tid'])) {
461 $status['tile'] = TRUE;
462 return TRUE;
463 }
464 else {
465 return FALSE;
466 }
467 }
468
469
470 function mapapi_tile_delete($tid) {
471 // The status vairable is an array,
472 // indecating the different status
473 // items.
474 // It is a keyed array containing
475 // information about the success
476 // of the query, any debug messages,
477 // this function name
478 $status['query'] = FALSE;
479 $status['message'] = "";
480 $status['function'] = "mapapi_tile_save";
481 $status['overall'] = FALSE;
482 $del_tile_content_query = "DELETE FROM {mapapi_tile_content} WHERE tid = %d";
483 if(!db_query($del_tile_content_query, $tid)){
484 //do something because deleting tile failed!
485 $query_status = false;
486 }
487 $del_tile_definition_query = "DELETE FROM {mapapi_tile_definition} WHERE tid = %d";
488 if(!db_query($del_tile_definition_query, $tid)){
489 //handle failed query
490 $query_status = false;
491 }
492 return $query_status;
493 }
494 /**
495 * inserts tile content
496 *
497 * @param $data
498 * @param $status
499 *
500 * $content_format = array(
501 * 'tid' => 1,
502 * 'data' => array()
503 * );
504 * @return bool
505 */
506 function mapapi_content_save($data, &$status){
507 // Check if the content is set.
508 // The other items are checked by mapapi_tile_save
509 if (!isset($data['content'])) {
510 return FALSE;
511 }
512 $content_query = "REPLACE INTO {mapapi_tile_content} (tid, mid, content) VALUES (%d, %d, '%s')";
513 $content_args[] = $data['tid'];
514 $content_args[] = $data['mid'];
515 $content_args[] = serialize($data['content']);
516 if(db_query($content_query, $content_args)){
517 return true;
518 }
519 return false;
520 }
521
522
523 function mapapi_content_delete($tid){
524 $content_query = "DELETE FROM {mapapi_tile_content} WHERE tid = %d";
525 if(db_query($content_query,$tid)){
526 return true;
527 }
528 return false;
529 }
530
531
532 /**
533 * Saves map data. $args has no practical use now, reserved for later addons
534 * @example
535 * $map_format = array(
536 * 'mid' => 1, //optional
537 * 'limit_x' => '6',
538 * 'limit_y' => '7',
539 * 'name' => 'New map name', //optional
540 * );
541 *
542 * @param array $data
543 * @param array $args
544 */
545 function mapapi_map_save($data,$args = array()){
546 if(!isset($data['mid']) && isset($data['name'])){
547 //find the mid by map name
548 $query = "SELECT mid FROM {mapapi_map_definition} WHERE name LIKE ('%s')"; $query_arg[] = db_escape_string($data['name']);
549 $success = false;
550 if($result = db_query($query, $query_arg)){
551 $success = true;
552 }
553 if($success && db_num_rows($result) > 0){
554 $mid = db_fetch_array($result);
555 $data['mid'] = $mid['mid'];
556 } else {
557 $data['mid'] = db_next_id("mapapi_map_definition");
558 }
559 } else {
560 $data['mid'] = db_next_id("mapapi_map_definition");
561 }
562 return _mapapi_map_save($data,$args);
563 }
564
565 function _mapapi_map_save($data,$args = array()) {
566 //make sure $data is of correct format
567 if(!isset($data['mid']) || !isset($data['limit_x']) || !isset($data['limit_y']) || !isset($data['name'])){
568 return false;
569 }
570 $insert_query = "REPLACE INTO {mapapi_map_definition} (mid, limit_x, limit_y, name) VALUES (%d, %d, %d, '%s')";
571 $insert_query_args = array();
572 $insert_query_args[] = $data['mid'];
573 $insert_query_args[] = $data['limit_x'];
574 $insert_query_args[] = $data['limit_y'];
575 $insert_query_args[] = db_escape_string($data['name']);
576 if(db_query($insert_query,$insert_query_args)){
577 return true; //successful insert
578 } else {
579 return false; // unsuccessful insert
580 }
581 }
582 function mapapi_map_delete($mid) {
583 // Return at the end of the function, This is not very descriptive at which stage this was set to false
584 $query_status = true;
585 // Delete tile contents
586 $content_query = "DELETE FROM {mapapi_tile_content} WHERE {mapapi_tile_content}.mid = %d";
587 if (!db_query($content_query $mid)){
588 $query_status = false;
589 }
590 // Delete tiles
591 $tiles_query = "DELETE FROM {mapapi_tile_definition} WHERE mid = %d";
592 if (!db_query($tiles_query, $mid)){
593 $query_status = false;
594 }
595 //delete map
596 $map_query = "DELETE FROM {mapapi_map_definition} WHERE mid = %d";
597 if (!db_query($map_query, $mid)){
598 $query_status = false;
599 }
600 // All data from this particular $mid was deleted
601 return $query_status;
602 }

  ViewVC Help
Powered by ViewVC 1.1.2