From 20fbf670db15809fd01b155773aab38e6298f670 Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Wed, 30 Dec 2015 00:26:50 +0100
Subject: [PATCH] photo aside widget for profile page

---
 include/features.php               |   6 ++
 include/photos.php                 | 142 +++++++++++++++++++++++++++++
 mod/photos.php                     |  66 ++------------
 mod/profile.php                    |   4 +
 view/global.css                    |  15 +++
 view/templates/widget_photos.tpl   |  18 ++++
 view/theme/duepuntozero/style.css  |  13 ++-
 view/theme/frost-mobile/style.css  |  15 ++-
 view/theme/frost/style.css         |  19 +++-
 view/theme/quattro/dark/style.css  |   5 +-
 view/theme/quattro/green/style.css |   5 +-
 view/theme/quattro/lilac/style.css |  11 ++-
 view/theme/quattro/quattro.less    |   1 +
 view/theme/smoothly/style.css      |   9 ++
 view/theme/vier/style.css          |   6 ++
 15 files changed, 263 insertions(+), 72 deletions(-)
 create mode 100644 view/templates/widget_photos.tpl

diff --git a/include/features.php b/include/features.php
index 263960457..8b3ad5d3f 100644
--- a/include/features.php
+++ b/include/features.php
@@ -79,6 +79,12 @@ function get_features() {
 			array('savedsearch',	t('Saved Searches'),			t('Save search terms for re-use'),false),
 		),
 
