Skip to content

Commit

Permalink
wip refactor to use classes
Browse files Browse the repository at this point in the history
  • Loading branch information
westnordost authored and exploide committed Jul 21, 2020
1 parent 521d786 commit 23188fa
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 146 deletions.
10 changes: 10 additions & 0 deletions classes/OSMPhotoNote.class.php
@@ -0,0 +1,10 @@
<?php

/** Represents an OSM note to which a photo is attached */
class OSMPhotoNote
{
public $note_id;
public $status;
public $closed_at;
public $photo_ids;
}
104 changes: 104 additions & 0 deletions classes/OSMPhotoNoteDao.class.php
@@ -0,0 +1,104 @@
<?php

/** Persists OSMPhotoNotes */
class OSMPhotoNoteDao
{
private $mysqli;

public function __construct($mysqli)
{
$this->mysqli = $mysqli;
$this->createTable();
}

private function createTable()
{
$this->mysqli->query(
'CREATE TABLE IF NOT EXISTS photos(
file_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
file_ext VARCHAR(10) NOT NULL,
creation_time DATETIME NOT NULL,
note_id BIGINT UNSIGNED
)'
);
}

public function newPhoto($file_ext)
{
$stmt = $this->mysqli->prepare(
'INSERT INTO photos(file_ext, creation_time)
VALUES (?, NOW())'
);
$stmt->bind_param('s', $file_ext);
$stmt->execute();
return $this->mysqli->insert_id;
}

public function deletePhoto(int $file_id)
{
$stmt = $this->mysqli->prepare('DELETE FROM photos WHERE file_id=?');
$stmt->bind_param('i', $file_id);
$stmt->execute();
}

public function getOldInactivePhotos(): array
{
$stmt = $this->mysqli->prepare(
'SELECT file_id, file_ext, note_id FROM photos
WHERE note_id IS NULL
AND creation_time < ADDDATE(NOW(), INTERVAL -? HOUR)'
);
$max_age = Config::MAX_TMP_LIFETIME_HOURS;
$stmt->bind_param('i', $max_age);
$stmt->execute();
$result = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
return $result;
}

public function getOldestActivePhotos(int $num): array
{
$stmt = $this->mysqli->prepare(
'SELECT file_id, file_ext, note_id FROM photos
WHERE note_id IS NOT NULL
ORDER BY creation_time
LIMIT ?'
);
$stmt->bind_param('i', $num);
$stmt->execute();
$result = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
return $result;
}

public function getActivePhotos(): array
{
$result = $this->mysqli->query(
'SELECT file_id, file_ext, note_id FROM photos
WHERE note_id IS NOT NULL
ORDER BY creation_time DESC'
);
return $result->fetch_all(MYSQLI_ASSOC);
}

public function getInactivePhotos(array $photo_ids): array
{
$in = str_repeat('?,', count($photo_ids) - 1) . '?';
$stmt = $this->mysqli->prepare(
"SELECT file_id, file_ext FROM photos
WHERE file_id IN ($in)
AND note_id IS NULL"
);
$stmt->bind_param(str_repeat('i', count($photo_ids)), ...$photo_ids);
$stmt->execute();
return $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
}

public function activatePhoto(int $photo_id, int $note_id)
{
$stmt = $this->mysqli->prepare(
"UPDATE photos SET note_id = ?
WHERE file_id = ?"
);
$stmt->bind_param('ii', $note_id, $photo_id);
$stmt->execute();
}
}
50 changes: 50 additions & 0 deletions classes/OSMPhotoNoteFetcher.class.php
@@ -0,0 +1,50 @@
<?php
require_once 'OSMPhotoNoteParser.class.php';
require_once 'OSMPhotoNote.class.php';

/** Fetches photo notes from the OSM API 0.6
*
* See https://wiki.openstreetmap.org/wiki/API_v0.6#Read:_GET_.2Fapi.2F0.6.2Fnotes.2F.23id */
class OSMPhotoNoteFetcher
{
const OSM_NOTES_API = 'https://api.openstreetmap.org/api/0.6/notes/';

private $user;
private $pass;
private $parser;

public function __construct(string $photos_url, string $user = null, string $pass = null)
{
$this->user = $user;
$this->pass = $pass;
$this->parser = new OSMPhotoNoteParser($photos_url);
}

public function fetch(int $note_id): ?OSMPhotoNote
{
$url = self::OSM_NOTES_API . strval($note_id) . '.json';
$response = fetchUrl($url, $this->user, $this->pass);
if ($response->code == 404 || $response->code == 410) {
return null;
}
else if ($response->code != 200) {
throw new Exception('OSM API returned error code ' . $response->code);
}
return $this->parser->parse($response->body);
}

function fetchUrl($url, $user = null, $pass = null)
{
$response = new stdClass();
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_USERAGENT, 'StreetComplete Photo Service');
if ($user !== null and $pass !== null) {
curl_setopt($curl, CURLOPT_USERPWD, $user . ":" . $pass);
}
$response->body = curl_exec($curl);
$response->code = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
curl_close($curl);
return $response;
}
}
38 changes: 38 additions & 0 deletions classes/OSMPhotoNoteParser.class.php
@@ -0,0 +1,38 @@
<?php

