static function call(OkapiRequest $request) { require_once 'log_images_common.inc.php'; list($image_uuid, $log_internal_id) = LogImagesCommon::validate_image_uuid($request); $image_uuid_escaped = Db::escape_string($image_uuid); Db::execute('start transaction'); $image_row = Db::select_row("\n select id, node, url, local\n from pictures\n where uuid = '" . $image_uuid_escaped . "'\n "); Db::execute("\n delete from pictures where uuid = '" . $image_uuid_escaped . "'\n "); # Remember that OCPL picture sequence numbers are always 1, and # OCDE sequence numbers may have gaps. So we do not need to adjust # any numbers after deleting from table 'pictures'. if (Settings::get('OC_BRANCH') == 'oc.de') { # OCDE does all the housekeeping by triggers } else { Db::execute("\n INSERT INTO removed_objects (\n localID, uuid, type, removed_date, node\n )\n VALUES (\n " . $image_row['id'] . "\n '" . $image_uuid_escaped . "',\n 6,\n NOW(),\n " . $image_row['node'] . "\n )\n "); # This will also update cache_logs.okapi_syncbase, so that replication # can output the updated log entry with one image less. For OCDE # that's done by DB trigges. Db::execute("\n update cache_logs\n set\n picturescount = greatest(0, picturescount - 1),\n last_modified = NOW()\n where id = '" . Db::escape_string($log_internal_id) . "'\n "); } Db::execute('commit'); if ($image_row['local']) { $filename = basename($image_row['url']); unlink(Settings::get('IMAGES_DIR') . '/' . $filename); } $result = array('success' => true); return Okapi::formatted_response($request, $result); }
/** * Edit an log entry image and return its (new) position. * Throws CannotPublishException or BadRequest on errors. */ private static function _call(OkapiRequest $request) { # Developers! Please notice the fundamental difference between throwing # CannotPublishException and the "standard" BadRequest/InvalidParam # exceptions. CannotPublishException will be caught by the service's # call() function and returns a message to be displayed to the user. require_once 'log_images_common.inc.php'; # validate the 'image_uuid' parameter list($image_uuid, $log_internal_id) = LogImagesCommon::validate_image_uuid($request); # validate the 'caption', 'is_spoiler' and 'position' parameters $caption = $request->get_parameter('caption'); if ($caption !== null && $caption == '') { throw new CannotPublishException(sprintf(_("Please enter an image caption."), Okapi::get_normalized_site_name())); } $is_spoiler = $request->get_parameter('is_spoiler'); if ($is_spoiler !== null) { if (!in_array($is_spoiler, array('true', 'false'))) { throw new InvalidParam('is_spoiler'); } } $position = LogImagesCommon::validate_position($request); if ($caption === null && $is_spoiler === null && $position === null) { # If no-params were allowed, what would be the success message? # It's more reasonable to assume that this was a developer's error. throw new BadRequest("At least one of the parameters 'caption', 'is_spoiler' and 'position' must be supplied"); } $image_uuid_escaped = Db::escape_string($image_uuid); $log_entry_modified = false; # update caption if ($caption !== null) { Db::execute("\n update pictures\n set title = '" . Db::escape_string($caption) . "'\n where uuid = '" . $image_uuid_escaped . "'\n "); $log_entry_modified = true; } # update spoiler flag if ($is_spoiler !== null) { Db::execute("\n update pictures\n set spoiler = " . ($is_spoiler == 'true' ? 1 : 0) . "\n where uuid = '" . $image_uuid_escaped . "'\n "); $log_entry_modified = true; } # update position if ($position !== null) { if (Settings::get('OC_BRANCH') == 'oc.pl') { # OCPL as no arbitrary log picture ordering => ignore position parameter # and return the picture's current position. $image_uuids = Db::select_column("\n select uuid from pictures\n where object_type = 1 and object_id = '" . Db::escape_string($log_internal_id) . "'\n order by date_created\n "); $position = array_search($image_uuid, $image_uuids); } else { list($position, $seq) = LogImagesCommon::prepare_position($log_internal_id, $position, 0); # For OCDE the pictures table is write locked now. $old_seq = DB::select_value("\n select seq from pictures where uuid = '" . $image_uuid_escaped . "'\n "); if ($seq != $old_seq) { # First move the edited picture to the end, to make space for rotating. # Remember that we have no transactions at OC.de. If something goes wrong, # the image will stay at the end of the list. $max_seq = Db::select_value("\n select max(seq)\n from pictures\n where object_type = 1 and object_id = '" . Db::escape_string($log_internal_id) . "'\n "); Db::query("\n update pictures\n set seq = '" . Db::escape_string($max_seq + 1) . "'\n where uuid = '" . $image_uuid_escaped . "'\n "); # now move the pictures inbetween if ($seq < $old_seq) { Db::execute("\n update pictures\n set seq = seq + 1\n where\n object_type = 1\n and object_id = '" . Db::escape_string($log_internal_id) . "'\n and seq >= '" . Db::escape_string($seq) . "'\n and seq < '" . Db::escape_string($old_seq) . "'\n order by seq desc\n "); } else { Db::execute("\n update pictures\n set seq = seq - 1\n where\n object_type = 1\n and object_id = '" . Db::escape_string($log_internal_id) . "'\n and seq <= '" . Db::escape_string($seq) . "'\n and seq > '" . Db::escape_string($old_seq) . "'\n order by seq asc\n "); } # and finally move the edited picture into place Db::query("\n update pictures\n set seq = '" . Db::escape_string($seq) . "'\n where uuid = '" . $image_uuid_escaped . "'\n "); } Db::execute('unlock tables'); $log_entry_modified = true; } } if (Settings::get('OC_BRANCH') == 'oc.pl' && $log_entry_modified) { # OCDE touches the log entry via trigger, OCPL needs an explicit update. # This will also update okapi_syncbase. Db::query("\n update cache_logs\n set last_modified = NOW()\n where id = '" . Db::escape_string($log_internal_id) . "'\n "); # OCPL code currently does not update pictures.last_modified when # editing, but that is a bug, see # https://github.com/opencaching/opencaching-pl/issues/341. } return $position; }
private static function db_insert_image($consumer_key, $user_id, $log_internal_id, $image_uuid, $position, $caption, $is_spoiler, $file_ext) { require_once 'log_images_common.inc.php'; list($position, $seq, $log_images_count) = LogImagesCommon::prepare_position($log_internal_id, $position, +1); # For OCDE the pictures table is write locked now. # Transactions do not work on OCDE MyISAM tables. However, the worst # thing that can happen on OCDE is creating a sequence number gap, # which is allowed. # # For OCPL InnoDB tables, the transactions DO and MUST work, because # we write to two dependent tables. Db::execute('start transaction'); # shift positions of existing images to make space for the new one if ($position < $log_images_count && Settings::get('OC_BRANCH') == 'oc.de') { Db::execute("\n update pictures\n set seq = seq + 1\n where\n object_type = 1\n and object_id = '" . Db::escape_string($log_internal_id) . "'\n and seq >= '" . Db::escape_string($seq) . "'\n order by seq desc\n "); } if (Settings::get('OC_BRANCH') == 'oc.de') { $local_fields_SQL = "seq"; $local_values_escaped_SQL = "'" . Db::escape_string($seq) . "'"; # All other fields are set by trigger or defaults for OCDE. } else { # These are the additional fields that OCPL newpic.php supplies # (seq is set from default): $local_fields_SQL = "date_created, last_modified, description, desc_html, last_url_check, user_id"; $local_values_escaped_SQL = "NOW(), NOW(), '', 0, NOW(), '" . Db::escape_string($user_id) . "'"; } Db::execute("\n insert into pictures (\n uuid, node, local, title, spoiler, url, object_type, object_id,\n unknown_format, display,\n " . $local_fields_SQL . "\n )\n values (\n '" . Db::escape_string($image_uuid) . "',\n '" . Db::escape_string(Settings::get('OC_NODE_ID')) . "',\n 1,\n '" . Db::escape_string($caption) . "',\n '" . ($is_spoiler == 'true' ? 1 : 0) . "',\n '" . Db::escape_string(Settings::get('IMAGES_URL') . $image_uuid . $file_ext) . "',\n 1,\n '" . Db::escape_string($log_internal_id) . "',\n 0,\n 1,\n " . $local_values_escaped_SQL . "\n )\n "); $image_internal_id = Db::last_insert_id(); # update OCPL log entry properties; OCDE does everything necessary by triggers if (Settings::get('OC_BRANCH') == 'oc.pl') { # This will also update cache_logs.okapi_syncbase, so that replication # can output the updated log entry with one image less. For OCDE # that's done by DB triggers. Db::execute("\n update cache_logs\n set\n picturescount = picturescount + 1,\n last_modified = NOW()\n where id = '" . Db::escape_string($log_internal_id) . "'\n "); } # Store information on the consumer_key which uploaded this image. # (Maybe we'll want to display this somewhen later.) Db::execute("\n insert into okapi_submitted_objects (object_type, object_id, consumer_key)\n values (\n '" . Okapi::OBJECT_TYPE_CACHE_LOG_IMAGE . "',\n '" . Db::escape_string($image_internal_id) . "',\n '" . Db::escape_string($consumer_key) . "'\n );\n "); Db::execute('commit'); Db::execute('unlock tables'); return $position; }