+		// Profile sidebar widgets
+		'profile-widgets' => array(
+			t('Profile Sidebar Widgets'),
+			array('photos_widget',	t('Show last Photos'),			t('Show your last Photos on the Profile Page Sidebar'),false),
+		),
+
 		// Network tabs
 		'net_tabs' => array(
 			t('Network Tabs'),
diff --git a/include/photos.php b/include/photos.php
index 93a565b51..fed4ab10c 100644
--- a/include/photos.php
+++ b/include/photos.php
@@ -4,6 +4,148 @@
  * @brief Functions related to photo handling.
  */
 
+
+/**
+ * @brief Get the permissions for the photos page
+ * 
+ * @param int $owner_uid Owner of the photos page
+ * @param bool $community_page If it's an forum account
+ * 
+ * @return array
+ *......'can_post'
+ *......'visitor'
+ *......'contact'
+ *      'remote_contact'
+ * .....'contact_id'
+ *      'groups'
+ */
+function photos_permissions($owner_uid, $community_page = 0) {
+
+	$arr = array();
+
+	if((local_user()) && (local_user() == $owner_uid))
+		$arr['can_post'] = true;
+	else {
+		if($community_page && remote_user()) {
+			if(is_array($_SESSION['remote'])) {
+				foreach($_SESSION['remote'] as $v) {
+					if($v['uid'] == $owner_uid) {
+						$arr['contact_id'] = $v['cid'];
+						break;
+					}
+				}
+			}
+			if($arr['contact_id']) {
+
+				$r = q("SELECT `uid` FROM `contact` WHERE `blocked` = 0 AND `pending` = 0 AND `id` = %d AND `uid` = %d LIMIT 1",
+					intval($arr['contact_id']),
+					intval($owner_uid)
+				);
+				if(count($r)) {
+					$arr['can_post'] = true;
+					$arr['contact'] = $r[0];
+					$arr['remote_contact'] = true;
+					$arr['visitor'] = $cid;
+				}
+			}
+		}
+	}
+
+	// perhaps they're visiting - but not a community page, so they wouldn't have write access
+
+	if(remote_user() && (! $arr['visitor'])) {
+		$arr['contact_id'] = 0;
+		if(is_array($_SESSION['remote'])) {
+			foreach($_SESSION['remote'] as $v) {
+				if($v['uid'] == $owner_uid) {
+					$arr['contact_id'] = $v['cid'];
+					break;
+				}
+			}
+		}
+		if($arr['contact_id']) {
+			$arr['groups'] = init_groups_visitor($arr['contact_id']);
+			$r = q("SELECT * FROM `contact` WHERE `blocked` = 0 AND `pending` = 0 AND `id` = %d AND `uid` = %d LIMIT 1",
+				intval($arr['contact_id']),
+				intval($owner_uid)
+			);
+			if(count($r)) {
+				$arr['contact'] = $r[0];
+				$arr['remote_contact'] = true;
+			}
+		}
+	}
+
+	if(! $arr['remote_contact']) {
+		if(local_user()) {
+			$arr['contact_id'] = $_SESSION['cid'];
+			$arr['contact'] = $a->contact;
+		}
+	}
+
+	return $arr;
+}
+
+/**
+ * @brief Construnct a widget with last uploaded photos
+ * 
+ * It displays the last 9 photos
+ * 
+ * @param array $profile_data
+ *......'profile_uid'...=> The user.id of the profile (owner of the hotos)
+ *......'nickname'......=> Nick of the owner of the profile
+ *......'page-flags'....=> Account type of the profile
+ * 
+ * @return string
+ *......formatted html
+ * 
+ * @template widget_photos.tpl
+ */
+function widget_photos($profile_data) {
+
+	$community_page = (($profile_data['page-flags'] == PAGE_COMMUNITY) ? true : false);
+	$nickname = $profile_data['nickname'];
+	$owner_id = $profile_data['profile_uid'];
+
+	$phototypes = Photo::supportedTypes();
+	$photos_perms = photos_permissions($owner_id, $community_page);
+
+	$sql_extra = permissions_sql($owner_id, $photos_perms['remote_contact'], $photos_perms['groups']);
+
+	$r = q("SELECT `resource-id`, `id`, `filename`, `type`, max(`scale`) AS `scale` FROM `photo`
+		WHERE `uid` = %d AND `album` != '%s' AND `album` != '%s' AND `album` != '%s'
+		$sql_extra GROUP BY `resource-id` ORDER BY `created` DESC LIMIT 9",
+		intval($owner_id),
+		dbesc('Contact Photos'),
+		dbesc( t('Contact Photos')),
+		dbesc( t('Profile Photos'))
+	);
+
+	$photos = array();
+	if(count($r)) {
+		foreach($r as $rr) {
+			$ext = $phototypes[$rr['type']];
+	
+			$photos[] = array(
+				'id'		=> $rr['id'],
+				'src'		=> z_root() . '/photos/' . $nickname . '/image/' . $rr['resource-id'],
+				'photo'		=> z_root() . '/photo/' . $rr['resource-id'] . '-' . ((($rr['scale']) == 6) ? 4 : $rr['scale']) . '.' . $ext,
+				'alt_text'	=> $rr['filename'],
+			);
+		}
+
+		$tpl = get_markup_template('widget_photos.tpl');
+		$o .= replace_macros($tpl, array(
+			'$title' => t('Photos'),
+			'$photos' => $photos,
+			'$photo_albums_page'	=> z_root() . '/photos/' . $nickname,
+			'$photo_albums_page_title' => t('Vist the Photo Albums'),
+		));
+
+		return $o;
+	}
+}
+
 function getGps($exifCoord, $hemi) {
 	$degrees = count($exifCoord) > 0 ? gps2Num($exifCoord[0]) : 0;
 	$minutes = count($exifCoord) > 1 ? gps2Num($exifCoord[1]) : 0;
diff --git a/mod/photos.php b/mod/photos.php
index a9dade6a8..cd2026c25 100644
--- a/mod/photos.php
+++ b/mod/photos.php
@@ -1023,63 +1023,13 @@ function photos_content(&$a) {
 
 	$community_page = (($a->data['user']['page-flags'] == PAGE_COMMUNITY) ? true : false);
 
-	if((local_user()) && (local_user() == $owner_uid))
-		$can_post = true;
-	else {
-		if($community_page && remote_user()) {
-			if(is_array($_SESSION['remote'])) {
-				foreach($_SESSION['remote'] as $v) {
-					if($v['uid'] == $owner_uid) {
-						$contact_id = $v['cid'];
-						break;
-					}
-				}
-			}
-			if($contact_id) {
+	// get the access rights for photos
+	$photos_perms = photos_permissions($owner_uid, $community_page);
 
-				$r = q("SELECT `uid` FROM `contact` WHERE `blocked` = 0 AND `pending` = 0 AND `id` = %d AND `uid` = %d LIMIT 1",
-					intval($contact_id),
-					intval($owner_uid)
-				);
-				if(count($r)) {
-					$can_post = true;
-					$contact = $r[0];
-					$remote_contact = true;
-					$visitor = $cid;
-				}
-			}
-		}
-	}
-
-	// perhaps they're visiting - but not a community page, so they wouldn't have write access
-
-	if(remote_user() && (! $visitor)) {
-		$contact_id = 0;
-		if(is_array($_SESSION['remote'])) {
-			foreach($_SESSION['remote'] as $v) {
-				if($v['uid'] == $owner_uid) {
-					$contact_id = $v['cid'];
-					break;
-				}
-			}
-		}
-		if($contact_id) {
-			$groups = init_groups_visitor($contact_id);
-			$r = q("SELECT * FROM `contact` WHERE `blocked` = 0 AND `pending` = 0 AND `id` = %d AND `uid` = %d LIMIT 1",
-				intval($contact_id),
-				intval($owner_uid)
-			);
-			if(count($r)) {
-				$contact = $r[0];
-				$remote_contact = true;
-			}
-		}
-	}
-
-	if(! $remote_contact) {
-		if(local_user()) {
-			$contact_id = $_SESSION['cid'];
-			$contact = $a->contact;
+	// convert keys of the $photo_persms array into variables
+	if(count($photos_perms)) {
+		foreach ($photos_perms as $key => $value) {
+			${$key} = $value;
 		}
 	}
 
@@ -1088,7 +1038,7 @@ function photos_content(&$a) {
 		return;
 	}
 
-	$sql_extra = permissions_sql($owner_uid,$remote_contact,$groups);
+	$sql_extra = permissions_sql($owner_uid, $remote_contact, $groups);
 
 	$o = "";
 
@@ -1842,7 +1792,7 @@ function photos_content(&$a) {
 		$a->set_pager_itemspage(20);
 	}
 
-	$r = q("SELECT `resource-id`, `id`, `filename`, type, `album`, max(`scale`) AS `scale` FROM `photo`
+	$r = q("SELECT `resource-id`, `id`, `filename`, `type`, `album`, max(`scale`) AS `scale` FROM `photo`
 		WHERE `uid` = %d AND `album` != '%s' AND `album` != '%s'
 		$sql_extra GROUP BY `resource-id` ORDER BY `created` DESC LIMIT %d , %d",
 		intval($a->data['user']['uid']),
diff --git a/mod/profile.php b/mod/profile.php
index 26bd39523..0913573a8 100644
--- a/mod/profile.php
+++ b/mod/profile.php
@@ -181,6 +181,10 @@ function profile_content(&$a, $update = 0) {
 		$commpage = (($a->profile['page-flags'] == PAGE_COMMUNITY) ? true : false);
 		$commvisitor = (($commpage && $remote_contact == true) ? true : false);
 
+		if(feature_enabled($a->profile['profile_uid'],'photos_widget')) {
+			require_once('include/photos.php');
+			$a->page['aside'] .= widget_photos($a->profile);
+		}
 		$a->page['aside'] .= posted_date_widget($a->get_baseurl(true) . '/profile/' . $a->profile['nickname'],$a->profile['profile_uid'],true);
 		$a->page['aside'] .= categories_widget($a->get_baseurl(true) . '/profile/' . $a->profile['nickname'],(x($category) ? xmlify($category) : ''));
 
diff --git a/view/global.css b/view/global.css
index 05940508c..09168a52b 100644
--- a/view/global.css
+++ b/view/global.css
@@ -321,3 +321,18 @@ ul.credits li {
 .p-addr {
 	clear: both;	
 }
+
+.widget-photo {
+        float: left;
+}
+
+.widget-photo-link {
+        margin: 0 2px 2px 0;
+}
+
+img.widget-photo-img {
+	width: 48px;
+	height: 48px;
+	object-fit: cover;
+	padding-right: 2px;
+}
diff --git a/view/templates/widget_photos.tpl b/view/templates/widget_photos.tpl
new file mode 100644
index 000000000..1e56c8df1
--- /dev/null
+++ b/view/templates/widget_photos.tpl
@@ -0,0 +1,18 @@
+
+<div id="sidebar_photos_widget" class="widget">
+	<h3><a href="{{$photo_albums}}" title="{{$photo_albums_page_title}}">{{$title}}</a></h3>
+
+	<div id="widget_photos_wrapper">
+	{{foreach $photos as $photo}}
+		<div class="widget_photo_container">
+			<div class="widget-photo" id="widget-photo-{{$photo.id}}" >
+				<a href="{{$photo.src}}" class="widget-photo-link" id="widget-photo-link-{{$photo.id}}" >
+					<img class="widget-photo-img" src="{{$photo.photo}}" alt="{{$photo.alt_text}}" title="{{$photo.alt_text}}" />
+				</a>
+			</div>
+		</div>
+	{{/foreach}}
+	</div>
+
+	<div class="clear"></div>
+</div>
\ No newline at end of file
diff --git a/view/theme/duepuntozero/style.css b/view/theme/duepuntozero/style.css
index c004eb53d..bfffeb250 100644
--- a/view/theme/duepuntozero/style.css
+++ b/view/theme/duepuntozero/style.css
@@ -140,12 +140,12 @@ nav #banner #logo-text a:hover { text-decoration: none; }
 
 
 .nav-commlink, .nav-login-link {
-    display: block;
-    height: 15px;
+	display: block;
+	height: 15px;
 	margin-top: 67px;
 	margin-right: 2px;
-	//padding: 6px 10px;
-       padding: 6px 3px;
+	/* padding: 6px 10px; */
+	padding: 6px 3px;
 	float: left;
 	bottom: 140px;
 	border: 1px solid #babdb6;
@@ -244,7 +244,7 @@ section {
 	display:block;
 	float:left;
 	padding: 0.4em;
-	//margin-right: 1em;
+	/*margin-right: 1em; */
 	margin-right: 3px ;
 }
 .tab.active {
@@ -2164,6 +2164,9 @@ aside input[type='text'] {
 
 }
 
+.widget h3 a {
+	color: #000000;
+}
 
 /*.photos {
 	height: auto;
diff --git a/view/theme/frost-mobile/style.css b/view/theme/frost-mobile/style.css
index 400b23c10..94e5120c0 100644
--- a/view/theme/frost-mobile/style.css
+++ b/view/theme/frost-mobile/style.css
@@ -2541,6 +2541,14 @@ a.mail-list-link {
 	margin: 10px 0 10px;
 }
 
+.widget-photo {
+	float: left;
+}
+
+.widget-photo-link {
+	margin: 0 2px 2px 0;
+}
+
 #sidebar-group-list ul {
 	list-style-type: none;
 }
@@ -2626,12 +2634,15 @@ aside input[type='text'] {
 	-webkit-border-radius:5px;
 	border-radius:5px;
 }
+
+.widget h3 a {
+	color: #505050;
+}
+
 .widget.settings-widget {
 	padding: 0;
 }
 
-
-
 /*.photos {
 	height: auto;
 	overflow: auto;
diff --git a/view/theme/frost/style.css b/view/theme/frost/style.css
index 3dd400c76..3adf91ad6 100644
--- a/view/theme/frost/style.css
+++ b/view/theme/frost/style.css
@@ -2356,6 +2356,21 @@ a.mail-list-link {
 	margin: 10px 0 10px;
 }
 
+.widget-photo {
+	float: left;
+}
+
+.widget-photo-link {
+	margin: 0 2px 2px 0;
+}
+
+img.widget-photo-img {
+	width: 48px;
+	height: 48px;
+	object-fit: cover;
+	padding-right: 2px;
+}
+
 #sidebar-group-list ul {
 	list-style-type: none;
 }
@@ -2446,9 +2461,11 @@ aside input[type='text'] {
 	-moz-border-radius:5px;
 	-webkit-border-radius:5px;
 	border-radius:5px;
-
 }
 
+.widget h3  a {
+	color: #505050;
+}
 
 /*.photos {
 	height: auto;
diff --git a/view/theme/quattro/dark/style.css b/view/theme/quattro/dark/style.css
index 847017ee5..ebb997741 100644
--- a/view/theme/quattro/dark/style.css
+++ b/view/theme/quattro/dark/style.css
@@ -463,7 +463,7 @@ a:hover {
   text-decoration: underline;
 }
 blockquote {
-  background: #FFFFFF;
+  background: #ffffff;
   padding: 1em;
   margin-left: 1em;
   border-left: 1em solid #e6e6e6;
@@ -1007,6 +1007,9 @@ aside .posted-date-selector-months {
   padding: 0;
   margin: 2px;
 }
+.widget h3 a {
+  color: #2d2d2d;
+}
 .widget .action {
   opacity: 0.1;
   -webkit-transition: all 0.2s ease-in-out;
diff --git a/view/theme/quattro/green/style.css b/view/theme/quattro/green/style.css
index 4cfcb5927..5c2661e91 100644
--- a/view/theme/quattro/green/style.css
+++ b/view/theme/quattro/green/style.css
@@ -463,7 +463,7 @@ a:hover {
   text-decoration: underline;
 }
 blockquote {
-  background: #FFFFFF;
+  background: #ffffff;
   padding: 1em;
   margin-left: 1em;
   border-left: 1em solid #e6e6e6;
@@ -1007,6 +1007,9 @@ aside .posted-date-selector-months {
   padding: 0;
   margin: 2px;
 }
+.widget h3 a {
+  color: #2d2d2d;
+}
 .widget .action {
   opacity: 0.1;
   -webkit-transition: all 0.2s ease-in-out;
diff --git a/view/theme/quattro/lilac/style.css b/view/theme/quattro/lilac/style.css
index 2ff7cfcb0..32f1ccaf6 100644
--- a/view/theme/quattro/lilac/style.css
+++ b/view/theme/quattro/lilac/style.css
@@ -420,7 +420,7 @@
 body {
   font-family: Liberation Sans, helvetica, arial, clean, sans-serif;
   font-size: 11px;
-  background-color: #F6ECF9;
+  background-color: #f6ecf9;
   color: #2d2d2d;
   margin: 50px 0 0 0;
   display: table;
@@ -463,7 +463,7 @@ a:hover {
   text-decoration: underline;
 }
 blockquote {
-  background: #FFFFFF;
+  background: #ffffff;
   padding: 1em;
   margin-left: 1em;
   border-left: 1em solid #e6e6e6;
@@ -1007,6 +1007,9 @@ aside .posted-date-selector-months {
   padding: 0;
   margin: 2px;
 }
+.widget h3 a {
+  color: #2d2d2d;
+}
 .widget .action {
   opacity: 0.1;
   -webkit-transition: all 0.2s ease-in-out;
@@ -1753,7 +1756,7 @@ span[id^="showmore-wrap"] {
   height: 20px;
   width: 500px;
   font-weight: bold;
-  border: 1px solid #F6ECF9;
+  border: 1px solid #f6ecf9;
 }
 #jot #jot-title:-webkit-input-placeholder {
   font-weight: normal;
@@ -1780,7 +1783,7 @@ span[id^="showmore-wrap"] {
   margin: 0;
   height: 20px;
   width: 200px;
-  border: 1px solid #F6ECF9;
+  border: 1px solid #f6ecf9;
 }
 #jot #jot-category:hover {
   border: 1px solid #999999;
diff --git a/view/theme/quattro/quattro.less b/view/theme/quattro/quattro.less
index 681cfcc37..8822fc3de 100644
--- a/view/theme/quattro/quattro.less
+++ b/view/theme/quattro/quattro.less
@@ -454,6 +454,7 @@ aside {
 	margin-bottom: 2em;
 
 	h3 { padding: 0; margin: 2px;}
+	h3 a { color: @BodyColor; }
 	.action { .opaque(0.1); }
 	input.action { .opaque(0.5); }
 	&:hover .title .action { .opaque(1); }
diff --git a/view/theme/smoothly/style.css b/view/theme/smoothly/style.css
index b9f094932..512330749 100644
--- a/view/theme/smoothly/style.css
+++ b/view/theme/smoothly/style.css
@@ -1019,6 +1019,15 @@ ul .sidebar-group-li .icon {
 	text-shadow: -1px 0px 0px #bdbdbd;
 }
 
+.widget h3 a {
+	color: #626262;
+}
+
+.widget h3 a:hover, .widget h3 a:focus {
+	color: #6da6c4;
+	text-decoration: none;
+}
+
 #connect-desc {
 	margin-left: 10px;
 }
diff --git a/view/theme/vier/style.css b/view/theme/vier/style.css
index e53ac45f7..df503e273 100644
--- a/view/theme/vier/style.css
+++ b/view/theme/vier/style.css
@@ -1141,6 +1141,12 @@ aside h4, right_aside h4 {
   padding: 0px;
   margin: 2px;
 }
+.widget h3  a {
+  color: #737373;
+}
+.widget h3 a:hover {
+  color: black;
+}
 .widget .action {
   opacity: 0.1;
   -webkit-transition: all 0.2s ease-in-out;