require_once 'OSMPhotoNote.class.php';

/** Parses OSM note into the OSMPhotoNote data structure */
class OSMPhotoNoteParser
{
private $photos_url;

public function __construct(string $photos_url)
{
$this->photos_url = $photos_url;
}

public function parse(string $json): OSMPhotoNote
{
$note = json_decode($response->body, true);

$r = new OSMPhotoNote();
$r->note_id = $note['properties']['id'];
$r->status = $note['properties']['status'];
if ($r->status == 'closed') {
$r->closed_at = $note['properties']['closed_at'];
}

$relevant_comments = "";
foreach ($note['properties']['comments'] as $comment) {
if (array_key_exists('uid', $comment)) {
$relevant_comments .= "\n" . $comment['text'];
}
}
$search_regex = '~(?<!\S)' . preg_quote(trim($this->photos_url, '/')) . '/(\d+)\.[a-z]+(?!\S)~i';
preg_match_all($search_regex, $relevant_comments, $matches);
$r->photo_ids = array_unique(array_map('intval', $matches[1]));

return $r;
}
}
3 changes: 2 additions & 1 deletion cleanup.php
Expand Up @@ -12,7 +12,8 @@ function deletePhoto($photo)
{
global $db_helper;
$file_path = ($photo['note_id']==NULL ? Config::PHOTOS_TMP_DIR : Config::PHOTOS_SRV_DIR) . DIRECTORY_SEPARATOR . $photo['file_id'] . $photo['file_ext'];
$success = unlink($file_path);
echo "delete photo ".$photo['file_id']."\n";
$success = unlink($file_path);
if ($success) {
$db_helper->deletePhoto($photo['file_id']);
} else {
Expand Down
89 changes: 0 additions & 89 deletions db_helper.php
Expand Up @@ -16,93 +16,4 @@ public function __destruct()
$this->_connection->close();
}

public function createTable()
{
$this->_connection->query(
'CREATE TABLE IF NOT EXISTS photos(
file_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
file_ext VARCHAR(10) NOT NULL,
creation_time DATETIME NOT NULL,
note_id BIGINT UNSIGNED
)'
);
}

public function newPhoto($file_ext)
{
$stmt = $this->_connection->prepare(
'INSERT INTO photos(file_ext, creation_time)
VALUES (?, NOW())'
);
$stmt->bind_param('s', $file_ext);
$stmt->execute();
return $this->_connection->insert_id;
}

public function deletePhoto($file_id)
{
$stmt = $this->_connection->prepare('DELETE FROM photos WHERE file_id=?');
$stmt->bind_param('i', $file_id);
$stmt->execute();
}

public function getOldInactivePhotos()
{
$stmt = $this->_connection->prepare(
'SELECT file_id, file_ext, note_id FROM photos
WHERE note_id IS NULL
AND creation_time < ADDDATE(NOW(), INTERVAL -? HOUR)'
);
$max_age = Config::MAX_TMP_LIFETIME_HOURS;
$stmt->bind_param('i', $max_age);
$stmt->execute();
$result = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
return $result;
}

public function getOldestActivePhotos($num)
{
$stmt = $this->_connection->prepare(
'SELECT file_id, file_ext, note_id FROM photos
WHERE note_id IS NOT NULL
ORDER BY creation_time
LIMIT ?'
);
$stmt->bind_param('i', $num);
$stmt->execute();
$result = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
return $result;
}

public function getActivePhotos()
{
$result = $this->_connection->query(
'SELECT file_id, file_ext, note_id
FROM photos WHERE note_id IS NOT NULL'
);
return $result->fetch_all(MYSQLI_ASSOC);
}

public function getInactivePhotos($photo_ids)
{
$in = str_repeat('?,', count($photo_ids) - 1) . '?';
$stmt = $this->_connection->prepare(
"SELECT file_id, file_ext FROM photos
WHERE file_id IN ($in)
AND note_id IS NULL"
);
$stmt->bind_param(str_repeat('i', count($photo_ids)), ...$photo_ids);
$stmt->execute();
return $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
}

public function activatePhoto($photo_id, $note_id)
{
$stmt = $this->_connection->prepare(
"UPDATE photos SET note_id = ?
WHERE file_id = ?"
);
$stmt->bind_param('ii', $note_id, $photo_id);
$stmt->execute();
}
}
14 changes: 0 additions & 14 deletions helper.php
Expand Up @@ -6,20 +6,6 @@ function returnError($code, $message)
exit(json_encode(array('error' => $message)));
}

function fetchUrl($url, $user = null, $pass = null)
{
$response = new stdClass();
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
if ($user !== null and $pass !== null) {
curl_setopt($curl, CURLOPT_USERPWD, $user . ":" . $pass);
}
$response->body = curl_exec($curl);
$response->code = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
curl_close($curl);
return $response;
}

function directorySize($dir)
{
$size = 0;
Expand Down
42 changes: 0 additions & 42 deletions osm_photo_note.php

This file was deleted.

0 comments on commit 23188fa

Please sign in to comment.