forked from friendica/friendica-addons
274 lines
10 KiB
PHP
274 lines
10 KiB
PHP
<?php
|
|
/**
|
|
* Name: Photo Track
|
|
* Description: Track which photos are actually being used and delete any others
|
|
* Version: 1.0
|
|
* Author: Matthew Exon <http://mat.exon.name>
|
|
*/
|
|
|
|
/*
|
|
* List of tables and the fields that are checked:
|
|
*
|
|
* contact: photo thumb micro about
|
|
* fcontact: photo
|
|
* fsuggest: photo
|
|
* gcontact: photo about
|
|
* item: body
|
|
* item-content: body
|
|
* mail: from-photo
|
|
* notify: photo
|
|
* profile: photo thumb about
|
|
*/
|
|
|
|
use Friendica\Core\Addon;
|
|
use Friendica\Core\Logger;
|
|
use Friendica\Object\Image;
|
|
use Friendica\Database\DBA;
|
|
use Friendica\Util\Images;
|
|
use Friendica\Util\DateTimeFormat;
|
|
use Friendica\DI;
|
|
|
|
if (!defined('PHOTOTRACK_DEFAULT_BATCH_SIZE')) {
|
|
define('PHOTOTRACK_DEFAULT_BATCH_SIZE', 1000);
|
|
}
|
|
// Time in *minutes* between searching for photo uses
|
|
if (!defined('PHOTOTRACK_DEFAULT_SEARCH_INTERVAL')) {
|
|
define('PHOTOTRACK_DEFAULT_SEARCH_INTERVAL', 10);
|
|
}
|
|
|
|
function phototrack_install() {
|
|
global $db;
|
|
|
|
Addon::registerHook('post_local_end', 'addon/phototrack/phototrack.php', 'phototrack_post_local_end');
|
|
Addon::registerHook('post_remote_end', 'addon/phototrack/phototrack.php', 'phototrack_post_remote_end');
|
|
Addon::registerHook('notifier_end', 'addon/phototrack/phototrack.php', 'phototrack_notifier_end');
|
|
Addon::registerHook('cron', 'addon/phototrack/phototrack.php', 'phototrack_cron');
|
|
|
|
if (DI::config()->get('phototrack', 'dbversion') != '0.1') {
|
|
$schema = file_get_contents(dirname(__file__).'/database.sql');
|
|
$arr = explode(';', $schema);
|
|
foreach ($arr as $a) {
|
|
if (!DBA::e($a)) {
|
|
Logger::warning('Unable to create database table: ' . DBA::errorMessage());
|
|
return;
|
|
}
|
|
}
|
|
DI::config()->set('phototrack', 'dbversion', '0.1');
|
|
}
|
|
}
|
|
|
|
function phototrack_uninstall() {
|
|
Addon::unregisterHook('post_local_end', 'addon/phototrack/phototrack.php', 'phototrack_post_local_end');
|
|
Addon::unregisterHook('post_remote_end', 'addon/phototrack/phototrack.php', 'phototrack_post_remote_end');
|
|
Addon::unregisterHook('notifier_end', 'addon/phototrack/phototrack.php', 'phototrack_notifier_end');
|
|
Addon::unregisterHook('cron', 'addon/phototrack/phototrack.php', 'phototrack_cron');
|
|
}
|
|
|
|
function phototrack_module() {}
|
|
|
|
function phototrack_finished_row($table, $id) {
|
|
$existing = DBA::selectFirst('phototrack_row_check', ['id'], ['table' => $table, 'row-id' => $id]);
|
|
if (!is_bool($existing)) {
|
|
DBA::update('phototrack_row_check', ['checked' => DateTimeFormat::utcNow()], ['table' => $table, 'row-id' = $id]);
|
|
}
|
|
else {
|
|
DBA::insert('phototrack_row_check', ['table' => $table, 'row-id' = $id, 'checked' => DateTimeFormat::utcNow()]);
|
|
}
|
|
}
|
|
|
|
function phototrack_photo_use($photo, $table, $field, $id) {
|
|
Logger::debug('@@@ phototrack_photo_use ' . $photo);
|
|
foreach (Images::supportedTypes() as $m => $e) {
|
|
$photo = str_replace(".$e", '', $photo);
|
|
}
|
|
if (substr($photo, -2, 1) == '-') {
|
|
$resolution = intval(substr($photo,-1,1));
|
|
$photo = substr($photo,0,-2);
|
|
}
|
|
if (strlen($photo) != 32) {
|
|
return;
|
|
}
|
|
$r = DBA::selectFirst('photo', ['resource-id'], ['resource-id' => $photo]);
|
|
if (!DBA::isResult($r)) {
|
|
return;
|
|
}
|
|
$rid = $r['resource-id'];
|
|
$existing = DBA::selectFirst('phototrack_photo_use', ['id'], ['resource-id' => $rid, 'table' => $table, 'field' => $field, 'row-id' = $id]);
|
|
if (DBA::isResult($existing)) {
|
|
DBA::update('phototrack_photo_use', ['checked' => DateTimeFormat::utcNow()], ['resource-id' => $rid, 'table' => $table, 'field' => $field, 'row-id' = $id]);
|
|
}
|
|
else {
|
|
DBA::insert('phototrack_photo_use', ['resource-id' => $rid, 'table' => $table, 'field' => $field, 'row-id' = $id, 'checked' => DateTimeFormat::utcNow()]);
|
|
}
|
|
}
|
|
|
|
function phototrack_check_field_url($a, $table, $field, $id, $url) {
|
|
Logger::info('@@@ phototrack_check_field_url table ' . $table . ' field ' . $field . ' id ' . $id . ' url ' . $url);
|
|
$baseurl = DI::baseUrl()->get(true);
|
|
if (strpos($url, $baseurl) === FALSE) {
|
|
return;
|
|
}
|
|
else {
|
|
$url = substr($url, strlen($baseurl));
|
|
Logger::info('@@@ phototrack_check_field_url funny url stuff ' . $url . ' base ' . $baseurl);
|
|
}
|
|
if (strpos($url, '/photo/') === FALSE) {
|
|
return;
|
|
}
|
|
else {
|
|
$url = substr($url, strlen('/photo/'));
|
|
Logger::info('@@@ phototrack_check_field_url more url stuff ' . $url);
|
|
}
|
|
if (preg_match('/([0-9a-z]{32})/', $url, $matches)) {
|
|
$rid = $matches[0];
|
|
Logger::info('@@@ phototrack_check_field_url rid ' . $rid);
|
|
phototrack_photo_use($rid, $table, $field, $id);
|
|
}
|
|
}
|
|
|
|
function phototrack_check_field_bbcode($a, $table, $field, $id, $value) {
|
|
$baseurl = DI::baseUrl()->get(true);
|
|
$matches = array();
|
|
preg_match_all("/\[img(\=([0-9]*)x([0-9]*))?\](.*?)\[\/img\]/ism", $value, $matches);
|
|
foreach ($matches[4] as $url) {
|
|
phototrack_check_field_url($a, $table, $field, $id, $url);
|
|
}
|
|
}
|
|
|
|
function phototrack_post_local_end(&$a, &$item) {
|
|
phototrack_check_row($a, 'item', $item);
|
|
phototrack_check_row($a, 'item-content', $item);
|
|
}
|
|
|
|
function phototrack_post_remote_end(&$a, &$item) {
|
|
phototrack_check_row($a, 'item', $item);
|
|
phototrack_check_row($a, 'item-content', $item);
|
|
}
|
|
|
|
function phototrack_notifier_end($item) {
|
|
}
|
|
|
|
function phototrack_check_row($a, $table, $row) {
|
|
switch ($table) {
|
|
case 'item':
|
|
$fields = array(
|
|
'body' => 'bbcode');
|
|
break;
|
|
case 'item-content':
|
|
$fields = array(
|
|
'body' => 'bbcode');
|
|
break;
|
|
case 'contact':
|
|
$fields = array(
|
|
'photo' => 'url',
|
|
'thumb' => 'url',
|
|
'micro' => 'url',
|
|
'about' => 'bbcode');
|
|
break;
|
|
case 'fcontact':
|
|
$fields = array(
|
|
'photo' => 'url');
|
|
break;
|
|
case 'fsuggest':
|
|
$fields = array(
|
|
'photo' => 'url');
|
|
break;
|
|
case 'gcontact':
|
|
$fields = array(
|
|
'photo' => 'url',
|
|
'about' => 'bbcode');
|
|
break;
|
|
default: $fields = array(); break;
|
|
}
|
|
foreach ($fields as $field => $type) {
|
|
switch ($type) {
|
|
case 'bbcode': phototrack_check_field_bbcode($a, $table, $field, $row['id'], $row[$field]); break;
|
|
case 'url': phototrack_check_field_url($a, $table, $field, $row['id'], $row[$field]); break;
|
|
}
|
|
}
|
|
phototrack_finished_row($table, $row['id']);
|
|
}
|
|
|
|
function phototrack_batch_size() {
|
|
$batch_size = DI::config()->get('phototrack', 'batch_size');
|
|
if ($batch_size > 0) {
|
|
return $batch_size;
|
|
}
|
|
return PHOTOTRACK_DEFAULT_BATCH_SIZE;
|
|
}
|
|
|
|
function phototrack_search_table($a, $table) {
|
|
$batch_size = phototrack_batch_size();
|
|
$rows = DBA::p("SELECT `$table`.* FROM `$table` LEFT OUTER JOIN phototrack_row_check ON ( phototrack_row_check.`table` = '$table' AND phototrack_row_check.`row-id` = `$table`.id ) WHERE ( ( phototrack_row_check.checked IS NULL ) OR ( phototrack_row_check.checked < DATE_SUB(NOW(), INTERVAL 1 MONTH) ) ) ORDER BY phototrack_row_check.checked LIMIT $batch_size");
|
|
if (DBA::isResult($rows)) {
|
|
while ($row = DBA::fetch($rows)) {
|
|
phototrack_check_row($a, $table, $row);
|
|
}
|
|
}
|
|
$r = DBA::p("SELECT COUNT(*) FROM `$table` LEFT OUTER JOIN phototrack_row_check ON ( phototrack_row_check.`table` = '$table' AND phototrack_row_check.`row-id` = `$table`.id ) WHERE ( ( phototrack_row_check.checked IS NULL ) OR ( phototrack_row_check.checked < DATE_SUB(NOW(), INTERVAL 1 MONTH) ) )");
|
|
$remaining = DBA::fetch($r)['COUNT(*)'];
|
|
Logger::info('phototrack: searched ' . count($rows) . ' rows in table ' . $table . ', ' . $remaining . ' still remaining to search');
|
|
return $remaining;
|
|
}
|
|
|
|
function phototrack_cron_time() {
|
|
$prev_remaining = DI::config()->get('phototrack', 'remaining_items');
|
|
if ($prev_remaining > 10 * phototrack_batch_size()) {
|
|
Logger::debug('phototrack: more than ' . (10 * phototrack_batch_size()) . ' items remaining');
|
|
return true;
|
|
}
|
|
$last = DI::config()->get('phototrack', 'last_search');
|
|
$search_interval = intval(DI::config()->get('phototrack', 'search_interval'));
|
|
if (!$search_interval) {
|
|
$search_interval = PHOTOTRACK_DEFAULT_SEARCH_INTERVAL;
|
|
}
|
|
if ($last) {
|
|
$next = $last + ($search_interval * 60);
|
|
if ($next > time()) {
|
|
Logger::debug('phototrack: search interval not reached');
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function phototrack_cron($a, $b) {
|
|
if (!phototrack_cron_time()) {
|
|
return;
|
|
}
|
|
DI::config()->set('phototrack', 'last_search', time());
|
|
|
|
$remaining = 0;
|
|
$remaining += phototrack_search_table($a, 'item');
|
|
$remaining += phototrack_search_table($a, 'item-content');
|
|
$remaining += phototrack_search_table($a, 'contact');
|
|
$remaining += phototrack_search_table($a, 'fcontact');
|
|
$remaining += phototrack_search_table($a, 'fsuggest');
|
|
$remaining += phototrack_search_table($a, 'gcontact');
|
|
|
|
DI::config()->set('phototrack', 'remaining_items', $remaining);
|
|
if ($remaining === 0) {
|
|
phototrack_tidy();
|
|
}
|
|
}
|
|
|
|
function phototrack_tidy() {
|
|
$batch_size = phototrack_batch_size();
|
|
DBA::e('CREATE TABLE IF NOT EXISTS `phototrack-temp` (`resource-id` char(255) not null)');
|
|
DBA::e('INSERT INTO `phototrack-temp` SELECT DISTINCT(`resource-id`) FROM photo WHERE photo.`created` < DATE_SUB(NOW(), INTERVAL 2 MONTH)');
|
|
$rows = DBA::p('SELECT `phototrack-temp`.`resource-id` FROM `phototrack-temp` LEFT OUTER JOIN phototrack_photo_use ON (`phototrack-temp`.`resource-id` = phototrack_photo_use.`resource-id`) WHERE phototrack_photo_use.id IS NULL limit ' . /*$batch_size*/1000);
|
|
if (DBA::isResult($rows)) {
|
|
foreach ($rows as $row) {
|
|
Logger::debug('phototrack: remove photo ' . $row['resource-id']);
|
|
DBA::e('DELETE FROM photo WHERE `resource-id` = "' . $row['resource-id'] . '"');
|
|
}
|
|
Logger::info('phototrack_tidy: deleted ' . count($rows) . ' photos');
|
|
}
|
|
DBA::e('DROP TABLE `phototrack-temp`');
|
|
$rows = DBA::p('SELECT id FROM phototrack_photo_use WHERE checked < DATE_SUB(NOW(), INTERVAL 14 DAY)');
|
|
foreach ($rows as $row) {
|
|
DBA::e( 'DELETE FROM phototrack_photo_use WHERE id = ' . $row['id']);
|
|
}
|
|
Logger::info('phototrack_tidy: deleted ' . count($rows) . ' phototrack_photo_use rows');
|
|
}
|