Various fixes to multiple address books handling

This commit is contained in:
Thomas Tanghus 2011-12-09 15:10:51 +01:00
parent 830efdccac
commit b3661adf02
13 changed files with 146 additions and 37 deletions

View file

@ -12,7 +12,7 @@ if(!OC_USER::isLoggedIn()) {
die("<script type=\"text/javascript\">document.location = oc_webroot;</script>"); die("<script type=\"text/javascript\">document.location = oc_webroot;</script>");
} }
OC_JSON::checkAppEnabled('contacts'); OC_JSON::checkAppEnabled('contacts');
/* OC_Log::write('contacts','chooseaddressbook.php',OC_Log::DEBUG); */ OC_Log::write('contacts','chooseaddressbook.php',OC_Log::DEBUG);
$output = new OC_TEMPLATE("contacts", "part.chooseaddressbook"); $output = new OC_TEMPLATE("contacts", "part.chooseaddressbook");
$output -> printpage(); $output -> printpage();

View file

@ -17,10 +17,10 @@ OC_JSON::checkAppEnabled('contacts');
$userid = OC_User::getUser(); $userid = OC_User::getUser();
$bookid = OC_Contacts_Addressbook::add($userid, $_POST['name'], null); $bookid = OC_Contacts_Addressbook::add($userid, $_POST['name'], null);
OC_Contacts_Addressbook::setActive($bookid, 1); OC_Contacts_Addressbook::setActive($bookid, 1);
$book = OC_Contacts_Addressbook::find($bookid); $addressbook = OC_Contacts_Addressbook::find($bookid);
$tmpl = new OC_Template('contacts', 'part.chooseaddressbook.rowfields'); $tmpl = new OC_Template('contacts', 'part.chooseaddressbook.rowfields');
$tmpl->assign('addressbook', $book); $tmpl->assign('addressbook', $addressbook);
OC_JSON::success(array( OC_JSON::success(array(
'page' => $tmpl->fetchPage(), 'page' => $tmpl->fetchPage(),
'bookid' => $bookid, 'addressbook' => $addressbook,
)); ));

View file

@ -32,7 +32,7 @@ OC_JSON::checkAppEnabled('contacts');
$adr_types = OC_Contacts_VCard::getTypesOfProperty($l10n, 'ADR'); $adr_types = OC_Contacts_VCard::getTypesOfProperty($l10n, 'ADR');
$phone_types = OC_Contacts_VCard::getTypesOfProperty($l10n, 'TEL'); $phone_types = OC_Contacts_VCard::getTypesOfProperty($l10n, 'TEL');
$addressbooks = OC_Contacts_Addressbook::all(OC_USER::getUser()); $addressbooks = OC_Contacts_Addressbook::allAddressbooks(OC_USER::getUser());
$tmpl = new OC_Template('contacts','part.addcardform'); $tmpl = new OC_Template('contacts','part.addcardform');
$tmpl->assign('addressbooks',$addressbooks); $tmpl->assign('addressbooks',$addressbooks);
$tmpl->assign('adr_types',$adr_types); $tmpl->assign('adr_types',$adr_types);

View file

