}
});
+ $dispatcher->addListener('OC\AccountManager::userUpdated', function(GenericEvent $event) {
+ $user = $event->getSubject();
+ $syncService = $this->getContainer()->query(SyncService::class);
+ $syncService->updateUser($user);
+ });
+
$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::createCalendar', function(GenericEvent $event) {
/** @var Backend $backend */
$backend = $this->getContainer()->query(Backend::class);
);
});
+ $dispatcher->addListener('OC\AccountManager::userUpdated', function(GenericEvent $event) {
+ error_log("hello");
+ });
+
$listener = function(GenericEvent $event, $eventName) {
/** @var Backend $backend */
$backend = $this->getContainer()->query(Backend::class);
namespace OCA\DAV\CardDAV;
+use OC\Accounts\AccountManager;
use OCP\IImage;
use OCP\IUser;
use Sabre\VObject\Component\VCard;
class Converter {
+ /** @var AccountManager */
+ private $accountManager;
+
/**
- * @param IUser $user
- * @return VCard
+ * Converter constructor.
+ *
+ * @param AccountManager $accountManager
*/
- public function createCardFromUser(IUser $user) {
-
- $uid = $user->getUID();
- $displayName = $user->getDisplayName();
- $displayName = empty($displayName ) ? $uid : $displayName;
- $emailAddress = $user->getEMailAddress();
- $cloudId = $user->getCloudId();
- $image = $this->getAvatarImage($user);
-
- $vCard = new VCard();
- $vCard->VERSION = '3.0';
- $vCard->UID = $uid;
- if (!empty($displayName)) {
- $vCard->FN = $displayName;
- $vCard->N = $this->splitFullName($displayName);
- }
- if (!empty($emailAddress)) {
- $vCard->add(new Text($vCard, 'EMAIL', $emailAddress, ['TYPE' => 'OTHER']));
- }
- if (!empty($cloudId)) {
- $vCard->CLOUD = $cloudId;
- }
- if ($image) {
- $vCard->add('PHOTO', $image->data(), ['ENCODING' => 'b', 'TYPE' => $image->mimeType()]);
- }
- $vCard->validate();
-
- return $vCard;
+ public function __construct(AccountManager $accountManager) {
+ $this->accountManager = $accountManager;
}
/**
- * @param VCard $vCard
* @param IUser $user
- * @return bool
+ * @return VCard|null
*/
- public function updateCard(VCard $vCard, IUser $user) {
+ public function createCardFromUser(IUser $user) {
+
+ $userData = $this->accountManager->getUser($user);
+
$uid = $user->getUID();
- $displayName = $user->getDisplayName();
- $displayName = empty($displayName ) ? $uid : $displayName;
- $emailAddress = $user->getEMailAddress();
$cloudId = $user->getCloudId();
$image = $this->getAvatarImage($user);
- $updated = false;
- if($this->propertyNeedsUpdate($vCard, 'FN', $displayName)) {
- $vCard->FN = new Text($vCard, 'FN', $displayName);
- unset($vCard->N);
- $vCard->add(new Text($vCard, 'N', $this->splitFullName($displayName)));
- $updated = true;
- }
- if($this->propertyNeedsUpdate($vCard, 'EMAIL', $emailAddress)) {
- $vCard->EMAIL = new Text($vCard, 'EMAIL', $emailAddress);
- $updated = true;
- }
- if($this->propertyNeedsUpdate($vCard, 'CLOUD', $cloudId)) {
- $vCard->CLOUD = new Text($vCard, 'CLOUD', $cloudId);
- $updated = true;
- }
-
- if($this->propertyNeedsUpdate($vCard, 'PHOTO', $image)) {
- unset($vCard->PHOTO);
- $vCard->add('PHOTO', $image->data(), ['ENCODING' => 'b', 'TYPE' => $image->mimeType()]);
- $updated = true;
- }
-
- if (empty($emailAddress) && !is_null($vCard->EMAIL)) {
- unset($vCard->EMAIL);
- $updated = true;
- }
- if (empty($cloudId) && !is_null($vCard->CLOUD)) {
- unset($vCard->CLOUD);
- $updated = true;
- }
- if (empty($image) && !is_null($vCard->PHOTO)) {
- unset($vCard->PHOTO);
- $updated = true;
+ $vCard = new VCard();
+ $vCard->add(new Text($vCard, 'UID', $uid));
+
+ $publish = false;
+
+ foreach ($userData as $property => $value) {
+ if ($value['scope'] === AccountManager::VISIBILITY_CONTACTS_ONLY ||
+ $value['scope'] === AccountManager::VISIBILITY_PUBLIC
+ ) {
+ $publish = true;
+ switch ($property) {
+ case AccountManager::PROPERTY_DISPLAYNAME:
+ $vCard->add(new Text($vCard, 'FN', $value['value']));
+ $vCard->add(new Text($vCard, 'N', $this->splitFullName($value['value'])));
+ break;
+ case AccountManager::PROPERTY_AVATAR:
+ if ($image !== null) {
+ $vCard->add('PHOTO', $image->data(), ['ENCODING' => 'b', 'TYPE' => $image->mimeType()]);
+ }
+ break;
+ case AccountManager::PROPERTY_EMAIL:
+ $vCard->add(new Text($vCard, 'EMAIL', $value['value'], ['TYPE' => 'OTHER']));
+ break;
+ case AccountManager::PROPERTY_WEBSITE:
+ $vCard->add(new Text($vCard, 'URL', $value['value']));
+ break;
+ case AccountManager::PROPERTY_PHONE:
+ $vCard->add(new Text($vCard, 'TEL', $value['value'], ['TYPE' => 'OTHER']));
+ break;
+ case AccountManager::PROPERTY_ADDRESS:
+ $vCard->add(new Text($vCard, 'ADR', $value['value'], ['TYPE' => 'OTHER']));
+ break;
+ case AccountManager::PROPERTY_TWITTER:
+ $vCard->add(new Text($vCard, 'X-SOCIALPROFILE', $value['value'], ['TYPE' => 'TWITTER']));
+ break;
+ }
+ }
}
- return $updated;
- }
-
- /**
- * @param VCard $vCard
- * @param string $name
- * @param string|IImage $newValue
- * @return bool
- */
- private function propertyNeedsUpdate(VCard $vCard, $name, $newValue) {
- if (is_null($newValue)) {
- return false;
+ if ($publish && !empty($cloudId)) {
+ $vCard->add(new Text($vCard, 'CLOUD', $cloudId));
+ $vCard->validate();
+ return $vCard;
}
- $value = $vCard->__get($name);
- if (!is_null($value)) {
- $value = $value->getValue();
- $newValue = $newValue instanceof IImage ? $newValue->data() : $newValue;
- return $value !== $newValue;
- }
- return true;
+ return null;
}
/**
namespace OCA\DAV\CardDAV;
+use OC\Accounts\AccountManager;
use OCP\AppFramework\Http;
use OCP\ILogger;
use OCP\IUser;
/** @var array */
private $localSystemAddressBook;
- public function __construct(CardDavBackend $backend, IUserManager $userManager, ILogger $logger) {
+ /** @var AccountManager */
+ private $accountManager;
+
+ /**
+ * SyncService constructor.
+ *
+ * @param CardDavBackend $backend
+ * @param IUserManager $userManager
+ * @param ILogger $logger
+ * @param AccountManager $accountManager
+ */
+ public function __construct(CardDavBackend $backend, IUserManager $userManager, ILogger $logger, AccountManager $accountManager) {
$this->backend = $backend;
$this->userManager = $userManager;
$this->logger = $logger;
+ $this->accountManager = $accountManager;
}
/**
public function updateUser($user) {
$systemAddressBook = $this->getLocalSystemAddressBook();
$addressBookId = $systemAddressBook['id'];
- $converter = new Converter();
+ $converter = new Converter($this->accountManager);
$name = $user->getBackendClassName();
$userId = $user->getUID();
$card = $this->backend->getCard($addressBookId, $cardId);
if ($card === false) {
$vCard = $converter->createCardFromUser($user);
- $this->backend->createCard($addressBookId, $cardId, $vCard->serialize());
+ if ($vCard !== null) {
+ $this->backend->createCard($addressBookId, $cardId, $vCard->serialize());
+ }
} else {
- $vCard = Reader::read($card['carddata']);
- if ($converter->updateCard($vCard, $user)) {
+ $vCard = $converter->createCardFromUser($user);
+ if (is_null($vCard)) {
+ $this->backend->deleteCard($addressBookId, $cardId);
+ } else {
$this->backend->updateCard($addressBookId, $cardId, $vCard->serialize());
}
}
use OCP\IUser;
use OCP\IUserManager;
use OCP\Util;
+use Symfony\Component\EventDispatcher\EventDispatcher;
+use Symfony\Component\EventDispatcher\GenericEvent;
class HookManager {
/** @var array */
private $addressBooksToDelete;
+ /** @var EventDispatcher */
+ private $eventDispatcher;
+
public function __construct(IUserManager $userManager,
SyncService $syncService,
CalDavBackend $calDav,
- CardDavBackend $cardDav) {
+ CardDavBackend $cardDav,
+ EventDispatcher $eventDispatcher) {
$this->userManager = $userManager;
$this->syncService = $syncService;
$this->calDav = $calDav;
$this->cardDav = $cardDav;
+ $this->eventDispatcher = $eventDispatcher;
}
public function setup() {
<?php
/**
- * @author Björn Schießle <schiessle@owncloud.com>
+ * @author Björn Schießle <bjoern@schiessle.org>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @copyright Copyright (c) 2016, Björn Schießle
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
use OCP\IDBConnection;
+use OCP\IUser;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\EventDispatcher\GenericEvent;
/**
* Class AccountManager
*/
class AccountManager {
+ /** nobody can see my account details */
+ const VISIBILITY_PRIVATE = 'private';
+ /** only contacts, especially trusted servers can see my contact details */
+ const VISIBILITY_CONTACTS_ONLY = 'contacts';
+ /** every body ca see my contact detail, will be published to the lookup server */
+ const VISIBILITY_PUBLIC = 'public';
+
+ const PROPERTY_AVATAR = 'avatar';
+ const PROPERTY_DISPLAYNAME = 'displayname';
+ const PROPERTY_PHONE = 'phone';
+ const PROPERTY_EMAIL = 'email';
+ const PROPERTY_WEBSITE = 'website';
+ const PROPERTY_ADDRESS = 'address';
+ const PROPERTY_TWITTER = 'twitter';
+
/** @var IDBConnection database connection */
private $connection;
/** @var string table name */
private $table = 'accounts';
+ /** @var EventDispatcherInterface */
+ private $eventDispatcher;
+
/**
* AccountManager constructor.
*
* @param IDBConnection $connection
+ * @param EventDispatcherInterface $eventDispatcher
*/
- public function __construct(IDBConnection $connection) {
+ public function __construct(IDBConnection $connection, EventDispatcherInterface $eventDispatcher) {
$this->connection = $connection;
+ $this->eventDispatcher = $eventDispatcher;
}
- public function updateUser($uid, $data) {
- $userData = $this->getUser($uid);
+ /**
+ * update user record
+ *
+ * @param IUser $user
+ * @param $data
+ */
+ public function updateUser(IUser $user, $data) {
+ $userData = $this->getUser($user);
if (empty($userData)) {
- $this->insertNewUser($uid, $data);
+ $this->insertNewUser($user, $data);
} else {
- $this->updateExistingUser($uid, $data);
+ $this->updateExistingUser($user, $data);
}
+
+ $this->eventDispatcher->dispatch(
+ 'OC\AccountManager::userUpdated',
+ new GenericEvent($user)
+ );
}
/**
* get stored data from a given user
*
- * @param $uid
+ * @param IUser $user
* @return array
*/
- public function getUser($uid) {
+ public function getUser(IUser $user) {
+ $uid = $user->getUID();
$query = $this->connection->getQueryBuilder();
$query->select('data')->from($this->table)
->where($query->expr()->eq('uid', $query->createParameter('uid')))
$result = $query->execute()->fetchAll();
if (empty($result)) {
- return [];
+ $userData = $this->buildDefaultUserRecord($user);
+ $this->insertNewUser($user, $userData);
+ return $userData;
}
return json_decode($result[0]['data'], true);
/**
* add new user to accounts table
*
- * @param string $uid
+ * @param IUser $user
* @param array $data
*/
- protected function insertNewUser($uid, $data) {
+ protected function insertNewUser(IUser $user, $data) {
+ $uid = $user->getUID();
$jsonEncodedData = json_encode($data);
$query = $this->connection->getQueryBuilder();
$query->insert($this->table)
/**
* update existing user in accounts table
*
- * @param string $uid
+ * @param IUser $user
* @param array $data
*/
- protected function updateExistingUser($uid, $data) {
+ protected function updateExistingUser(IUser $user, $data) {
+ $uid = $user->getUID();
$jsonEncodedData = json_encode($data);
$query = $this->connection->getQueryBuilder();
$query->update($this->table)
->where($query->expr()->eq('uid', $query->createNamedParameter($uid)))
->execute();
}
+
+ /**
+ * build default user record in case not data set exists yet
+ *
+ * @param IUser $user
+ * @return array
+ */
+ protected function buildDefaultUserRecord(IUser $user) {
+ return [
+ self::PROPERTY_DISPLAYNAME =>
+ [
+ 'value' => $user->getDisplayName(),
+ 'scope' => self::VISIBILITY_CONTACTS_ONLY,
+ ],
+ self::PROPERTY_ADDRESS =>
+ [
+ 'value' => '',
+ 'scope' => self::VISIBILITY_PRIVATE,
+ ],
+ self::PROPERTY_WEBSITE =>
+ [
+ 'value' => '',
+ 'scope' => self::VISIBILITY_PRIVATE,
+ ],
+ self::PROPERTY_EMAIL =>
+ [
+ 'value' => $user->getEMailAddress(),
+ 'scope' => self::VISIBILITY_CONTACTS_ONLY,
+ ],
+ self::PROPERTY_AVATAR =>
+ [
+ 'scope' => self::VISIBILITY_CONTACTS_ONLY
+ ],
+ self::PROPERTY_PHONE =>
+ [
+ 'value' => '',
+ 'scope' => self::VISIBILITY_PRIVATE,
+ ],
+ self::PROPERTY_TWITTER =>
+ [
+ 'value' => '',
+ 'scope' => self::VISIBILITY_PRIVATE,
+ ],
+ ];
+ }
+
}
/** @var ILogger $log */
private $log;
-
+
/** @var IConfig */
private $config;
* @param string $websiteScope
* @param string $address
* @param string $addressScope
+ * @param string $twitter
+ * @param string $twitterScope
* @return DataResponse
*/
public function setUserSettings($avatarScope,
$phone, $phoneScope,
$email, $emailScope,
$website, $websiteScope,
- $address, $addressScope
+ $address, $addressScope,
+ $twitter, $twitterScope
) {
);
}
- $userId = $this->userSession->getUser()->getUID();
+ $user = $this->userSession->getUser();
$data = [
- 'avatar' => ['scope' => $avatarScope],
- 'displayName' => ['value' => $displayname, 'scope' => $displaynameScope],
- 'email' => [['value' => $email, 'scope' => $emailScope]],
- 'website' => [['value' => $website, 'scope' => $websiteScope]],
- 'address' => [['value' => $address, 'scope' => $addressScope]],
- 'phone' => [['value' => $phone, 'scope' => $phoneScope]]
+ AccountManager::PROPERTY_AVATAR => ['scope' => $avatarScope],
+ AccountManager::PROPERTY_DISPLAYNAME => ['value' => $displayname, 'scope' => $displaynameScope],
+ AccountManager::PROPERTY_EMAIL=> ['value' => $email, 'scope' => $emailScope],
+ AccountManager::PROPERTY_WEBSITE => ['value' => $website, 'scope' => $websiteScope],
+ AccountManager::PROPERTY_ADDRESS => ['value' => $address, 'scope' => $addressScope],
+ AccountManager::PROPERTY_PHONE => ['value' => $phone, 'scope' => $phoneScope],
+ AccountManager::PROPERTY_TWITTER => ['value' => $twitter, 'scope' => $twitterScope]
];
- $this->accountManager->updateUser($userId, $data);
+ $this->accountManager->updateUser($user, $data);
try {
- $this->saveUserSettings($userId, $data);
+ $this->saveUserSettings($user, $data);
return new DataResponse(
array(
'status' => 'success',
'data' => array(
- 'userId' => $userId,
+ 'userId' => $user->getUID(),
'avatarScope' => $avatarScope,
'displayname' => $displayname,
'displaynameScope' => $displaynameScope,
/**
* update account manager with new user data
*
- * @param string $userId
+ * @param IUser $user
* @param array $data
* @throws ForbiddenException
*/
- private function saveUserSettings($userId, $data) {
- $user = $this->userManager->get($userId);
+ private function saveUserSettings(IUser $user, $data) {
// keep the user back-end up-to-date with the latest display name and email
// address
}
}
- $this->accountManager->updateUser($userId, $data);
+ $this->accountManager->updateUser($user, $data);
}
/**
]);
}
- $userData = $this->accountManager->getUser($user->getUID());
- $userData['displayName']['value'] = $displayName;
+ $userData = $this->accountManager->getUser($user);
+ $userData[AccountManager::PROPERTY_DISPLAYNAME]['value'] = $displayName;
try {
- $this->saveUserSettings($username, $userData);
+ $this->saveUserSettings($user, $userData);
return new DataResponse([
'status' => 'success',
'data' => [
'phone',
'email',
'website',
+ 'twitter',
'address',
'avatar'
];
OC.Settings = OC.Settings || {};
OC.Settings.FederationSettingsView = FederationSettingsView;
-})(_, $, OC);
\ No newline at end of file
+})(_, $, OC);
$defaults = \OC::$server->getThemingDefaults();
$certificateManager = \OC::$server->getCertificateManager();
-$accountManager = new \OC\Accounts\AccountManager(\OC::$server->getDatabaseConnection());
+$accountManager = new \OC\Accounts\AccountManager(\OC::$server->getDatabaseConnection(), \OC::$server->getEventDispatcher());
$config = \OC::$server->getConfig();
$urlGenerator = \OC::$server->getURLGenerator();
$storageInfo=OC_Helper::getStorageInfo('/');
$user = OC::$server->getUserManager()->get(OC_User::getUser());
-$email = $user->getEMailAddress();
$userLang=$config->getUserValue( OC_User::getUser(), 'core', 'lang', \OC::$server->getL10NFactory()->findLanguage() );
$languageCodes = \OC::$server->getL10NFactory()->findAvailableLanguages();
} else {
$totalSpace = OC_Helper::humanFileSize($storageInfo['total']);
}
-$userData = $accountManager->getUser($user->getUID());
+
+$uid = $user->getUID();
+$userData = $accountManager->getUser($user);
$tmpl->assign('total_space', $totalSpace);
$tmpl->assign('usage_relative', $storageInfo['relative']);
$tmpl->assign('clients', $clients);
-$tmpl->assign('email', $email);
+$tmpl->assign('email', $userData[\OC\Accounts\AccountManager::PROPERTY_EMAIL]['value']);
$tmpl->assign('languages', $languages);
$tmpl->assign('commonlanguages', $commonLanguages);
$tmpl->assign('activelanguage', $userLang);
$tmpl->assign('passwordChangeSupported', OC_User::canUserChangePassword(OC_User::getUser()));
$tmpl->assign('displayNameChangeSupported', OC_User::canUserChangeDisplayName(OC_User::getUser()));
-$tmpl->assign('displayName', OC_User::getDisplayName());
-
-$tmpl->assign('phone', isset($userData['phone'][0]['value']) ? $userData['phone'][0]['value'] : null);
-$tmpl->assign('website', isset($userData['website'][0]['value']) ? $userData['website'][0]['value'] : null);
-$tmpl->assign('address', isset($userData['address'][0]['value']) ? $userData['address'][0]['value'] : null);
-
-$tmpl->assign('avatarScope', isset($userData['avatar']['scope']) ? $userData['avatar']['scope'] : 'contacts');
-$tmpl->assign('displayNameScope', isset($userData['displayName']['scope']) ? $userData['displayName']['scope'] : 'contacts');
-$tmpl->assign('phoneScope', isset($userData['phone'][0]['scope']) ? $userData['phone'][0]['scope'] : 'private');
-$tmpl->assign('emailScope', isset($userData['email'][0]['scope']) ? $userData['email'][0]['scope'] : 'private');
-$tmpl->assign('websiteScope', isset($userData['website'][0]['scope']) ? $userData['website'][0]['scope'] : 'private');
-$tmpl->assign('addressScope', isset($userData['address'][0]['scope']) ? $userData['address'][0]['scope'] : 'private');
+$tmpl->assign('displayName', $userData[\OC\Accounts\AccountManager::PROPERTY_DISPLAYNAME]['value']);
+
+$tmpl->assign('phone', $userData[\OC\Accounts\AccountManager::PROPERTY_PHONE]['value']);
+$tmpl->assign('website', $userData[\OC\Accounts\AccountManager::PROPERTY_WEBSITE]['value']);
+$tmpl->assign('twitter', $userData[\OC\Accounts\AccountManager::PROPERTY_TWITTER]['value']);
+$tmpl->assign('address', $userData[\OC\Accounts\AccountManager::PROPERTY_ADDRESS]['value']);
+
+$tmpl->assign('avatarScope', $userData[\OC\Accounts\AccountManager::PROPERTY_AVATAR]['scope']);
+$tmpl->assign('displayNameScope', $userData[\OC\Accounts\AccountManager::PROPERTY_DISPLAYNAME]['scope']);
+$tmpl->assign('phoneScope', $userData[\OC\Accounts\AccountManager::PROPERTY_PHONE]['scope']);
+$tmpl->assign('emailScope', $userData[\OC\Accounts\AccountManager::PROPERTY_EMAIL]['scope']);
+$tmpl->assign('websiteScope', $userData[\OC\Accounts\AccountManager::PROPERTY_WEBSITE]['scope']);
+$tmpl->assign('twitterScope', $userData[\OC\Accounts\AccountManager::PROPERTY_TWITTER]['scope']);
+$tmpl->assign('addressScope', $userData[\OC\Accounts\AccountManager::PROPERTY_ADDRESS]['scope']);
$tmpl->assign('enableAvatars', $config->getSystemValue('enable_avatars', true) === true);
$tmpl->assign('avatarChangeSupported', OC_User::canUserChangeAvatar(OC_User::getUser()));
<div class="personal-settings-setting-box">
<form id="phoneform" class="section">
<h2>
- <label for="phone"><?php p($l->t('Phone name')); ?></label>
+ <label for="phone"><?php p($l->t('Phone number')); ?></label>
<span class="icon-password"/>
</h2>
<input type="tel" id="phone" name="phone"
value="<?php p($_['phone']) ?>"
+ placeholder="<?php p($l->t('Your phone number')); ?>"
autocomplete="on" autocapitalize="off" autocorrect="off" />
<span class="icon-checkmark hidden"/>
<input type="hidden" id="phonescope" value="<?php p($_['phoneScope']) ?>">
<input type="hidden" id="websitescope" value="<?php p($_['websiteScope']) ?>">
</form>
</div>
+
+ <div class="personal-settings-setting-box">
+ <form id="twitterform" class="section">
+ <h2>
+ <label for="twitter"><?php p($l->t('Twitter')); ?></label>
+ <span class="icon-password"/>
+ </h2>
+ <input type="text" name="twitter" id="twitter" value="<?php p($_['twitter']); ?>"
+ placeholder="<?php p($l->t('Your Twitter handle')); ?>"
+ autocomplete="on" autocapitalize="off" autocorrect="off" />
+ <span class="icon-checkmark hidden"/>
+ <input type="hidden" id="twitterscope" value="<?php p($_['twitterScope']) ?>">
+ </form>
+ </div>
+
+
<div class="personal-settings-setting-box">
<form id="addressform" class="section">
<h2>
<span class="icon-password"/>
</h2>
<input type="text" id="address" name="address"
+ placeholder="<?php p($l->t('Your postal address')); ?>"
value="<?php p($_['address']) ?>"
autocomplete="on" autocapitalize="off" autocorrect="off" />
<span class="icon-checkmark hidden"/>
<h2><?php p($l->t('Website')); ?></h2>
<span><?php if(isset($_['website'][0])) { p($_['website']); } else { p($l->t('No website set')); }?></span>
</div>
+ <div id="twitterform" class="section">
+ <h2><?php p($l->t('Twitter')); ?></h2>
+ <span><?php if(isset($_['twitter'][0])) { p($_['twitter']); } else { p($l->t('No twitter handle set')); }?></span>
+ </div>
<div id="addressform" class="section">
<h2><?php p($l->t('Address')); ?></h2>
<span><?php if(isset($_['address'][0])) { p($_['address']); } else { p($l->t('No address set')); }?></span>