streams/mod/photos.php

1277 lines
37 KiB
PHP
Raw Normal View History

2010-08-06 04:15:24 +00:00
<?php
2013-04-26 03:01:24 +00:00
require_once('include/photo/photo_driver.php');
2013-01-26 02:13:15 +00:00
require_once('include/photos.php');
require_once('include/items.php');
2010-11-16 05:02:59 +00:00
require_once('include/acl_selectors.php');
2010-11-02 06:42:26 +00:00
require_once('include/bbcode.php');
require_once('include/security.php');
2013-01-26 07:32:44 +00:00
require_once('include/Contact.php');
require_once('include/attach.php');
require_once('include/text.php');
2010-08-06 04:15:24 +00:00
2012-06-07 15:42:13 +00:00
2010-08-06 04:15:24 +00:00
function photos_init(&$a) {
2015-01-29 04:58:59 +00:00
if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
return;
}
2013-01-26 11:42:05 +00:00
$o = '';
2012-10-24 04:24:23 +00:00
if(argc() > 1) {
$nick = argv(1);
profile_load($a,$nick);
2013-01-26 10:24:07 +00:00
$channelx = channelx_by_nick($nick);
2010-08-06 04:15:24 +00:00
2013-01-26 10:24:07 +00:00
if(! $channelx)
2010-08-06 04:15:24 +00:00
return;
$a->data['channel'] = $channelx;
2010-08-06 04:15:24 +00:00
$observer = $a->get_observer();
2013-01-26 07:32:44 +00:00
$a->data['observer'] = $observer;
2013-01-26 07:32:44 +00:00
$observer_xchan = (($observer) ? $observer['xchan_hash'] : '');
head_set_icon($a->data['channel']['xchan_photo_s']);
2013-11-14 23:53:31 +00:00
$a->page['htmlhead'] .= "<script> var ispublic = '" . t('everybody') . "'; var profile_uid = " . (($a->data['channel']) ? $a->data['channel']['channel_id'] : 0) . "; </script>" ;
2010-08-06 04:15:24 +00:00
}
2010-09-09 03:14:17 +00:00
return;
2010-08-06 04:15:24 +00:00
}
function photos_post(&$a) {
logger('mod-photos: photos_post: begin' , LOGGER_DEBUG);
logger('mod_photos: REQUEST ' . print_r($_REQUEST,true), LOGGER_DATA);
logger('mod_photos: FILES ' . print_r($_FILES,true), LOGGER_DATA);
2013-04-26 03:01:24 +00:00
$ph = photo_factory('');
$phototypes = $ph->supportedTypes();
2012-06-07 15:42:13 +00:00
$can_post = false;
$page_owner_uid = $a->data['channel']['channel_id'];
2013-02-02 23:08:11 +00:00
if(perm_is_allowed($page_owner_uid,get_observer_hash(),'post_photos'))
$can_post = true;
2010-08-06 04:15:24 +00:00
if(! $can_post) {
notice( t('Permission denied.') . EOL );
2013-01-26 11:42:05 +00:00
if(is_ajax())
killme();
return;
}
2013-01-26 11:42:05 +00:00
$s = abook_self($page_owner_uid);
2013-01-26 11:42:05 +00:00
if(! $s) {
notice( t('Page owner information could not be retrieved.') . EOL);
logger('mod_photos: post: unable to locate contact record for page owner. uid=' . $page_owner_uid);
if(is_ajax())
killme();
return;
}
2013-01-26 11:42:05 +00:00
$owner_record = $s[0];
2013-01-26 11:42:05 +00:00
if((argc() > 3) && (argv(2) === 'album')) {
2013-01-26 11:42:05 +00:00
$album = hex2bin(argv(3));
2013-01-26 11:42:05 +00:00
if($album === t('Profile Photos')) {
// not allowed
goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
}
2013-01-26 11:42:05 +00:00
if(! photos_album_exists($page_owner_uid,$album)) {
notice( t('Album not found.') . EOL);
goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
}
2013-01-26 11:42:05 +00:00
/*
* RENAME photo album
*/
$newalbum = notags(trim($_REQUEST['albumname']));
if($newalbum != $album) {
2013-01-26 11:42:05 +00:00
$x = photos_album_rename($page_owner_uid,$album,$newalbum);
if($x) {
$newurl = str_replace(bin2hex($album),bin2hex($newalbum),$_SESSION['photo_return']);
goaway($a->get_baseurl() . '/' . $newurl);
}
}
2013-01-26 11:42:05 +00:00
/*
* DELETE photo album and all its photos
*/
2013-01-26 11:42:05 +00:00
if($_REQUEST['dropalbum'] == t('Delete Album')) {
$res = array();
// get the list of photos we are about to delete
2015-01-29 04:58:59 +00:00
if(remote_channel() && (! local_channel())) {
$str = photos_album_get_db_idstr($page_owner_uid,$album,remote_channel());
}
2015-01-29 04:56:04 +00:00
elseif(local_channel()) {
$str = photos_album_get_db_idstr(local_channel(),$album);
}
else {
2013-01-26 11:42:05 +00:00
$str = null;
}
if(! $str) {
goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
}
2015-06-10 23:59:04 +00:00
$r = q("select id from item where resource_id in ( $str ) and resource_type = 'photo' and uid = %d " . item_normal(),
intval($page_owner_uid)
);
2013-01-26 11:42:05 +00:00
if($r) {
foreach($r as $i) {
attach_delete($page_owner_uid, $i['resource_id'], 1 );
drop_item($i['id'],false,DROPITEM_PHASE1,true /* force removal of linked items */);
2015-06-10 23:59:04 +00:00
proc_run('php','include/notifier.php','drop',$i['id']);
2013-01-26 11:42:05 +00:00
}
}
2013-01-26 11:42:05 +00:00
// remove the associated photos in case they weren't attached to an item
2013-01-26 11:42:05 +00:00
q("delete from photo where resource_id in ( $str ) and uid = %d",
intval($page_owner_uid)
);
// @FIXME do the same for the linked attach
}
2013-01-26 11:42:05 +00:00
goaway($a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address']);
}
2013-01-26 11:42:05 +00:00
if((argc() > 2) && (x($_REQUEST,'delete')) && ($_REQUEST['delete'] === t('Delete Photo'))) {
// same as above but remove single photo
$ob_hash = get_observer_hash();
if(! $ob_hash)
goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
$r = q("SELECT `id`, `resource_id` FROM `photo` WHERE ( xchan = '%s' or `uid` = %d ) AND `resource_id` = '%s' LIMIT 1",
dbesc($ob_hash),
2015-01-29 04:56:04 +00:00
intval(local_channel()),
dbesc($a->argv[2])
);
if($r) {
q("DELETE FROM `photo` WHERE `uid` = %d AND `resource_id` = '%s'",
intval($page_owner_uid),
dbesc($r[0]['resource_id'])
);
attach_delete($page_owner_uid, $r[0]['resource_id'], 1 );
2013-08-28 01:40:33 +00:00
$i = q("SELECT * FROM `item` WHERE `resource_id` = '%s' AND resource_type = 'photo' and `uid` = %d LIMIT 1",
dbesc($r[0]['resource_id']),
intval($page_owner_uid)
);
if(count($i)) {
2015-01-23 05:04:54 +00:00
drop_item($i[0]['id'],true,DROPITEM_PHASE1);
$url = $a->get_baseurl();
}
}
2014-11-03 09:46:57 +00:00
goaway($a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/album/' . $_SESSION['album_return']);
}
if(($a->argc > 2) && ((x($_POST,'desc') !== false) || (x($_POST,'newtag') !== false)) || (x($_POST,'albname') !== false)) {
2012-05-23 08:01:04 +00:00
$desc = ((x($_POST,'desc')) ? notags(trim($_POST['desc'])) : '');
$rawtags = ((x($_POST,'newtag')) ? notags(trim($_POST['newtag'])) : '');
$item_id = ((x($_POST,'item_id')) ? intval($_POST['item_id']) : 0);
$albname = ((x($_POST,'albname')) ? notags(trim($_POST['albname'])) : '');
2015-05-19 03:10:44 +00:00
$is_nsfw = ((x($_POST,'adult')) ? intval($_POST['adult']) : 0);
2011-03-10 05:10:16 +00:00
$str_group_allow = perms2str($_POST['group_allow']);
$str_contact_allow = perms2str($_POST['contact_allow']);
$str_group_deny = perms2str($_POST['group_deny']);
$str_contact_deny = perms2str($_POST['contact_deny']);
$resource_id = $a->argv[2];
2010-08-08 08:58:26 +00:00
if(! strlen($albname))
$albname = datetime_convert('UTC',date_default_timezone_get(),'now', 'Y');
2012-05-23 08:01:04 +00:00
2012-06-21 02:36:10 +00:00
if((x($_POST,'rotate') !== false) &&
( (intval($_POST['rotate']) == 1) || (intval($_POST['rotate']) == 2) )) {
2012-05-23 08:01:04 +00:00
logger('rotate');
$r = q("select * from photo where `resource_id` = '%s' and uid = %d and scale = 0 limit 1",
2012-05-23 08:01:04 +00:00
dbesc($resource_id),
intval($page_owner_uid)
);
if(count($r)) {
PostgreSQL support initial commit There were 11 main types of changes: - UPDATE's and DELETE's sometimes had LIMIT 1 at the end of them. This is not only non-compliant but it would certainly not do what whoever wrote it thought it would. It is likely this mistake was just copied from Friendica. All of these instances, the LIMIT 1 was simply removed. - Bitwise operations (and even some non-zero int checks) erroneously rely on MySQL implicit integer-boolean conversion in the WHERE clauses. This is non-compliant (and bad programming practice to boot). Proper explicit boolean conversions were added. New queries should use proper conventions. - MySQL has a different operator for bitwise XOR than postgres. Rather than add yet another dba_ func, I converted them to "& ~" ("AND NOT") when turning off, and "|" ("OR") when turning on. There were no true toggles (XOR). New queries should refrain from using XOR when not necessary. - There are several fields which the schema has marked as NOT NULL, but the inserts don't specify them. The reason this works is because mysql totally ignores the constraint and adds an empty text default automatically. Again, non-compliant, obviously. In these cases a default of empty text was added. - Several statements rely on a non-standard MySQL feature (http://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html). These queries can all be rewritten to be standards compliant. Interestingly enough, the newly rewritten standards compliant queries run a zillion times faster, even on MySQL. - A couple of function/operator name translations were needed (RAND/RANDOM, GROUP_CONCAT/STRING_AGG, UTC_NOW, REGEXP/~, ^/#) -- assist functions added in the dba_ - INTERVALs: postgres requires quotes around the value, mysql requires that there are not quotes around the value -- assist functions added in the dba_ - NULL_DATE's -- Postgres does not allow the invalid date '0000-00-00 00:00:00' (there is no such thing as year 0 or month 0 or day 0). We use '0001-01-01 00:00:00' for postgres. Conversions are handled in Zot/item packets automagically by quoting all dates with dbescdate(). - char(##) specifications in the schema creates fields with blank spaces that aren't trimmed in the code. MySQL apparently treats char(##) as varchar(##), again, non-compliant. Since postgres works better with text fields anyway, this ball of bugs was simply side-stepped by using 'text' datatype for all text fields in the postgres schema. varchar was used in a couple of places where it actually seemed appropriate (size constraint), but without rigorously vetting that all of the PHP code actually validates data, new bugs might come out from under the rug. - postgres doesn't store nul bytes and a few other non-printables in text fields, even when quoted. bytea fields were used when storing binary data (photo.data, attach.data). A new dbescbin() function was added to handle this transparently. - postgres does not support LIMIT #,# syntax. All databases support LIMIT # OFFSET # syntax. Statements were updated to be standard. These changes require corresponding changes in the coding standards. Please review those before adding any code going forward. Still on my TODO list: - remove quotes from non-reserved identifiers and make reserved identifiers use dba func for quoting - Rewrite search queries for better results (both MySQL and Postgres)
2014-11-13 20:21:58 +00:00
$ph = photo_factory(dbunescbin($r[0]['data']), $r[0]['type']);
2012-05-23 08:01:04 +00:00
if($ph->is_valid()) {
2012-06-21 02:36:10 +00:00
$rotate_deg = ( (intval($_POST['rotate']) == 1) ? 270 : 90 );
$ph->rotate($rotate_deg);
2012-05-23 08:01:04 +00:00
$width = $ph->getWidth();
$height = $ph->getHeight();
PostgreSQL support initial commit There were 11 main types of changes: - UPDATE's and DELETE's sometimes had LIMIT 1 at the end of them. This is not only non-compliant but it would certainly not do what whoever wrote it thought it would. It is likely this mistake was just copied from Friendica. All of these instances, the LIMIT 1 was simply removed. - Bitwise operations (and even some non-zero int checks) erroneously rely on MySQL implicit integer-boolean conversion in the WHERE clauses. This is non-compliant (and bad programming practice to boot). Proper explicit boolean conversions were added. New queries should use proper conventions. - MySQL has a different operator for bitwise XOR than postgres. Rather than add yet another dba_ func, I converted them to "& ~" ("AND NOT") when turning off, and "|" ("OR") when turning on. There were no true toggles (XOR). New queries should refrain from using XOR when not necessary. - There are several fields which the schema has marked as NOT NULL, but the inserts don't specify them. The reason this works is because mysql totally ignores the constraint and adds an empty text default automatically. Again, non-compliant, obviously. In these cases a default of empty text was added. - Several statements rely on a non-standard MySQL feature (http://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html). These queries can all be rewritten to be standards compliant. Interestingly enough, the newly rewritten standards compliant queries run a zillion times faster, even on MySQL. - A couple of function/operator name translations were needed (RAND/RANDOM, GROUP_CONCAT/STRING_AGG, UTC_NOW, REGEXP/~, ^/#) -- assist functions added in the dba_ - INTERVALs: postgres requires quotes around the value, mysql requires that there are not quotes around the value -- assist functions added in the dba_ - NULL_DATE's -- Postgres does not allow the invalid date '0000-00-00 00:00:00' (there is no such thing as year 0 or month 0 or day 0). We use '0001-01-01 00:00:00' for postgres. Conversions are handled in Zot/item packets automagically by quoting all dates with dbescdate(). - char(##) specifications in the schema creates fields with blank spaces that aren't trimmed in the code. MySQL apparently treats char(##) as varchar(##), again, non-compliant. Since postgres works better with text fields anyway, this ball of bugs was simply side-stepped by using 'text' datatype for all text fields in the postgres schema. varchar was used in a couple of places where it actually seemed appropriate (size constraint), but without rigorously vetting that all of the PHP code actually validates data, new bugs might come out from under the rug. - postgres doesn't store nul bytes and a few other non-printables in text fields, even when quoted. bytea fields were used when storing binary data (photo.data, attach.data). A new dbescbin() function was added to handle this transparently. - postgres does not support LIMIT #,# syntax. All databases support LIMIT # OFFSET # syntax. Statements were updated to be standard. These changes require corresponding changes in the coding standards. Please review those before adding any code going forward. Still on my TODO list: - remove quotes from non-reserved identifiers and make reserved identifiers use dba func for quoting - Rewrite search queries for better results (both MySQL and Postgres)
2014-11-13 20:21:58 +00:00
$x = q("update photo set data = '%s', height = %d, width = %d where `resource_id` = '%s' and uid = %d and scale = 0",
dbescbin($ph->imageString()),
2012-05-23 08:01:04 +00:00
intval($height),
intval($width),
2012-06-21 02:36:10 +00:00
dbesc($resource_id),
intval($page_owner_uid)
2012-05-23 08:01:04 +00:00
);
if($width > 640 || $height > 640) {
$ph->scaleImage(640);
$width = $ph->getWidth();
$height = $ph->getHeight();
PostgreSQL support initial commit There were 11 main types of changes: - UPDATE's and DELETE's sometimes had LIMIT 1 at the end of them. This is not only non-compliant but it would certainly not do what whoever wrote it thought it would. It is likely this mistake was just copied from Friendica. All of these instances, the LIMIT 1 was simply removed. - Bitwise operations (and even some non-zero int checks) erroneously rely on MySQL implicit integer-boolean conversion in the WHERE clauses. This is non-compliant (and bad programming practice to boot). Proper explicit boolean conversions were added. New queries should use proper conventions. - MySQL has a different operator for bitwise XOR than postgres. Rather than add yet another dba_ func, I converted them to "& ~" ("AND NOT") when turning off, and "|" ("OR") when turning on. There were no true toggles (XOR). New queries should refrain from using XOR when not necessary. - There are several fields which the schema has marked as NOT NULL, but the inserts don't specify them. The reason this works is because mysql totally ignores the constraint and adds an empty text default automatically. Again, non-compliant, obviously. In these cases a default of empty text was added. - Several statements rely on a non-standard MySQL feature (http://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html). These queries can all be rewritten to be standards compliant. Interestingly enough, the newly rewritten standards compliant queries run a zillion times faster, even on MySQL. - A couple of function/operator name translations were needed (RAND/RANDOM, GROUP_CONCAT/STRING_AGG, UTC_NOW, REGEXP/~, ^/#) -- assist functions added in the dba_ - INTERVALs: postgres requires quotes around the value, mysql requires that there are not quotes around the value -- assist functions added in the dba_ - NULL_DATE's -- Postgres does not allow the invalid date '0000-00-00 00:00:00' (there is no such thing as year 0 or month 0 or day 0). We use '0001-01-01 00:00:00' for postgres. Conversions are handled in Zot/item packets automagically by quoting all dates with dbescdate(). - char(##) specifications in the schema creates fields with blank spaces that aren't trimmed in the code. MySQL apparently treats char(##) as varchar(##), again, non-compliant. Since postgres works better with text fields anyway, this ball of bugs was simply side-stepped by using 'text' datatype for all text fields in the postgres schema. varchar was used in a couple of places where it actually seemed appropriate (size constraint), but without rigorously vetting that all of the PHP code actually validates data, new bugs might come out from under the rug. - postgres doesn't store nul bytes and a few other non-printables in text fields, even when quoted. bytea fields were used when storing binary data (photo.data, attach.data). A new dbescbin() function was added to handle this transparently. - postgres does not support LIMIT #,# syntax. All databases support LIMIT # OFFSET # syntax. Statements were updated to be standard. These changes require corresponding changes in the coding standards. Please review those before adding any code going forward. Still on my TODO list: - remove quotes from non-reserved identifiers and make reserved identifiers use dba func for quoting - Rewrite search queries for better results (both MySQL and Postgres)
2014-11-13 20:21:58 +00:00
$x = q("update photo set data = '%s', height = %d, width = %d where `resource_id` = '%s' and uid = %d and scale = 1",
dbescbin($ph->imageString()),
2012-05-23 08:01:04 +00:00
intval($height),
intval($width),
2012-06-21 02:36:10 +00:00
dbesc($resource_id),
intval($page_owner_uid)
2012-05-23 08:01:04 +00:00
);
}
if($width > 320 || $height > 320) {
$ph->scaleImage(320);
$width = $ph->getWidth();
$height = $ph->getHeight();
PostgreSQL support initial commit There were 11 main types of changes: - UPDATE's and DELETE's sometimes had LIMIT 1 at the end of them. This is not only non-compliant but it would certainly not do what whoever wrote it thought it would. It is likely this mistake was just copied from Friendica. All of these instances, the LIMIT 1 was simply removed. - Bitwise operations (and even some non-zero int checks) erroneously rely on MySQL implicit integer-boolean conversion in the WHERE clauses. This is non-compliant (and bad programming practice to boot). Proper explicit boolean conversions were added. New queries should use proper conventions. - MySQL has a different operator for bitwise XOR than postgres. Rather than add yet another dba_ func, I converted them to "& ~" ("AND NOT") when turning off, and "|" ("OR") when turning on. There were no true toggles (XOR). New queries should refrain from using XOR when not necessary. - There are several fields which the schema has marked as NOT NULL, but the inserts don't specify them. The reason this works is because mysql totally ignores the constraint and adds an empty text default automatically. Again, non-compliant, obviously. In these cases a default of empty text was added. - Several statements rely on a non-standard MySQL feature (http://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html). These queries can all be rewritten to be standards compliant. Interestingly enough, the newly rewritten standards compliant queries run a zillion times faster, even on MySQL. - A couple of function/operator name translations were needed (RAND/RANDOM, GROUP_CONCAT/STRING_AGG, UTC_NOW, REGEXP/~, ^/#) -- assist functions added in the dba_ - INTERVALs: postgres requires quotes around the value, mysql requires that there are not quotes around the value -- assist functions added in the dba_ - NULL_DATE's -- Postgres does not allow the invalid date '0000-00-00 00:00:00' (there is no such thing as year 0 or month 0 or day 0). We use '0001-01-01 00:00:00' for postgres. Conversions are handled in Zot/item packets automagically by quoting all dates with dbescdate(). - char(##) specifications in the schema creates fields with blank spaces that aren't trimmed in the code. MySQL apparently treats char(##) as varchar(##), again, non-compliant. Since postgres works better with text fields anyway, this ball of bugs was simply side-stepped by using 'text' datatype for all text fields in the postgres schema. varchar was used in a couple of places where it actually seemed appropriate (size constraint), but without rigorously vetting that all of the PHP code actually validates data, new bugs might come out from under the rug. - postgres doesn't store nul bytes and a few other non-printables in text fields, even when quoted. bytea fields were used when storing binary data (photo.data, attach.data). A new dbescbin() function was added to handle this transparently. - postgres does not support LIMIT #,# syntax. All databases support LIMIT # OFFSET # syntax. Statements were updated to be standard. These changes require corresponding changes in the coding standards. Please review those before adding any code going forward. Still on my TODO list: - remove quotes from non-reserved identifiers and make reserved identifiers use dba func for quoting - Rewrite search queries for better results (both MySQL and Postgres)
2014-11-13 20:21:58 +00:00
$x = q("update photo set data = '%s', height = %d, width = %d where `resource_id` = '%s' and uid = %d and scale = 2",
dbescbin($ph->imageString()),
2012-05-23 08:01:04 +00:00
intval($height),
intval($width),
2012-06-21 02:36:10 +00:00
dbesc($resource_id),
intval($page_owner_uid)
2012-05-23 08:01:04 +00:00
);
}
}
}
}
$p = q("SELECT * FROM `photo` WHERE `resource_id` = '%s' AND `uid` = %d ORDER BY `scale` DESC",
dbesc($resource_id),
intval($page_owner_uid)
2010-08-08 08:58:26 +00:00
);
if($p) {
2012-06-07 15:42:13 +00:00
$ext = $phototypes[$p[0]['type']];
$r = q("UPDATE `photo` SET `description` = '%s', `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s' WHERE `resource_id` = '%s' AND `uid` = %d",
dbesc($desc),
2011-03-10 05:10:16 +00:00
dbesc($str_contact_allow),
dbesc($str_group_allow),
dbesc($str_contact_deny),
dbesc($str_group_deny),
dbesc($resource_id),
intval($page_owner_uid)
);
}
$item_private = (($str_contact_allow || $str_group_allow || $str_contact_deny || $str_group_deny) ? true : false);
2015-05-19 03:10:44 +00:00
$old_is_nsfw = $p[0]['is_nsfw'];
if($old_is_nsfw != $is_nsfw) {
$r = q("update photo set is_nsfw = %d where resource_id = '%s' and uid = %d",
intval($is_nsfw),
dbesc($resource_id),
intval($page_owner_uid)
);
}
/* Don't make the item visible if the only change was the album name */
$visibility = 0;
if($p[0]['description'] !== $desc || strlen($rawtags))
$visibility = 1;
if(! $item_id) {
2013-02-02 09:58:11 +00:00
$item_id = photos_create_item($a->data['channel'],get_observer_hash(),$p[0],$visibility);
}
2010-11-02 06:42:26 +00:00
if($item_id) {
$r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($item_id),
intval($page_owner_uid)
2010-11-02 06:42:26 +00:00
);
if($r) {
$old_tag = $r[0]['tag'];
$old_inform = $r[0]['inform'];
}
2010-11-02 06:42:26 +00:00
}
2010-08-08 08:58:26 +00:00
2014-10-27 04:37:59 +00:00
// make sure the linked item has the same permissions as the photo regardless of any other changes
$x = q("update item set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', item_private = %d
PostgreSQL support initial commit There were 11 main types of changes: - UPDATE's and DELETE's sometimes had LIMIT 1 at the end of them. This is not only non-compliant but it would certainly not do what whoever wrote it thought it would. It is likely this mistake was just copied from Friendica. All of these instances, the LIMIT 1 was simply removed. - Bitwise operations (and even some non-zero int checks) erroneously rely on MySQL implicit integer-boolean conversion in the WHERE clauses. This is non-compliant (and bad programming practice to boot). Proper explicit boolean conversions were added. New queries should use proper conventions. - MySQL has a different operator for bitwise XOR than postgres. Rather than add yet another dba_ func, I converted them to "& ~" ("AND NOT") when turning off, and "|" ("OR") when turning on. There were no true toggles (XOR). New queries should refrain from using XOR when not necessary. - There are several fields which the schema has marked as NOT NULL, but the inserts don't specify them. The reason this works is because mysql totally ignores the constraint and adds an empty text default automatically. Again, non-compliant, obviously. In these cases a default of empty text was added. - Several statements rely on a non-standard MySQL feature (http://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html). These queries can all be rewritten to be standards compliant. Interestingly enough, the newly rewritten standards compliant queries run a zillion times faster, even on MySQL. - A couple of function/operator name translations were needed (RAND/RANDOM, GROUP_CONCAT/STRING_AGG, UTC_NOW, REGEXP/~, ^/#) -- assist functions added in the dba_ - INTERVALs: postgres requires quotes around the value, mysql requires that there are not quotes around the value -- assist functions added in the dba_ - NULL_DATE's -- Postgres does not allow the invalid date '0000-00-00 00:00:00' (there is no such thing as year 0 or month 0 or day 0). We use '0001-01-01 00:00:00' for postgres. Conversions are handled in Zot/item packets automagically by quoting all dates with dbescdate(). - char(##) specifications in the schema creates fields with blank spaces that aren't trimmed in the code. MySQL apparently treats char(##) as varchar(##), again, non-compliant. Since postgres works better with text fields anyway, this ball of bugs was simply side-stepped by using 'text' datatype for all text fields in the postgres schema. varchar was used in a couple of places where it actually seemed appropriate (size constraint), but without rigorously vetting that all of the PHP code actually validates data, new bugs might come out from under the rug. - postgres doesn't store nul bytes and a few other non-printables in text fields, even when quoted. bytea fields were used when storing binary data (photo.data, attach.data). A new dbescbin() function was added to handle this transparently. - postgres does not support LIMIT #,# syntax. All databases support LIMIT # OFFSET # syntax. Statements were updated to be standard. These changes require corresponding changes in the coding standards. Please review those before adding any code going forward. Still on my TODO list: - remove quotes from non-reserved identifiers and make reserved identifiers use dba func for quoting - Rewrite search queries for better results (both MySQL and Postgres)
2014-11-13 20:21:58 +00:00
where id = %d",
dbesc($str_contact_allow),
dbesc($str_group_allow),
dbesc($str_contact_deny),
dbesc($str_group_deny),
intval($item_private),
intval($item_id)
);
// make sure the attach has the same permissions as the photo regardless of any other changes
$x = q("update attach set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where hash = '%s' and uid = %d and is_photo = 1",
dbesc($str_contact_allow),
dbesc($str_group_allow),
dbesc($str_contact_deny),
dbesc($str_group_deny),
dbesc($resource_id),
intval($page_owner_uid)
);
2010-11-02 06:42:26 +00:00
if(strlen($rawtags)) {
$str_tags = '';
$inform = '';
// if the new tag doesn't have a namespace specifier (@foo or #foo) give it a mention
2010-11-02 06:42:26 +00:00
$x = substr($rawtags,0,1);
if($x !== '@' && $x !== '#')
$rawtags = '@' . $rawtags;
2010-11-02 06:42:26 +00:00
require_once('include/text.php');
$profile_uid = $a->profile['profile_uid'];
2015-01-29 04:56:04 +00:00
$results = linkify_tags($a, $rawtags, (local_channel()) ? local_channel() : $profile_uid);
$success = $results['success'];
$post_tags = array();
foreach($results as $result) {
$success = $result['success'];
if($success['replaced']) {
$post_tags[] = array(
'uid' => $profile_uid,
'type' => $success['termtype'],
'otype' => TERM_OBJ_POST,
'term' => $success['term'],
'url' => $success['url']
);
2010-11-02 06:42:26 +00:00
}
}
$r = q("select * from item where id = %d and uid = %d limit 1",
intval($item_id),
intval($page_owner_uid)
);
if($r) {
2014-10-27 04:37:59 +00:00
$r = fetch_post_tags($r,true);
$datarray = $r[0];
2014-10-27 04:37:59 +00:00
if($post_tags) {
if((! array_key_exists('term',$datarray)) || (! is_array($datarray['term'])))
$datarray['term'] = $post_tags;
else
$datarray['term'] = array_merge($datarray['term'],$post_tags);
}
item_store_update($datarray,$execflag);
2010-11-05 03:47:44 +00:00
}
2010-11-02 06:42:26 +00:00
}
2010-08-08 08:58:26 +00:00
goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
return; // NOTREACHED
2010-08-08 08:58:26 +00:00
}
/**
* default post action - upload a photo
*/
2011-01-27 11:46:09 +00:00
$channel = $a->data['channel'];
$observer = $a->data['observer'];
$_REQUEST['source'] = 'photos';
2015-06-15 04:08:00 +00:00
require_once('include/attach.php');
2012-06-25 08:37:44 +00:00
if(!local_channel()) {
$_REQUEST['contact_allow'] = expand_acl($channel['channel_allow_cid']);
$_REQUEST['group_allow'] = expand_acl($channel['channel_allow_gid']);
$_REQUEST['contact_deny'] = expand_acl($channel['channel_deny_cid']);
$_REQUEST['group_deny'] = expand_acl($channel['channel_deny_gid']);
}
$r = attach_store($a->channel,get_observer_hash(), '', $_REQUEST);
2013-02-02 09:58:11 +00:00
if(! $r['success']) {
notice($r['message'] . EOL);
}
2014-11-03 10:19:27 +00:00
if($_REQUEST['newalbum'])
goaway($a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/album/' . bin2hex($_REQUEST['newalbum']));
else
goaway($a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/album/' . bin2hex(datetime_convert('UTC',date_default_timezone_get(),'now', 'Y')));
2013-02-02 09:58:11 +00:00
2010-08-06 04:15:24 +00:00
}
function photos_content(&$a) {
// URLs:
// photos/name
2014-11-01 22:55:36 +00:00
// photos/name/album/xxxxx (xxxxx is album name)
2010-08-06 04:15:24 +00:00
// photos/name/image/xxxxx
2010-08-06 04:15:24 +00:00
2015-01-29 04:58:59 +00:00
if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) {
notice( t('Public access denied.') . EOL);
return;
}
$unsafe = ((array_key_exists('unsafe',$_REQUEST) && $_REQUEST['unsafe']) ? 1 : 0);
require_once('include/bbcode.php');
require_once('include/security.php');
require_once('include/conversation.php');
if(! x($a->data,'channel')) {
2010-08-06 04:15:24 +00:00
notice( t('No photos selected') . EOL );
return;
}
2013-04-26 03:01:24 +00:00
$ph = photo_factory('');
$phototypes = $ph->supportedTypes();
2012-06-07 15:42:13 +00:00
2010-08-06 04:15:24 +00:00
$_SESSION['photo_return'] = $a->cmd;
//
// Parse arguments
//
2013-12-20 01:36:31 +00:00
$can_comment = perm_is_allowed($a->profile['profile_uid'],get_observer_hash(),'post_comments');
if(argc() > 3) {
$datatype = argv(2);
$datum = argv(3);
2014-10-31 19:25:43 +00:00
} else {
2010-08-06 04:15:24 +00:00
$datatype = 'summary';
2014-10-31 19:25:43 +00:00
}
2010-08-06 04:15:24 +00:00
if(argc() > 4)
$cmd = argv(4);
2010-08-06 04:15:24 +00:00
else
$cmd = 'view';
//
// Setup permissions structures
//
$can_post = false;
$visitor = 0;
2010-08-06 04:15:24 +00:00
$owner_uid = $a->data['channel']['channel_id'];
$owner_aid = $a->data['channel']['channel_account_id'];
$observer = $a->get_observer();
2010-12-08 01:16:05 +00:00
$can_post = perm_is_allowed($owner_uid,$observer['xchan_hash'],'post_photos');
$can_view = perm_is_allowed($owner_uid,$observer['xchan_hash'],'view_photos');
2010-08-06 04:15:24 +00:00
if(! $can_view) {
notice( t('Access to this item is restricted.') . EOL);
return;
}
$sql_extra = permissions_sql($owner_uid);
2010-08-06 04:15:24 +00:00
$o = "";
$o .= "<script> var profile_uid = " . $a->profile['profile_uid']
. "; var netargs = '?f='; var profile_page = " . $a->pager['page'] . "; </script>\r\n";
// tabs
2015-01-29 04:56:04 +00:00
$_is_owner = (local_channel() && (local_channel() == $owner_uid));
$o .= profile_tabs($a,$_is_owner, $a->data['channel']['channel_address']);
/**
* Display upload form
*/
2010-08-06 04:15:24 +00:00
2014-10-31 19:25:43 +00:00
if( $can_post) {
$uploader = '';
$ret = array('post_url' => $a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'],
'addon_text' => $uploader,
'default_upload' => true);
call_hooks('photo_upload_form',$ret);
/* Show space usage */
$r = q("select sum(size) as total from photo where aid = %d and scale = 0 ",
intval($a->data['channel']['channel_account_id'])
2012-06-25 08:37:44 +00:00
);
$limit = service_class_fetch($a->data['channel']['channel_id'],'photo_upload_limit');
2012-06-25 08:37:44 +00:00
if($limit !== false) {
2014-10-30 13:10:55 +00:00
$usage_message = sprintf( t("%1$.2f MB of %2$.2f MB photo storage used."), $r[0]['total'] / 1024000, $limit / 1024000 );
2012-06-25 08:37:44 +00:00
}
else {
2014-10-30 13:10:55 +00:00
$usage_message = sprintf( t('%1$.2f MB photo storage used.'), $r[0]['total'] / 1024000 );
2012-06-25 08:37:44 +00:00
}
if($_is_owner) {
$channel = $a->get_channel();
$channel_acl = array(
'allow_cid' => $channel['channel_allow_cid'],
'allow_gid' => $channel['channel_allow_gid'],
'deny_cid' => $channel['channel_deny_cid'],
'deny_gid' => $channel['channel_deny_gid']
);
2014-11-06 10:57:33 +00:00
$lockstate = (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock');
}
$aclselect = (($_is_owner) ? populate_acl($channel_acl,false) : '');
2013-01-06 21:42:51 +00:00
2014-10-30 13:10:55 +00:00
$selname = (($datum) ? hex2bin($datum) : '');
$albums = ((array_key_exists('albums', $a->data)) ? $a->data['albums'] : photos_albums_list($a->data['channel'],$a->data['observer']));
2011-05-11 11:37:13 +00:00
$tpl = get_markup_template('photos_upload.tpl');
2014-10-31 19:25:43 +00:00
$upload_form = replace_macros($tpl,array(
2010-08-06 04:15:24 +00:00
'$pagename' => t('Upload Photos'),
'$sessid' => session_id(),
2012-06-25 08:37:44 +00:00
'$usage' => $usage_message,
'$nickname' => $a->data['channel']['channel_address'],
2014-10-31 13:33:41 +00:00
'$newalbum_label' => t('Enter a new album name'),
'$newalbum_placeholder' => t('or select an existing one (doubleclick)'),
2015-04-12 11:13:22 +00:00
'$visible' => array('visible', t('Create a status post for this upload'), 0, '', array(t('No'), t('Yes'))),
2014-10-30 13:10:55 +00:00
'$albums' => $albums['albums'],
'$selname' => $selname,
2010-08-07 13:20:27 +00:00
'$permissions' => t('Permissions'),
'$aclselect' => $aclselect,
2014-11-06 10:57:33 +00:00
'$lockstate' => $lockstate,
'$uploader' => $ret['addon_text'],
2014-10-31 13:33:41 +00:00
'$default' => (($ret['default_upload']) ? true : false),
'$uploadurl' => $ret['post_url'],
'$submit' => t('Submit')
2010-08-06 04:15:24 +00:00
));
}
2014-11-01 22:55:36 +00:00
//
// dispatch request
//
/*
* Display a single photo album
*/
2010-09-27 00:24:20 +00:00
if($datatype === 'album') {
2010-08-06 04:15:24 +00:00
if((strlen($datum) & 1) || (! ctype_xdigit($datum))) {
notice( t('Album name could not be decoded') . EOL);
2014-08-15 13:05:52 +00:00
logger('mod_photos: illegal album encoding: ' . $datum);
$datum = '';
}
2010-08-06 04:15:24 +00:00
$album = hex2bin($datum);
$r = q("SELECT `resource_id`, max(`scale`) AS `scale` FROM `photo` WHERE `uid` = %d AND `album` = '%s'
2015-05-19 02:43:53 +00:00
AND `scale` <= 4 and photo_usage IN ( %d, %d ) and is_nsfw = %d $sql_extra GROUP BY `resource_id`",
intval($owner_uid),
dbesc($album),
intval(PHOTO_NORMAL),
2015-05-19 02:43:53 +00:00
intval(PHOTO_PROFILE),
intval($unsafe)
2010-08-06 04:15:24 +00:00
);
if(count($r)) {
2010-08-06 04:15:24 +00:00
$a->set_pager_total(count($r));
2014-09-11 11:07:08 +00:00
$a->set_pager_itemspage(60);
2014-11-03 10:19:27 +00:00
} else {
goaway($a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address']);
}
2010-08-06 04:15:24 +00:00
2012-09-10 04:17:06 +00:00
if($_GET['order'] === 'posted')
$order = 'ASC';
else
$order = 'DESC';
PostgreSQL support initial commit There were 11 main types of changes: - UPDATE's and DELETE's sometimes had LIMIT 1 at the end of them. This is not only non-compliant but it would certainly not do what whoever wrote it thought it would. It is likely this mistake was just copied from Friendica. All of these instances, the LIMIT 1 was simply removed. - Bitwise operations (and even some non-zero int checks) erroneously rely on MySQL implicit integer-boolean conversion in the WHERE clauses. This is non-compliant (and bad programming practice to boot). Proper explicit boolean conversions were added. New queries should use proper conventions. - MySQL has a different operator for bitwise XOR than postgres. Rather than add yet another dba_ func, I converted them to "& ~" ("AND NOT") when turning off, and "|" ("OR") when turning on. There were no true toggles (XOR). New queries should refrain from using XOR when not necessary. - There are several fields which the schema has marked as NOT NULL, but the inserts don't specify them. The reason this works is because mysql totally ignores the constraint and adds an empty text default automatically. Again, non-compliant, obviously. In these cases a default of empty text was added. - Several statements rely on a non-standard MySQL feature (http://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html). These queries can all be rewritten to be standards compliant. Interestingly enough, the newly rewritten standards compliant queries run a zillion times faster, even on MySQL. - A couple of function/operator name translations were needed (RAND/RANDOM, GROUP_CONCAT/STRING_AGG, UTC_NOW, REGEXP/~, ^/#) -- assist functions added in the dba_ - INTERVALs: postgres requires quotes around the value, mysql requires that there are not quotes around the value -- assist functions added in the dba_ - NULL_DATE's -- Postgres does not allow the invalid date '0000-00-00 00:00:00' (there is no such thing as year 0 or month 0 or day 0). We use '0001-01-01 00:00:00' for postgres. Conversions are handled in Zot/item packets automagically by quoting all dates with dbescdate(). - char(##) specifications in the schema creates fields with blank spaces that aren't trimmed in the code. MySQL apparently treats char(##) as varchar(##), again, non-compliant. Since postgres works better with text fields anyway, this ball of bugs was simply side-stepped by using 'text' datatype for all text fields in the postgres schema. varchar was used in a couple of places where it actually seemed appropriate (size constraint), but without rigorously vetting that all of the PHP code actually validates data, new bugs might come out from under the rug. - postgres doesn't store nul bytes and a few other non-printables in text fields, even when quoted. bytea fields were used when storing binary data (photo.data, attach.data). A new dbescbin() function was added to handle this transparently. - postgres does not support LIMIT #,# syntax. All databases support LIMIT # OFFSET # syntax. Statements were updated to be standard. These changes require corresponding changes in the coding standards. Please review those before adding any code going forward. Still on my TODO list: - remove quotes from non-reserved identifiers and make reserved identifiers use dba func for quoting - Rewrite search queries for better results (both MySQL and Postgres)
2014-11-13 20:21:58 +00:00
$r = q("SELECT p.resource_id, p.id, p.filename, p.type, p.scale, p.description, p.created FROM photo p INNER JOIN
2015-05-19 02:43:53 +00:00
(SELECT resource_id, max(scale) scale FROM photo WHERE uid = %d AND album = '%s' AND scale <= 4 AND photo_usage IN ( %d, %d ) and is_nsfw = %d $sql_extra GROUP BY resource_id) ph
PostgreSQL support initial commit There were 11 main types of changes: - UPDATE's and DELETE's sometimes had LIMIT 1 at the end of them. This is not only non-compliant but it would certainly not do what whoever wrote it thought it would. It is likely this mistake was just copied from Friendica. All of these instances, the LIMIT 1 was simply removed. - Bitwise operations (and even some non-zero int checks) erroneously rely on MySQL implicit integer-boolean conversion in the WHERE clauses. This is non-compliant (and bad programming practice to boot). Proper explicit boolean conversions were added. New queries should use proper conventions. - MySQL has a different operator for bitwise XOR than postgres. Rather than add yet another dba_ func, I converted them to "& ~" ("AND NOT") when turning off, and "|" ("OR") when turning on. There were no true toggles (XOR). New queries should refrain from using XOR when not necessary. - There are several fields which the schema has marked as NOT NULL, but the inserts don't specify them. The reason this works is because mysql totally ignores the constraint and adds an empty text default automatically. Again, non-compliant, obviously. In these cases a default of empty text was added. - Several statements rely on a non-standard MySQL feature (http://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html). These queries can all be rewritten to be standards compliant. Interestingly enough, the newly rewritten standards compliant queries run a zillion times faster, even on MySQL. - A couple of function/operator name translations were needed (RAND/RANDOM, GROUP_CONCAT/STRING_AGG, UTC_NOW, REGEXP/~, ^/#) -- assist functions added in the dba_ - INTERVALs: postgres requires quotes around the value, mysql requires that there are not quotes around the value -- assist functions added in the dba_ - NULL_DATE's -- Postgres does not allow the invalid date '0000-00-00 00:00:00' (there is no such thing as year 0 or month 0 or day 0). We use '0001-01-01 00:00:00' for postgres. Conversions are handled in Zot/item packets automagically by quoting all dates with dbescdate(). - char(##) specifications in the schema creates fields with blank spaces that aren't trimmed in the code. MySQL apparently treats char(##) as varchar(##), again, non-compliant. Since postgres works better with text fields anyway, this ball of bugs was simply side-stepped by using 'text' datatype for all text fields in the postgres schema. varchar was used in a couple of places where it actually seemed appropriate (size constraint), but without rigorously vetting that all of the PHP code actually validates data, new bugs might come out from under the rug. - postgres doesn't store nul bytes and a few other non-printables in text fields, even when quoted. bytea fields were used when storing binary data (photo.data, attach.data). A new dbescbin() function was added to handle this transparently. - postgres does not support LIMIT #,# syntax. All databases support LIMIT # OFFSET # syntax. Statements were updated to be standard. These changes require corresponding changes in the coding standards. Please review those before adding any code going forward. Still on my TODO list: - remove quotes from non-reserved identifiers and make reserved identifiers use dba func for quoting - Rewrite search queries for better results (both MySQL and Postgres)
2014-11-13 20:21:58 +00:00
ON (p.resource_id = ph.resource_id AND p.scale = ph.scale)
ORDER BY created $order LIMIT %d OFFSET %d",
intval($owner_uid),
2010-08-06 04:15:24 +00:00
dbesc($album),
2015-05-19 02:43:53 +00:00
intval(PHOTO_NORMAL),
intval(PHOTO_PROFILE),
intval($unsafe),
PostgreSQL support initial commit There were 11 main types of changes: - UPDATE's and DELETE's sometimes had LIMIT 1 at the end of them. This is not only non-compliant but it would certainly not do what whoever wrote it thought it would. It is likely this mistake was just copied from Friendica. All of these instances, the LIMIT 1 was simply removed. - Bitwise operations (and even some non-zero int checks) erroneously rely on MySQL implicit integer-boolean conversion in the WHERE clauses. This is non-compliant (and bad programming practice to boot). Proper explicit boolean conversions were added. New queries should use proper conventions. - MySQL has a different operator for bitwise XOR than postgres. Rather than add yet another dba_ func, I converted them to "& ~" ("AND NOT") when turning off, and "|" ("OR") when turning on. There were no true toggles (XOR). New queries should refrain from using XOR when not necessary. - There are several fields which the schema has marked as NOT NULL, but the inserts don't specify them. The reason this works is because mysql totally ignores the constraint and adds an empty text default automatically. Again, non-compliant, obviously. In these cases a default of empty text was added. - Several statements rely on a non-standard MySQL feature (http://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html). These queries can all be rewritten to be standards compliant. Interestingly enough, the newly rewritten standards compliant queries run a zillion times faster, even on MySQL. - A couple of function/operator name translations were needed (RAND/RANDOM, GROUP_CONCAT/STRING_AGG, UTC_NOW, REGEXP/~, ^/#) -- assist functions added in the dba_ - INTERVALs: postgres requires quotes around the value, mysql requires that there are not quotes around the value -- assist functions added in the dba_ - NULL_DATE's -- Postgres does not allow the invalid date '0000-00-00 00:00:00' (there is no such thing as year 0 or month 0 or day 0). We use '0001-01-01 00:00:00' for postgres. Conversions are handled in Zot/item packets automagically by quoting all dates with dbescdate(). - char(##) specifications in the schema creates fields with blank spaces that aren't trimmed in the code. MySQL apparently treats char(##) as varchar(##), again, non-compliant. Since postgres works better with text fields anyway, this ball of bugs was simply side-stepped by using 'text' datatype for all text fields in the postgres schema. varchar was used in a couple of places where it actually seemed appropriate (size constraint), but without rigorously vetting that all of the PHP code actually validates data, new bugs might come out from under the rug. - postgres doesn't store nul bytes and a few other non-printables in text fields, even when quoted. bytea fields were used when storing binary data (photo.data, attach.data). A new dbescbin() function was added to handle this transparently. - postgres does not support LIMIT #,# syntax. All databases support LIMIT # OFFSET # syntax. Statements were updated to be standard. These changes require corresponding changes in the coding standards. Please review those before adding any code going forward. Still on my TODO list: - remove quotes from non-reserved identifiers and make reserved identifiers use dba func for quoting - Rewrite search queries for better results (both MySQL and Postgres)
2014-11-13 20:21:58 +00:00
intval($a->pager['itemspage']),
intval($a->pager['start'])
2010-08-06 04:15:24 +00:00
);
//edit album name
$album_edit = null;
if(($album !== t('Profile Photos')) && ($album !== 'Profile Photos') && ($album !== 'Contact Photos') && ($album !== t('Contact Photos'))) {
if($can_post) {
if($a->get_template_engine() === 'internal') {
$album_e = template_escape($album);
}
else {
$album_e = $album;
}
2014-10-30 13:10:55 +00:00
$albums = ((array_key_exists('albums', $a->data)) ? $a->data['albums'] : photos_albums_list($a->data['channel'],$a->data['observer']));
$edit_tpl = get_markup_template('album_edit.tpl');
$album_edit = replace_macros($edit_tpl,array(
2014-11-01 22:55:36 +00:00
'$nametext' => t('Enter a new album name'),
'$name_placeholder' => t('or select an existing one (doubleclick)'),
'$nickname' => $a->data['channel']['channel_address'],
'$album' => $album_e,
2014-10-30 13:10:55 +00:00
'$albums' => $albums['albums'],
'$hexalbum' => bin2hex($album),
'$submit' => t('Submit'),
'$dropsubmit' => t('Delete Album')
));
}
}
2012-09-10 04:17:06 +00:00
if($_GET['order'] === 'posted')
2014-10-02 19:04:50 +00:00
$order = array(t('Show Newest First'), $a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/album/' . bin2hex($album));
2012-09-10 04:17:06 +00:00
else
2014-10-02 19:04:50 +00:00
$order = array(t('Show Oldest First'), $a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/album/' . bin2hex($album) . '?f=&order=posted');
2012-09-10 04:17:06 +00:00
2014-10-02 19:04:50 +00:00
$photos = array();
2014-09-06 07:37:15 +00:00
if(count($r)) {
$twist = 'rotright';
2010-08-06 04:15:24 +00:00
foreach($r as $rr) {
if($twist == 'rotright')
$twist = 'rotleft';
else
$twist = 'rotright';
2012-06-07 15:42:13 +00:00
$ext = $phototypes[$rr['type']];
$imgalt_e = $rr['filename'];
$desc_e = $rr['description'];
2014-10-02 19:04:50 +00:00
$imagelink = ($a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/image/' . $rr['resource_id']
. (($_GET['order'] === 'posted') ? '?f=&order=posted' : ''));
$photos[] = array(
'id' => $rr['id'],
'twist' => ' ' . $twist . rand(2,4),
'link' => $imagelink,
'title' => t('View Photo'),
'src' => $a->get_baseurl() . '/photo/' . $rr['resource_id'] . '-' . $rr['scale'] . '.' .$ext,
'alt' => $imgalt_e,
'desc'=> $desc_e,
'ext' => $ext,
'hash'=> $rr['resource_id'],
'unknown' => t('Unknown')
2014-10-02 19:04:50 +00:00
);
2014-09-06 07:37:15 +00:00
}
}
2014-10-02 19:04:50 +00:00
2014-09-06 07:37:15 +00:00
if($_REQUEST['aj']) {
2014-10-02 19:04:50 +00:00
if($photos) {
$o = replace_macros(get_markup_template('photosajax.tpl'),array(
'$photos' => $photos,
));
}
else {
$o = '<div id="content-complete"></div>';
}
2014-10-02 19:04:50 +00:00
echo $o;
killme();
}
else {
$o .= "<script> var page_query = '" . $_GET['q'] . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
$tpl = get_markup_template('photo_album.tpl');
$o .= replace_macros($tpl, array(
'$photos' => $photos,
'$album' => $album,
'$album_edit' => array(t('Edit Album'), $album_edit),
2014-10-02 19:04:50 +00:00
'$can_post' => $can_post,
'$upload' => array(t('Upload'), $a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/upload/' . bin2hex($album)),
'$order' => $order,
2014-10-31 19:25:43 +00:00
'$upload_form' => $upload_form,
'$usage' => $usage_message
2014-10-02 19:04:50 +00:00
));
}
if((! $photos) && ($_REQUEST['aj'])) {
$o .= '<div id="content-complete"></div>';
echo $o;
2014-09-06 07:37:15 +00:00
killme();
2010-08-06 04:15:24 +00:00
}
2014-09-06 07:37:15 +00:00
// $o .= paginate($a);
2010-08-06 04:15:24 +00:00
return $o;
}
/**
* Display one photo
*/
2010-08-06 04:15:24 +00:00
2010-09-27 00:24:20 +00:00
if($datatype === 'image') {
2010-08-06 04:15:24 +00:00
2010-08-07 13:20:27 +00:00
// fetch image, item containing image, then comments
2010-08-06 13:30:25 +00:00
2015-05-19 03:10:44 +00:00
$ph = q("SELECT aid,uid,xchan,resource_id,created,edited,title,`description`,album,filename,`type`,height,width,`size`,scale,photo_usage,is_nsfw,allow_cid,allow_gid,deny_cid,deny_gid FROM `photo` WHERE `uid` = %d AND `resource_id` = '%s'
$sql_extra ORDER BY `scale` ASC ",
intval($owner_uid),
dbesc($datum)
2010-08-06 04:15:24 +00:00
);
if(! $ph) {
/* Check again - this time without specifying permissions */
$ph = q("SELECT id FROM photo WHERE uid = %d AND resource_id = '%s' LIMIT 1",
intval($owner_uid),
dbesc($datum)
);
if($ph)
notice( t('Permission denied. Access to this item may be restricted.') . EOL);
else
notice( t('Photo not available') . EOL );
2010-08-06 04:15:24 +00:00
return;
}
2011-03-12 04:06:13 +00:00
$prevlink = '';
$nextlink = '';
2012-09-10 04:17:06 +00:00
if($_GET['order'] === 'posted')
$order = 'ASC';
else
$order = 'DESC';
$prvnxt = q("SELECT `resource_id` FROM `photo` WHERE `album` = '%s' AND `uid` = %d AND `scale` = 0
$sql_extra ORDER BY `created` $order ",
2011-03-12 04:06:13 +00:00
dbesc($ph[0]['album']),
intval($owner_uid)
2011-03-12 04:06:13 +00:00
);
if(count($prvnxt)) {
for($z = 0; $z < count($prvnxt); $z++) {
if($prvnxt[$z]['resource_id'] == $ph[0]['resource_id']) {
2011-03-12 04:06:13 +00:00
$prv = $z - 1;
$nxt = $z + 1;
if($prv < 0)
$prv = count($prvnxt) - 1;
if($nxt >= count($prvnxt))
$nxt = 0;
break;
}
}
$prevlink = $a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/image/' . $prvnxt[$prv]['resource_id'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
$nextlink = $a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/image/' . $prvnxt[$nxt]['resource_id'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
2011-03-12 04:06:13 +00:00
}
2010-08-06 13:30:25 +00:00
if(count($ph) == 1)
$hires = $lores = $ph[0];
if(count($ph) > 1) {
if($ph[1]['scale'] == 2) {
// original is 640 or less, we can display it directly
$hires = $lores = $ph[0];
}
else {
2010-08-06 13:30:25 +00:00
$hires = $ph[0];
$lores = $ph[1];
}
2010-08-06 04:15:24 +00:00
}
$album_link = $a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/album/' . bin2hex($ph[0]['album']);
2011-05-05 08:53:03 +00:00
$tools = Null;
$lock = Null;
if($can_post && ($ph[0]['uid'] == $owner_uid)) {
2011-05-05 08:53:03 +00:00
$tools = array(
'profile'=>array($a->get_baseurl() . '/profile_photo/use/'.$ph[0]['resource_id'], t('Use as profile photo')),
2011-05-05 08:53:03 +00:00
);
2010-08-08 08:58:26 +00:00
}
2014-11-07 11:13:38 +00:00
// lockstate
$lockstate = ( ( (strlen($ph[0]['allow_cid']) || strlen($ph[0]['allow_gid'])
2014-10-20 13:05:33 +00:00
|| strlen($ph[0]['deny_cid']) || strlen($ph[0]['deny_gid'])) )
2014-11-07 11:13:38 +00:00
? array('lock', t('Private Photo'))
: array('unlock', Null));
2014-10-20 13:05:33 +00:00
$a->page['htmlhead'] .= '<script>$(document).keydown(function(event) {' . "\n";
if($prevlink)
$a->page['htmlhead'] .= 'if(event.ctrlKey && event.keyCode == 37) { event.preventDefault(); window.location.href = \'' . $prevlink . '\'; }' . "\n";
if($nextlink)
$a->page['htmlhead'] .= 'if(event.ctrlKey && event.keyCode == 39) { event.preventDefault(); window.location.href = \'' . $nextlink . '\'; }' . "\n";
$a->page['htmlhead'] .= '});</script>';
2011-03-12 04:06:13 +00:00
if($prevlink)
2014-10-20 13:05:33 +00:00
$prevlink = array($prevlink, t('Previous'));
2010-08-08 08:58:26 +00:00
2011-05-05 08:53:03 +00:00
$photo = array(
'href' => $a->get_baseurl() . '/photo/' . $hires['resource_id'] . '-' . $hires['scale'] . '.' . $phototypes[$hires['type']],
2011-05-05 08:53:03 +00:00
'title'=> t('View Full Size'),
'src' => $a->get_baseurl() . '/photo/' . $lores['resource_id'] . '-' . $lores['scale'] . '.' . $phototypes[$lores['type']] . '?f=&_u=' . datetime_convert('','','','ymdhis')
2011-05-05 08:53:03 +00:00
);
2011-03-12 04:06:13 +00:00
if($nextlink)
2014-10-20 13:05:33 +00:00
$nextlink = array($nextlink, t('Next'));
2010-08-06 04:15:24 +00:00
2010-08-08 08:58:26 +00:00
2010-08-06 13:30:25 +00:00
// Do we have an item for this photo?
$linked_items = q("SELECT * FROM item WHERE resource_id = '%s' and resource_type = 'photo'
$sql_extra LIMIT 1",
2010-08-06 13:30:25 +00:00
dbesc($datum)
);
$map = null;
if($linked_items) {
xchan_query($linked_items);
$linked_items = fetch_post_tags($linked_items,true);
2010-11-05 03:47:44 +00:00
$link_item = $linked_items[0];
$item_normal = item_normal();
$r = q("select * from item where parent_mid = '%s'
$item_normal and uid = %d $sql_extra ",
dbesc($link_item['mid']),
2010-11-05 03:47:44 +00:00
intval($link_item['uid'])
2010-08-06 13:30:25 +00:00
);
if($r) {
xchan_query($r);
$r = fetch_post_tags($r,true);
$r = conv_sort($r,'commented');
}
2010-08-06 13:30:25 +00:00
$tags = array();
if($link_item['term']) {
$cnt = 0;
2014-10-27 04:37:59 +00:00
foreach($link_item['term'] as $t) {
$tags[$cnt] = array(0 => format_term_for_display($t));
if($can_post && ($ph[0]['uid'] == $owner_uid)) {
$tags[$cnt][1] = 'tagrm/drop/' . $link_item['id'] . '/' . bin2hex($t['term']); //?f=&item=' . $link_item['id'];
$tags[$cnt][2] = t('Remove');
}
$cnt ++;
2014-10-27 04:37:59 +00:00
}
}
if((local_channel()) && (local_user() == $link_item['uid'])) {
q("UPDATE `item` SET item_unseen = 0 WHERE parent = %d and uid = %d and item_unseen = 1",
2010-11-05 03:47:44 +00:00
intval($link_item['parent']),
intval(local_channel())
);
}
if($link_item['coord']) {
$map = generate_map($link_item['coord']);
}
}
2010-08-08 08:58:26 +00:00
// logger('mod_photo: link_item' . print_r($link_item,true));
// FIXME - remove this when we move to conversation module
$r = $r[0]['children'];
2010-11-05 03:47:44 +00:00
$edit = null;
if($can_post) {
$album_e = $ph[0]['album'];
$caption_e = $ph[0]['description'];
$aclselect_e = (($_is_owner) ? populate_acl($ph[0]) : '');
2014-10-30 13:10:55 +00:00
$albums = ((array_key_exists('albums', $a->data)) ? $a->data['albums'] : photos_albums_list($a->data['channel'],$a->data['observer']));
2014-11-03 09:46:57 +00:00
$_SESSION['album_return'] = bin2hex($ph[0]['album']);
$edit = array(
'edit' => t('Edit photo'),
2014-10-30 13:10:55 +00:00
'id' => $link_item['id'],
'rotatecw' => t('Rotate CW (right)'),
'rotateccw' => t('Rotate CCW (left)'),
'albums' => $albums['albums'],
'album' => $album_e,
2014-11-01 22:55:36 +00:00
'newalbum_label' => t('Enter a new album name'),
'newalbum_placeholder' => t('or select an existing one (doubleclick)'),
'nickname' => $a->data['channel']['channel_address'],
'resource_id' => $ph[0]['resource_id'],
'capt_label' => t('Caption'),
'caption' => $caption_e,
'tag_label' => t('Add a Tag'),
'permissions' => t('Permissions'),
'aclselect' => $aclselect_e,
2014-11-07 11:13:38 +00:00
'lockstate' => $lockstate[0],
2014-10-28 11:18:08 +00:00
'help_tags' => t('Example: @bob, @Barbara_Jensen, @jim@example.com'),
'item_id' => ((count($linked_items)) ? $link_item['id'] : 0),
'adult_enabled' => feature_enabled($owner_uid,'adult_photo_flagging'),
2015-05-19 03:10:44 +00:00
'adult' => array('adult',t('Flag as adult in album view'), intval($ph[0]['is_nsfw']),''),
'submit' => t('Submit'),
'delete' => t('Delete Photo')
);
}
2010-08-07 13:20:27 +00:00
2010-11-05 03:47:44 +00:00
if(count($linked_items)) {
2010-08-06 13:30:25 +00:00
2011-05-11 11:37:13 +00:00
$cmnt_tpl = get_markup_template('comment_item.tpl');
$tpl = get_markup_template('photo_item.tpl');
2010-08-06 13:30:25 +00:00
$return_url = $a->cmd;
2011-05-11 11:37:13 +00:00
$like_tpl = get_markup_template('like_noshare.tpl');
$likebuttons = '';
2013-12-20 01:36:31 +00:00
if($can_post || $can_comment) {
$likebuttons = replace_macros($like_tpl,array(
2011-05-05 08:53:03 +00:00
'$id' => $link_item['id'],
'$likethis' => t("I like this \x28toggle\x29"),
'$nolike' => t("I don't like this \x28toggle\x29"),
2011-03-17 02:36:59 +00:00
'$share' => t('Share'),
2011-05-05 08:53:03 +00:00
'$wait' => t('Please wait')
));
}
2011-05-05 08:53:03 +00:00
$comments = '';
if(! count($r)) {
2013-12-20 01:36:31 +00:00
if($can_post || $can_comment) {
2014-10-15 20:41:42 +00:00
$commentbox = replace_macros($cmnt_tpl,array(
'$return_path' => '',
'$mode' => 'photos',
'$jsreload' => $return_url,
'$type' => 'wall-comment',
'$id' => $link_item['id'],
'$parent' => $link_item['id'],
'$profile_uid' => $owner_uid,
'$mylink' => $observer['xchan_url'],
'$mytitle' => t('This is you'),
'$myphoto' => $observer['xchan_photo_s'],
'$comment' => t('Comment'),
'$submit' => t('Submit'),
'$preview' => t('Preview'),
'$ww' => '',
'$feature_encrypt' => false
));
2010-08-06 13:30:25 +00:00
}
}
$alike = array();
$dlike = array();
2011-05-05 08:53:03 +00:00
$like = '';
$dislike = '';
2010-08-06 13:30:25 +00:00
$conv_responses = array(
'like' => array('title' => t('Likes','title')),'dislike' => array('title' => t('Dislikes','title')),
'agree' => array('title' => t('Agree','title')),'disagree' => array('title' => t('Disagree','title')), 'abstain' => array('title' => t('Abstain','title')),
'attendyes' => array('title' => t('Attending','title')), 'attendno' => array('title' => t('Not attending','title')), 'attendmaybe' => array('title' => t('Might attend','title'))
);
2014-10-25 13:23:20 +00:00
2013-04-26 03:01:24 +00:00
if($r) {
foreach($r as $item) {
builtin_activity_puller($item, $conv_responses);
}
2014-10-25 13:23:20 +00:00
$like_count = ((x($alike,$link_item['mid'])) ? $alike[$link_item['mid']] : '');
$like_list = ((x($alike,$link_item['mid'])) ? $alike[$link_item['mid'] . '-l'] : '');
if (count($like_list) > MAX_LIKERS) {
$like_list_part = array_slice($like_list, 0, MAX_LIKERS);
array_push($like_list_part, '<a href="#" data-toggle="modal" data-target="#likeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
} else {
$like_list_part = '';
}
$like_button_label = tt('Like','Likes',$like_count,'noun');
//if (feature_enabled($conv->get_profile_owner(),'dislike')) {
$dislike_count = ((x($dlike,$link_item['mid'])) ? $dlike[$link_item['mid']] : '');
$dislike_list = ((x($dlike,$link_item['mid'])) ? $dlike[$link_item['mid'] . '-l'] : '');
$dislike_button_label = tt('Dislike','Dislikes',$dislike_count,'noun');
if (count($dislike_list) > MAX_LIKERS) {
$dislike_list_part = array_slice($dislike_list, 0, MAX_LIKERS);
array_push($dislike_list_part, '<a href="#" data-toggle="modal" data-target="#dislikeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
} else {
$dislike_list_part = '';
}
//}
2014-10-25 13:23:20 +00:00
$like = ((isset($alike[$link_item['mid']])) ? format_like($alike[$link_item['mid']],$alike[$link_item['mid'] . '-l'],'like',$link_item['mid']) : '');
$dislike = ((isset($dlike[$link_item['mid']])) ? format_like($dlike[$link_item['mid']],$dlike[$link_item['mid'] . '-l'],'dislike',$link_item['mid']) : '');
2014-10-25 13:23:20 +00:00
// display comments
2010-08-06 13:30:25 +00:00
foreach($r as $item) {
$comment = '';
$template = $tpl;
$sparkle = '';
if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE))) && ($item['id'] != $item['parent']))
continue;
2010-08-06 13:30:25 +00:00
$redirect_url = $a->get_baseurl() . '/redir/' . $item['cid'] ;
$profile_url = zid($item['author']['xchan_url']);
$sparkle = '';
$profile_name = $item['author']['xchan_name'];
$profile_avatar = $item['author']['xchan_photo_m'];
2010-08-06 13:30:25 +00:00
$profile_link = $profile_url;
$drop = '';
if($observer['xchan_hash'] === $item['author_xchan'] || $observer['xchan_hash'] === $item['owner_xchan'])
2011-06-16 03:43:39 +00:00
$drop = replace_macros(get_markup_template('photo_drop.tpl'), array('$id' => $item['id'], '$delete' => t('Delete')));
2010-08-06 13:30:25 +00:00
$name_e = $profile_name;
$title_e = $item['title'];
unobscure($item);
$body_e = prepare_text($item['body'],$item['mimetype']);
2011-05-05 08:53:03 +00:00
$comments .= replace_macros($template,array(
'$id' => $item['id'],
'$mode' => 'photos',
2010-08-06 13:30:25 +00:00
'$profile_url' => $profile_link,
2013-01-06 21:42:51 +00:00
'$name' => $name_e,
2010-08-06 13:30:25 +00:00
'$thumb' => $profile_avatar,
'$sparkle' => $sparkle,
2013-01-06 21:42:51 +00:00
'$title' => $title_e,
'$body' => $body_e,
2010-08-06 13:30:25 +00:00
'$ago' => relative_date($item['created']),
2014-10-15 19:17:07 +00:00
'$indent' => (($item['parent'] != $item['id']) ? ' comment' : ''),
2010-08-06 13:30:25 +00:00
'$drop' => $drop,
'$comment' => $comment
));
}
2013-12-20 01:36:31 +00:00
if($can_post || $can_comment) {
$commentbox = replace_macros($cmnt_tpl,array(
'$return_path' => '',
'$jsreload' => $return_url,
'$type' => 'wall-comment',
'$id' => $link_item['id'],
'$parent' => $link_item['id'],
'$profile_uid' => $owner_uid,
'$mylink' => $observer['xchan_url'],
'$mytitle' => t('This is you'),
'$myphoto' => $observer['xchan_photo_s'],
'$comment' => t('Comment'),
'$submit' => t('Submit'),
'$ww' => ''
));
2010-08-06 13:30:25 +00:00
}
}
2011-05-05 08:53:03 +00:00
$paginate = paginate($a);
2010-08-06 13:30:25 +00:00
}
2011-05-05 08:53:03 +00:00
$album_e = array($album_link,$ph[0]['album']);
$like_e = $like;
$dislike_e = $dislike;
2013-01-06 21:42:51 +00:00
$response_verbs = array('like');
if(feature_enabled($owner_uid,'dislike'))
$response_verbs[] = 'dislike';
$responses = get_responses($conv_responses,$response_verbs,'',$link_item);
2011-05-11 11:37:13 +00:00
$photo_tpl = get_markup_template('photo_view.tpl');
2011-05-05 08:53:03 +00:00
$o .= replace_macros($photo_tpl, array(
2014-10-19 23:12:05 +00:00
'$id' => $link_item['id'], //$ph[0]['id'],
2013-01-06 21:42:51 +00:00
'$album' => $album_e,
2011-05-05 08:53:03 +00:00
'$tools' => $tools,
2014-11-07 11:13:38 +00:00
'$lock' => $lockstate[1],
2011-05-05 08:53:03 +00:00
'$photo' => $photo,
'$prevlink' => $prevlink,
'$nextlink' => $nextlink,
'$desc' => $ph[0]['description'],
2014-10-20 13:05:33 +00:00
'$filename' => $ph[0]['filename'],
'$unknown' => t('Unknown'),
'$tag_hdr' => t('In This Photo:'),
'$tags' => $tags,
'responses' => $responses,
2011-05-05 08:53:03 +00:00
'$edit' => $edit,
'$map' => $map,
'$map_text' => t('Map'),
2011-05-05 08:53:03 +00:00
'$likebuttons' => $likebuttons,
2013-01-06 21:42:51 +00:00
'$like' => $like_e,
'$dislike' => $dislike_e,
2014-10-25 13:23:20 +00:00
'$like_count' => $like_count,
'$like_list' => $like_list,
'$like_list_part' => $like_list_part,
'$like_button_label' => $like_button_label,
'$like_modal_title' => t('Likes','noun'),
'$dislike_modal_title' => t('Dislikes','noun'),
'$dislike_count' => $dislike_count, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_count : ''),
'$dislike_list' => $dislike_list, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list : ''),
'$dislike_list_part' => $dislike_list_part, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list_part : ''),
'$dislike_button_label' => $dislike_button_label, //((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_button_label : ''),
'$modal_dismiss' => t('Close'),
2011-05-05 08:53:03 +00:00
'$comments' => $comments,
'$commentbox' => $commentbox,
2011-05-05 08:53:03 +00:00
'$paginate' => $paginate,
));
$a->data['photo_html'] = $o;
2011-05-05 08:53:03 +00:00
2010-08-06 04:15:24 +00:00
return $o;
}
// Default - show recent photos with upload link (if applicable)
//$o = '';
2010-08-06 04:15:24 +00:00
$r = q("SELECT `resource_id`, max(`scale`) AS `scale` FROM `photo` WHERE `uid` = %d AND `album` != '%s' AND `album` != '%s'
2015-05-19 02:43:53 +00:00
and photo_usage in ( %d, %d ) and is_nsfw = %d $sql_extra GROUP BY `resource_id`",
intval($a->data['channel']['channel_id']),
dbesc('Contact Photos'),
dbesc( t('Contact Photos')),
intval(PHOTO_NORMAL),
2015-05-19 02:43:53 +00:00
intval(PHOTO_PROFILE),
intval($unsafe)
2010-08-06 04:15:24 +00:00
);
if(count($r)) {
2010-08-06 04:15:24 +00:00
$a->set_pager_total(count($r));
2014-09-11 11:07:08 +00:00
$a->set_pager_itemspage(60);
}
PostgreSQL support initial commit There were 11 main types of changes: - UPDATE's and DELETE's sometimes had LIMIT 1 at the end of them. This is not only non-compliant but it would certainly not do what whoever wrote it thought it would. It is likely this mistake was just copied from Friendica. All of these instances, the LIMIT 1 was simply removed. - Bitwise operations (and even some non-zero int checks) erroneously rely on MySQL implicit integer-boolean conversion in the WHERE clauses. This is non-compliant (and bad programming practice to boot). Proper explicit boolean conversions were added. New queries should use proper conventions. - MySQL has a different operator for bitwise XOR than postgres. Rather than add yet another dba_ func, I converted them to "& ~" ("AND NOT") when turning off, and "|" ("OR") when turning on. There were no true toggles (XOR). New queries should refrain from using XOR when not necessary. - There are several fields which the schema has marked as NOT NULL, but the inserts don't specify them. The reason this works is because mysql totally ignores the constraint and adds an empty text default automatically. Again, non-compliant, obviously. In these cases a default of empty text was added. - Several statements rely on a non-standard MySQL feature (http://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html). These queries can all be rewritten to be standards compliant. Interestingly enough, the newly rewritten standards compliant queries run a zillion times faster, even on MySQL. - A couple of function/operator name translations were needed (RAND/RANDOM, GROUP_CONCAT/STRING_AGG, UTC_NOW, REGEXP/~, ^/#) -- assist functions added in the dba_ - INTERVALs: postgres requires quotes around the value, mysql requires that there are not quotes around the value -- assist functions added in the dba_ - NULL_DATE's -- Postgres does not allow the invalid date '0000-00-00 00:00:00' (there is no such thing as year 0 or month 0 or day 0). We use '0001-01-01 00:00:00' for postgres. Conversions are handled in Zot/item packets automagically by quoting all dates with dbescdate(). - char(##) specifications in the schema creates fields with blank spaces that aren't trimmed in the code. MySQL apparently treats char(##) as varchar(##), again, non-compliant. Since postgres works better with text fields anyway, this ball of bugs was simply side-stepped by using 'text' datatype for all text fields in the postgres schema. varchar was used in a couple of places where it actually seemed appropriate (size constraint), but without rigorously vetting that all of the PHP code actually validates data, new bugs might come out from under the rug. - postgres doesn't store nul bytes and a few other non-printables in text fields, even when quoted. bytea fields were used when storing binary data (photo.data, attach.data). A new dbescbin() function was added to handle this transparently. - postgres does not support LIMIT #,# syntax. All databases support LIMIT # OFFSET # syntax. Statements were updated to be standard. These changes require corresponding changes in the coding standards. Please review those before adding any code going forward. Still on my TODO list: - remove quotes from non-reserved identifiers and make reserved identifiers use dba func for quoting - Rewrite search queries for better results (both MySQL and Postgres)
2014-11-13 20:21:58 +00:00
$r = q("SELECT p.resource_id, p.id, p.filename, p.type, p.album, p.scale, p.created FROM photo p INNER JOIN
(SELECT resource_id, max(scale) scale FROM photo
WHERE uid=%d AND album != '%s' AND album != '%s'
2015-05-19 02:43:53 +00:00
AND photo_usage IN ( %d, %d ) and is_nsfw = %d $sql_extra group by resource_id) ph
PostgreSQL support initial commit There were 11 main types of changes: - UPDATE's and DELETE's sometimes had LIMIT 1 at the end of them. This is not only non-compliant but it would certainly not do what whoever wrote it thought it would. It is likely this mistake was just copied from Friendica. All of these instances, the LIMIT 1 was simply removed. - Bitwise operations (and even some non-zero int checks) erroneously rely on MySQL implicit integer-boolean conversion in the WHERE clauses. This is non-compliant (and bad programming practice to boot). Proper explicit boolean conversions were added. New queries should use proper conventions. - MySQL has a different operator for bitwise XOR than postgres. Rather than add yet another dba_ func, I converted them to "& ~" ("AND NOT") when turning off, and "|" ("OR") when turning on. There were no true toggles (XOR). New queries should refrain from using XOR when not necessary. - There are several fields which the schema has marked as NOT NULL, but the inserts don't specify them. The reason this works is because mysql totally ignores the constraint and adds an empty text default automatically. Again, non-compliant, obviously. In these cases a default of empty text was added. - Several statements rely on a non-standard MySQL feature (http://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html). These queries can all be rewritten to be standards compliant. Interestingly enough, the newly rewritten standards compliant queries run a zillion times faster, even on MySQL. - A couple of function/operator name translations were needed (RAND/RANDOM, GROUP_CONCAT/STRING_AGG, UTC_NOW, REGEXP/~, ^/#) -- assist functions added in the dba_ - INTERVALs: postgres requires quotes around the value, mysql requires that there are not quotes around the value -- assist functions added in the dba_ - NULL_DATE's -- Postgres does not allow the invalid date '0000-00-00 00:00:00' (there is no such thing as year 0 or month 0 or day 0). We use '0001-01-01 00:00:00' for postgres. Conversions are handled in Zot/item packets automagically by quoting all dates with dbescdate(). - char(##) specifications in the schema creates fields with blank spaces that aren't trimmed in the code. MySQL apparently treats char(##) as varchar(##), again, non-compliant. Since postgres works better with text fields anyway, this ball of bugs was simply side-stepped by using 'text' datatype for all text fields in the postgres schema. varchar was used in a couple of places where it actually seemed appropriate (size constraint), but without rigorously vetting that all of the PHP code actually validates data, new bugs might come out from under the rug. - postgres doesn't store nul bytes and a few other non-printables in text fields, even when quoted. bytea fields were used when storing binary data (photo.data, attach.data). A new dbescbin() function was added to handle this transparently. - postgres does not support LIMIT #,# syntax. All databases support LIMIT # OFFSET # syntax. Statements were updated to be standard. These changes require corresponding changes in the coding standards. Please review those before adding any code going forward. Still on my TODO list: - remove quotes from non-reserved identifiers and make reserved identifiers use dba func for quoting - Rewrite search queries for better results (both MySQL and Postgres)
2014-11-13 20:21:58 +00:00
ON (p.resource_id = ph.resource_id and p.scale = ph.scale) ORDER by p.created DESC LIMIT %d OFFSET %d",
intval($a->data['channel']['channel_id']),
dbesc('Contact Photos'),
2010-08-06 04:15:24 +00:00
dbesc( t('Contact Photos')),
intval(PHOTO_NORMAL),
2015-05-19 02:43:53 +00:00
intval(PHOTO_PROFILE),
intval($unsafe),
PostgreSQL support initial commit There were 11 main types of changes: - UPDATE's and DELETE's sometimes had LIMIT 1 at the end of them. This is not only non-compliant but it would certainly not do what whoever wrote it thought it would. It is likely this mistake was just copied from Friendica. All of these instances, the LIMIT 1 was simply removed. - Bitwise operations (and even some non-zero int checks) erroneously rely on MySQL implicit integer-boolean conversion in the WHERE clauses. This is non-compliant (and bad programming practice to boot). Proper explicit boolean conversions were added. New queries should use proper conventions. - MySQL has a different operator for bitwise XOR than postgres. Rather than add yet another dba_ func, I converted them to "& ~" ("AND NOT") when turning off, and "|" ("OR") when turning on. There were no true toggles (XOR). New queries should refrain from using XOR when not necessary. - There are several fields which the schema has marked as NOT NULL, but the inserts don't specify them. The reason this works is because mysql totally ignores the constraint and adds an empty text default automatically. Again, non-compliant, obviously. In these cases a default of empty text was added. - Several statements rely on a non-standard MySQL feature (http://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html). These queries can all be rewritten to be standards compliant. Interestingly enough, the newly rewritten standards compliant queries run a zillion times faster, even on MySQL. - A couple of function/operator name translations were needed (RAND/RANDOM, GROUP_CONCAT/STRING_AGG, UTC_NOW, REGEXP/~, ^/#) -- assist functions added in the dba_ - INTERVALs: postgres requires quotes around the value, mysql requires that there are not quotes around the value -- assist functions added in the dba_ - NULL_DATE's -- Postgres does not allow the invalid date '0000-00-00 00:00:00' (there is no such thing as year 0 or month 0 or day 0). We use '0001-01-01 00:00:00' for postgres. Conversions are handled in Zot/item packets automagically by quoting all dates with dbescdate(). - char(##) specifications in the schema creates fields with blank spaces that aren't trimmed in the code. MySQL apparently treats char(##) as varchar(##), again, non-compliant. Since postgres works better with text fields anyway, this ball of bugs was simply side-stepped by using 'text' datatype for all text fields in the postgres schema. varchar was used in a couple of places where it actually seemed appropriate (size constraint), but without rigorously vetting that all of the PHP code actually validates data, new bugs might come out from under the rug. - postgres doesn't store nul bytes and a few other non-printables in text fields, even when quoted. bytea fields were used when storing binary data (photo.data, attach.data). A new dbescbin() function was added to handle this transparently. - postgres does not support LIMIT #,# syntax. All databases support LIMIT # OFFSET # syntax. Statements were updated to be standard. These changes require corresponding changes in the coding standards. Please review those before adding any code going forward. Still on my TODO list: - remove quotes from non-reserved identifiers and make reserved identifiers use dba func for quoting - Rewrite search queries for better results (both MySQL and Postgres)
2014-11-13 20:21:58 +00:00
intval($a->pager['itemspage']),
intval($a->pager['start'])
2010-08-06 04:15:24 +00:00
);
2011-12-22 15:33:14 +00:00
$photos = array();
2010-08-06 04:15:24 +00:00
if(count($r)) {
$twist = 'rotright';
2010-08-06 04:15:24 +00:00
foreach($r as $rr) {
if($twist == 'rotright')
$twist = 'rotleft';
else
$twist = 'rotright';
2012-06-07 15:42:13 +00:00
$ext = $phototypes[$rr['type']];
2013-01-07 02:34:54 +00:00
if($a->get_template_engine() === 'internal') {
2013-01-06 21:42:51 +00:00
$alt_e = template_escape($rr['filename']);
$name_e = template_escape($rr['album']);
}
else {
$alt_e = $rr['filename'];
$name_e = $rr['album'];
}
2011-12-22 15:33:14 +00:00
$photos[] = array(
'id' => $rr['id'],
'twist' => ' ' . $twist . rand(2,4),
'link' => $a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/image/' . $rr['resource_id'],
2011-12-22 15:33:14 +00:00
'title' => t('View Photo'),
'src' => $a->get_baseurl() . '/photo/' . $rr['resource_id'] . '-' . ((($rr['scale']) == 6) ? 4 : $rr['scale']) . '.' . $ext,
2013-01-06 21:42:51 +00:00
'alt' => $alt_e,
2011-12-22 15:33:14 +00:00
'album' => array(
'link' => $a->get_baseurl() . '/photos/' . $a->data['channel']['channel_address'] . '/album/' . bin2hex($rr['album']),
2013-01-06 21:42:51 +00:00
'name' => $name_e,
2011-12-22 15:33:14 +00:00
'alt' => t('View Album'),
),
);
2010-08-06 04:15:24 +00:00
}
}
2011-12-22 15:33:14 +00:00
2014-09-06 07:37:15 +00:00
if($_REQUEST['aj']) {
if($photos) {
$o = replace_macros(get_markup_template('photosajax.tpl'),array(
'$photos' => $photos,
2014-09-06 07:37:15 +00:00
));
}
else {
$o = '<div id="content-complete"></div>';
}
echo $o;
killme();
}
else {
2014-09-06 07:48:00 +00:00
$o .= "<script> var page_query = '" . $_GET['q'] . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
2014-09-06 07:37:15 +00:00
$tpl = get_markup_template('photos_recent.tpl');
$o .= replace_macros($tpl, array(
'$title' => t('Recent Photos'),
'$can_post' => $can_post,
2014-09-28 21:14:49 +00:00
'$upload' => array(t('Upload'), $a->get_baseurl().'/photos/'.$a->data['channel']['channel_address'].'/upload'),
2014-09-06 07:37:15 +00:00
'$photos' => $photos,
2014-10-31 19:25:43 +00:00
'$upload_form' => $upload_form,
'$usage' => $usage_message
2014-09-06 07:37:15 +00:00
));
2011-12-22 15:33:14 +00:00
2014-09-06 07:37:15 +00:00
}
if((! $photos) && ($_REQUEST['aj'])) {
$o .= '<div id="content-complete"></div>';
echo $o;
killme();
}
// paginate($a);
2010-08-06 04:15:24 +00:00
return $o;
}