@ -19,7 +19,7 @@ OC_Contacts_Addressbook::edit($bookid, $_POST['name'], null);
OC_Contacts_Addressbook::setActive($bookid, $_POST['active']); OC_Contacts_Addressbook::setActive($bookid, $_POST['active']);
$addressbook = OC_Contacts_Addressbook::find($bookid); $addressbook = OC_Contacts_Addressbook::find($bookid);
$tmpl = new OC_Template('contacts', 'part.chooseaddressbook.rowfields'); $tmpl = new OC_Template('contacts', 'part.chooseaddressbook.rowfields');
$tmpl->assign('book', $book); $tmpl->assign('addressbook', $addressbook);
OC_JSON::success(array( OC_JSON::success(array(
'page' => $tmpl->fetchPage(), 'page' => $tmpl->fetchPage(),
'addressbook' => $addressbook, 'addressbook' => $addressbook,

View file

@ -21,7 +21,7 @@
*/ */
function contacts_namesort($a,$b){ function contacts_namesort($a,$b){
return strcmp($a['name'],$b['name']); return strcmp($a['fullname'],$b['fullname']);
} }
// Init owncloud // Init owncloud
@ -32,16 +32,17 @@ OC_Util::checkLoggedIn();
OC_Util::checkAppEnabled('contacts'); OC_Util::checkAppEnabled('contacts');
// Check if the user has an addressbook // Check if the user has an addressbook
$addressbooks = OC_Contacts_Addressbook::all(OC_User::getUser()); $openaddressbooks = OC_Contacts_Addressbook::activeAddressbookIds(OC_User::getUser());
if( count($addressbooks) == 0){ OC_Log::write('contacts','Got IDs'.implode(',', $openaddressbooks),OC_Log::DEBUG);
OC_Contacts_Addressbook::add(OC_User::getUser(),'default','Default Address Book'); // if( count($addressbooks) == 0){
$addressbooks = OC_Contacts_Addressbook::all(OC_User::getUser()); // OC_Contacts_Addressbook::add(OC_User::getUser(),'default','Default Address Book');
} // $addressbooks = OC_Contacts_Addressbook::all(OC_User::getUser());
$prefbooks = OC_Preferences::getValue(OC_User::getUser(),'contacts','openaddressbooks',null); // }
if(is_null($prefbooks)){ // $prefbooks = OC_Preferences::getValue(OC_User::getUser(),'contacts','openaddressbooks',null);
$prefbooks = $addressbooks[0]['id']; // if(is_null($prefbooks)){
OC_Preferences::setValue(OC_User::getUser(),'contacts','openaddressbooks',$prefbooks); // $prefbooks = $addressbooks[0]['id'];
} // OC_Preferences::setValue(OC_User::getUser(),'contacts','openaddressbooks',$prefbooks);
// }
// Load the files we need // Load the files we need
OC_App::setActiveNavigationEntry( 'contacts_index' ); OC_App::setActiveNavigationEntry( 'contacts_index' );
@ -52,16 +53,18 @@ $id = isset( $_GET['id'] ) ? $_GET['id'] : null;
// sort addressbooks (use contactsort) // sort addressbooks (use contactsort)
usort($addressbooks,'contacts_namesort'); usort($addressbooks,'contacts_namesort');
// Addressbooks to load // Addressbooks to load
$openaddressbooks = explode(';',$prefbooks); //$openaddressbooks = explode(';',$prefbooks);
$contacts = array(); $contacts = array();
foreach( $openaddressbooks as $addressbook ){ foreach( $openaddressbooks as $addressbook ){
$addressbookcontacts = OC_Contacts_VCard::all($addressbook); $addressbookcontacts = OC_Contacts_VCard::all($addressbook);
OC_Log::write('contacts','index.php. Getting contacts for: '.$addressbook,OC_Log::DEBUG);
foreach( $addressbookcontacts as $contact ){ foreach( $addressbookcontacts as $contact ){
if(is_null($contact['fullname'])){ if(is_null($contact['fullname'])){
continue; continue;
} }
$contacts[] = array( 'name' => $contact['fullname'], 'id' => $contact['id'] ); $contacts[] = $contact;
//$contacts[] = array( 'name' => $contact['fullname'], 'id' => $contact['id'] );
} }
} }
@ -75,10 +78,6 @@ if( !is_null($id) || count($contacts)){
$details = OC_Contacts_VCard::structureContact($vcard); $details = OC_Contacts_VCard::structureContact($vcard);
} }
$l10n = new OC_L10N('contacts');
$adr_types = OC_Contacts_VCard::getTypesOfProperty($l10n, 'ADR');
$phone_types = OC_Contacts_VCard::getTypesOfProperty($l10n, 'TEL');
// Include Style and Script // Include Style and Script
OC_Util::addScript('contacts','interface'); OC_Util::addScript('contacts','interface');
OC_Util::addStyle('contacts','styles'); OC_Util::addStyle('contacts','styles');
@ -86,6 +85,10 @@ OC_Util::addStyle('contacts','formtastic');
OC_Util::addScript('', 'jquery.multiselect'); OC_Util::addScript('', 'jquery.multiselect');
OC_Util::addStyle('', 'jquery.multiselect'); OC_Util::addStyle('', 'jquery.multiselect');
$l10n = new OC_L10N('contacts');
$adr_types = OC_Contacts_VCard::getTypesOfProperty($l10n, 'ADR');
$phone_types = OC_Contacts_VCard::getTypesOfProperty($l10n, 'TEL');
// Process the template // Process the template
$tmpl = new OC_Template( 'contacts', 'index', 'user' ); $tmpl = new OC_Template( 'contacts', 'index', 'user' );
$tmpl->assign('adr_types',$adr_types); $tmpl->assign('adr_types',$adr_types);

View file

@ -6,10 +6,15 @@ Contacts={
$('#carddav_url').show(); $('#carddav_url').show();
$('#carddav_url_close').show(); $('#carddav_url_close').show();
}, },
Contacts:{
update:function(){
alert('Contacts.update()');
}
},
Addressbooks:{ Addressbooks:{
overview:function(){ overview:function(){
/* alert('overview');*/
if($('#chooseaddressbook_dialog').dialog('isOpen') == true){ if($('#chooseaddressbook_dialog').dialog('isOpen') == true){
/*alert('Address books.moveToTop');*/
$('#chooseaddressbook_dialog').dialog('moveToTop'); $('#chooseaddressbook_dialog').dialog('moveToTop');
}else{ }else{
$('#dialog_holder').load(OC.filePath('contacts', 'ajax', 'chooseaddressbook.php'), function(){ $('#dialog_holder').load(OC.filePath('contacts', 'ajax', 'chooseaddressbook.php'), function(){
@ -71,6 +76,7 @@ Contacts={
var url = 'ajax/deletebook.php?id='+bookid; var url = 'ajax/deletebook.php?id='+bookid;
$('#calendar_holder').fullCalendar('removeEventSource', url);*/ $('#calendar_holder').fullCalendar('removeEventSource', url);*/
$('#chooseaddressbook_dialog').dialog('destroy').remove(); $('#chooseaddressbook_dialog').dialog('destroy').remove();
Contacts.UI.Contacts.update();
Contacts.UI.Addressbooks.overview(); Contacts.UI.Addressbooks.overview();
} else { } else {
alert('Error: ' + data.message); alert('Error: ' + data.message);

View file

@ -43,8 +43,9 @@ class OC_Contacts_Addressbook{
* @param string $uid * @param string $uid
* @return array * @return array
*/ */
public static function all($uid){ public static function allAddressbooks($uid){
$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_addressbooks WHERE userid = ?' ); OC_Log::write('contacts','allAddressbooks',OC_Log::DEBUG);
$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_addressbooks WHERE userid = ? ORDER BY displayname' );
$result = $stmt->execute(array($uid)); $result = $stmt->execute(array($uid));
$addressbooks = array(); $addressbooks = array();
@ -55,6 +56,24 @@ class OC_Contacts_Addressbook{
return $addressbooks; return $addressbooks;
} }
/**
* @brief Returns the list of active addressbooks for a specific user.
* @param string $uid
* @return array
*/
public static function activeAddressbooks($uid){
$active = implode(',', self::activeAddressbookIds());
$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_addressbooks WHERE id IN (?) AND userid = ? ORDER BY displayname' );
$result = $stmt->execute(array($active, $uid));
$addressbooks = array();
while( $row = $result->fetchRow()){
$addressbooks[] = $row;
}
return $addressbooks;
}
/** /**
* @brief Returns the list of addressbooks for a principal (DAV term of user) * @brief Returns the list of addressbooks for a principal (DAV term of user)
* @param string $principaluri * @param string $principaluri
@ -62,7 +81,7 @@ class OC_Contacts_Addressbook{
*/ */
public static function allWherePrincipalURIIs($principaluri){ public static function allWherePrincipalURIIs($principaluri){
$uid = self::extractUserID($principaluri); $uid = self::extractUserID($principaluri);
return self::all($uid); return self::allAddressbooks($uid);
} }
/** /**
@ -85,7 +104,7 @@ class OC_Contacts_Addressbook{
* @return insertid * @return insertid
*/ */
public static function add($userid,$name,$description){ public static function add($userid,$name,$description){
$all = self::all($userid); $all = self::allAddressbooks($userid);
$uris = array(); $uris = array();
foreach($all as $i){ foreach($all as $i){
$uris[] = $i['uri']; $uris[] = $i['uri'];
@ -140,6 +159,28 @@ class OC_Contacts_Addressbook{
return true; return true;
} }
/**
* @brief Get active addressbooks for a user.
* @param integer $uid User id. If null current user will be used.
* @return array
*/
public static function activeAddressbookIds($uid){
if(is_null($uid)){
$uid = OC_User::getUser();
}
$prefbooks = OC_Preferences::getValue($uid,'contacts','openaddressbooks',null);
if(is_null($prefbooks)){
$addressbooks = OC_Contacts_Addressbook::allAddressbooks($uid);
if(count($addressbooks) == 0){
OC_Contacts_Addressbook::add($uid,'default','Default Address Book');
$addressbooks = OC_Contacts_Addressbook::allAddressbooks($uid);
}
$prefbooks = $addressbooks[0]['id'];
OC_Preferences::setValue($uid,'contacts','openaddressbooks',$prefbooks);
}
return explode(';',$prefbooks);
}
/** /**
* @brief Activates an addressbook * @brief Activates an addressbook
* @param integer $id * @param integer $id
@ -149,17 +190,50 @@ class OC_Contacts_Addressbook{
public static function setActive($id,$active){ public static function setActive($id,$active){
// Need these ones for checking uri // Need these ones for checking uri
//$addressbook = self::find($id); //$addressbook = self::find($id);
OC_Log::write('contacts','setActive('.$id.'): '.$active,OC_Log::DEBUG);
if(is_null($id)){ if(is_null($id)){
$id = 0; $id = 0;
} }
/**
* For now I have active state redundant both in preferences and in the address book
* table as I can't get the OC_Contacts_Addressbook::isActive() call to work when
* iterating over several results.
*/
$stmt = OC_DB::prepare( 'UPDATE *PREFIX*contacts_addressbooks SET active=?, ctag=ctag+1 WHERE id=?' ); $stmt = OC_DB::prepare( 'UPDATE *PREFIX*contacts_addressbooks SET active=?, ctag=ctag+1 WHERE id=?' );
$result = $stmt->execute(array($active,$id)); $result = $stmt->execute(array($active,$id));
$openaddressbooks = self::activeAddressbookIds();
if($active) {
if(!in_array($id, $openaddressbooks)) {
// TODO: Test this instead
//$openaddressbooks[] = $id;
array_push($openaddressbooks, $id);
}
} else {
if(in_array($id, $openaddressbooks)) {
array_pop($openaddressbooks, $id);
$openaddressbooks = array_diff( $openaddressbooks, array($id) );
}
}
sort($openaddressbooks, SORT_NUMERIC);
OC_Log::write('contacts','setActive('.$id.'):all '.implode(';', $openaddressbooks),OC_Log::DEBUG);
OC_Preferences::setValue(OC_User::getUser(),'contacts','openaddressbooks',implode(';', $openaddressbooks));
return true; return true;
} }
/**
* @brief Checks if an addressbook is active.
* @param integer $id ID of the address book.
* @return boolean
*/
public static function isActive($id){
OC_Log::write('contacts','isActive('.$id.')',OC_Log::DEBUG);
OC_Log::write('contacts','isActive('.$id.'): '.in_array($id, self::activeAddressbookIds()),OC_Log::DEBUG);
return in_array($id, self::activeAddressbookIds());
}
/** /**
* @brief removes an address book * @brief removes an address book
* @param integer $id * @param integer $id

View file

@ -30,7 +30,7 @@ class OC_Contacts_Hooks{
* @return array * @return array
*/ */
public function deleteUser($parameters) { public function deleteUser($parameters) {
$addressbooks = OC_Contacts_Addressbook::all($parameters['uid']); $addressbooks = OC_Contacts_Addressbook::allAddressbooks($parameters['uid']);
foreach($addressbooks as $addressbook) { foreach($addressbooks as $addressbook) {
OC_Contacts_Addressbook::delete($addressbook['id']); OC_Contacts_Addressbook::delete($addressbook['id']);

View file

@ -47,15 +47,35 @@ class OC_Contacts_VCard{
* ['carddata'] * ['carddata']
*/ */
public static function all($id){ public static function all($id){
OC_Log::write('contacts','OC_Contacts_VCard::all ids: '.$id,OC_Log::DEBUG);
// if(is_array($id)) {
// OC_Log::write('contacts','OC_Contacts_VCard::all Array?: '.$id,OC_Log::DEBUG);
// OC_Log::write('contacts','count: '.implode(',', $id),OC_Log::DEBUG);
// $ids = implode(',', $id);
// $prep = '?'.str_repeat ( ',?' , count($id)-1 );
// //$repeat = str_repeat ( ',?' , count($id)-1 );
// //OC_Log::write('contacts','OC_Contacts_VCard::all: repeat: '.$repeat,OC_Log::DEBUG);
// OC_Log::write('contacts','OC_Contacts_VCard::all: from: '.$ids,OC_Log::DEBUG);
// OC_Log::write('contacts','OC_Contacts_VCard::all: PREP: SELECT * FROM contacts_cards WHERE addressbookid IN ('.$prep.')',OC_Log::DEBUG);
// OC_Log::write('contacts','OC_Contacts_VCard::all: SQL: SELECT * FROM contacts_cards WHERE addressbookid IN ('.$prep.')',OC_Log::DEBUG);
// $stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_cards WHERE addressbookid IN ('.'?,?,?'.') ORDER BY fullname' );
// } else {
// $ids = $id;
// $stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_cards WHERE addressbookid = ? ORDER BY fullname' );
// }
$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_cards WHERE addressbookid = ?' ); $stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_cards WHERE addressbookid = ?' );
$result = $stmt->execute(array($id)); $result = $stmt->execute(array($id));
OC_Log::write('contacts','OC_Contacts_VCard::all: result->numRows(): '.$result->numRows(),OC_Log::DEBUG);
$addressbooks = array(); $cards = array();
while( $row = $result->fetchRow()){ while( $row = $result->fetchRow()){
$addressbooks[] = $row; $cards[] = $row;
//OC_Log::write('contacts','OC_Contacts_VCard::all: fullname: '.$row['fullname'],OC_Log::DEBUG);
} }
OC_Log::write('contacts','OC_Contacts_VCard::all: count($cards): '.count($cards),OC_Log::DEBUG);
return $addressbooks; return $cards;
} }
/** /**

View file

@ -8,7 +8,7 @@
</form> </form>
</div> </div>
<div id="leftcontent" class="leftcontent"> <div id="leftcontent" class="leftcontent">
<ul> <ul id="contacts">
<?php echo $this->inc("part.contacts"); ?> <?php echo $this->inc("part.contacts"); ?>
</ul> </ul>
</div> </div>

View file

@ -1,11 +1,15 @@
<div id="chooseaddressbook_dialog" title="<?php echo $l->t("Choose active Address Books"); ?>"> <div id="chooseaddressbook_dialog" title="<?php echo $l->t("Choose active Address Books"); ?>">
<table width="100%" style="border: 0;"> <table width="100%" style="border: 0;">
<?php <?php
$option_addressbooks = OC_Contacts_Addressbook::all(OC_User::getUser()); OC_Log::write('contacts','part.chooseaddressbook.php',OC_Log::DEBUG);
$option_addressbooks = OC_Contacts_Addressbook::allAddressbooks(OC_User::getUser());
for($i = 0; $i < count($option_addressbooks); $i++){ for($i = 0; $i < count($option_addressbooks); $i++){
OC_Log::write('contacts','part.chooseaddressbook.php: '.$option_addressbooks[$i]['id'],OC_Log::DEBUG);
echo "<tr>"; echo "<tr>";
$tmpl = new OC_Template('contacts', 'part.chooseaddressbook.rowfields'); $tmpl = new OC_Template('contacts', 'part.chooseaddressbook.rowfields');
$tmpl->assign('addressbook', $option_addressbooks[$i]); $tmpl->assign('addressbook', $option_addressbooks[$i]);
$tmpl->assign('active', OC_Contacts_Addressbook::isActive($option_addressbooks[$i]['id']));
$tmpl->printpage(); $tmpl->printpage();
echo "</tr>"; echo "</tr>";
} }

View file

@ -1,4 +1,6 @@
<?php <?php
echo "<td width=\"20px\"><input id=\"active_" . $_['addressbook']["id"] . "\" type=\"checkbox\" onClick=\"Contacts.UI.Addressbooks.activation(this, " . $_['addressbook']["id"] . ")\"" . ($_['addressbook']["active"] ? ' checked="checked"' : '') . "></td>"; OC_Log::write('contacts','part.chooseaddressbook.rowfields.php',OC_Log::DEBUG);
echo "<td><label for=\"active_" . $_['addressbook']["id"] . "\">" . $_['addressbook']["displayname"] . "</label></td>";
echo "<td width=\"20px\"><input id=\"active_" . $_['addressbook']["id"] . "\" type=\"checkbox\" onClick=\"Contacts.UI.Addressbooks.activation(this, " . $_['addressbook']["id"] . ")\"" . (OC_Contacts_Addressbook::isActive($_['addressbook']["id"]) ? ' checked="checked"' : '') . "></td>";
echo "<td>Active: ".$_['active'].",ID: " . $_['addressbook']["id"] . " - <label for=\"active_" . $_['addressbook']["id"] . "\">" . $_['addressbook']["displayname"] . "</label></td>";
echo "<td width=\"20px\"><a href=\"#\" onclick=\"Contacts.UI.showCardDAVUrl('" . OC_User::getUser() . "', '" . $_['addressbook']["uri"] . "');\" title=\"" . $l->t("CardDav Link") . "\" class=\"action\"><img class=\"svg action\" src=\"../../core/img/actions/public.svg\"></a></td><td width=\"20px\"><a href=\"export.php?bookid=" . $_['addressbook']["id"] . "\" title=\"" . $l->t("Download") . "\" class=\"action\"><img class=\"svg action\" src=\"../../core/img/actions/download.svg\"></a></td><td width=\"20px\"><a href=\"#\" title=\"" . $l->t("Edit") . "\" class=\"action\" onclick=\"Contacts.UI.Addressbooks.editAddressbook(this, " . $_['addressbook']["id"] . ");\"><img class=\"svg action\" src=\"../../core/img/actions/rename.svg\"></a></td><td width=\"20px\"><a href=\"#\" onclick=\"Contacts.UI.Addressbooks.deleteAddressbook('" . $_['addressbook']["id"] . "');\" title=\"" . $l->t("Delete") . "\" class=\"action\"><img class=\"svg action\" src=\"../../core/img/actions/delete.svg\"></a></td>"; echo "<td width=\"20px\"><a href=\"#\" onclick=\"Contacts.UI.showCardDAVUrl('" . OC_User::getUser() . "', '" . $_['addressbook']["uri"] . "');\" title=\"" . $l->t("CardDav Link") . "\" class=\"action\"><img class=\"svg action\" src=\"../../core/img/actions/public.svg\"></a></td><td width=\"20px\"><a href=\"export.php?bookid=" . $_['addressbook']["id"] . "\" title=\"" . $l->t("Download") . "\" class=\"action\"><img class=\"svg action\" src=\"../../core/img/actions/download.svg\"></a></td><td width=\"20px\"><a href=\"#\" title=\"" . $l->t("Edit") . "\" class=\"action\" onclick=\"Contacts.UI.Addressbooks.editAddressbook(this, " . $_['addressbook']["id"] . ");\"><img class=\"svg action\" src=\"../../core/img/actions/rename.svg\"></a></td><td width=\"20px\"><a href=\"#\" onclick=\"Contacts.UI.Addressbooks.deleteAddressbook('" . $_['addressbook']["id"] . "');\" title=\"" . $l->t("Delete") . "\" class=\"action\"><img class=\"svg action\" src=\"../../core/img/actions/delete.svg\"></a></td>";

View file

@ -1,3 +1,3 @@
<?php foreach( $_['contacts'] as $contact ): ?> <?php foreach( $_['contacts'] as $contact ): ?>
<li data-id="<?php echo $contact['id']; ?>"><a href="index.php?id=<?php echo $contact['id']; ?>"><?php echo $contact['name']; ?></a> </li> <li data-id="<?php echo $contact['id']; ?>"><?php echo $contact['addressbookid']; ?> - <a href="index.php?id=<?php echo $contact['id']; ?>"><?php echo $contact['fullname']; ?></a> </li>
<?php endforeach; ?> <?php endforeach; ?>