<?php
/**
 * DokuWiki Plugin DAVCard (Book Syntax Component)
 *
 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
 * @author  Andreas Böhler <dev@aboehler.at>
 */

// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();

if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');

class syntax_plugin_davcard_book extends DokuWiki_Syntax_Plugin {
    
    protected $hlp = null;
    
    // Load the helper plugin
    public function syntax_plugin_davcard_book() {  
        $this->hlp =& plugin_load('helper', 'davcard');     
    }
    
    
    /**
     * What kind of syntax are we?
     */
    function getType(){
        return 'substition';
    }

    /**
     * What about paragraphs?
     */
    function getPType(){
        return 'normal';
    }

    /**
     * Where to sort in?
     */
    function getSort(){
        return 165;
    }

    /**
     * Connect pattern to lexer
     */
    function connectTo($mode) {
        $this->Lexer->addSpecialPattern('\{\{davcardbook>[^}]*\}\}',$mode,'plugin_davcard_book');
    }

    /**
     * Handle the match
     */
    function handle($match, $state, $pos, Doku_Handler $handler){
        global $ID;
        $options = trim(substr($match,14,-2));
        $options = explode(',', $options);
        $data = array('name' => $ID,
                      'description' => $this->getLang('created_by_davcard'),
                      'id' => array(),
                      'filter' => array(),
                      );
        foreach($options as $option)
        {
            list($key, $val) = explode('=', $option);
            $key = strtolower(trim($key));
            $val = trim($val);
            switch($key)
            {
                case 'filter':
                    list($k, $v) = explode(':', strtolower($val), 2);
                    $data['filter'][$k] = $v;
                break;
                case 'id':
                    if(!in_array($val, $data['id']))
                        $data['id'][] = $val;
                break;
                default:
                    $data[$key] = $val;
            }
        }
        // Handle the default case when the user didn't enter a different ID
        if(empty($data['id']))
        {
            $data['id'] = array($ID);
        }
        // Only update the addressbook name/description if the ID matches the page ID.
        // Otherwise, the addressbook is included in another page and we don't want
        // to interfere with its data.
        if(in_array($ID, $data['id']))
        {
            if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER']))
                $username = $_SERVER['REMOTE_USER'];
            else
                $username = uniqid('davcard-');
            $this->hlp->setAddressbookNameForPage($data['name'], $data['description'], $ID, $username);
        }

        $meta = p_get_metadata($ID, 'plugin_davcard');
        if(is_null($meta))
            $meta = array();
        $meta['addressbooks'] = $data;
        // Add webdavclient information so that we can disable caching if need be
        foreach($data['id'] as $addrbkid)
        {
            if(strpos($addrbkid, 'webdav://') === 0)
            {
                $connectionId = str_replace('webdav://', '', $addrbkid);
                if(!is_array($meta['webdavclient']))
                    $meta['webdavclient'] = array();
                if(!in_array($addrbkid, $meta['webdavclient']))
                    $meta['webdavclient'][] = $connectionId;
            }
        }
        p_set_metadata($ID, array('plugin_davcard' => $meta));
        return $data;
    }
    
    /**
     * Create output
     */
    function render($format, Doku_Renderer $R, $data) 
    {
        global $ID;
        if($format !== 'xhtml')
            return false;
        
        $addressbooklist = array();
                
        $R->doc .= '<div class="davcardAddressbookAddNew"><a href="#" class="davcardAddressbookAddNew">'.$this->getLang('add_new').'</a></div>';     
        
        $R->doc .= '<div id="davcardAddressbookList" data-addressbookpage="'.$ID.'">';
        $R->doc .= '<table class="davcardAddressbookTable">';
        $R->doc .= '<tr><th>'.$this->getLang('name').'</th><th>'.$this->getLang('address').'</th><th>'.$this->getLang('phone').'</th><th>'.$this->getLang('email').'</th></tr>';
        foreach($data['id'] as $id)
        {
            $write = false;
            if(strpos($id, 'webdav://') === 0)
            {
                $wdc =& plugin_load('helper', 'webdavclient');
                if(is_null($wdc))
                {
                    echo $this->getLang('no_wdc');
                    continue;
                }
                $connectionId = str_replace('webdav://', '', $id);
                $settings = $wdc->getConnection($connectionId);
                if($settings === false)
                {
                    echo $this->getLang('settings_not_found');
                    continue;
                }
                if($settings['type'] !== 'contacts')
                {
                    echo $this->getLang('wrong_type');
                    continue;
                }
                $name = $settings['displayname'];
                $entries = $wdc->getAddressbookEntries($connectionId);
                $write = $settings['write'];
            }
            else
            {
                $acl = auth_quickaclcheck($id);
                if($acl > AUTH_READ)
                {
                    $write = true;
                }
                elseif($acl < AUTH_READ)
                {
                    continue;
                }
                else 
                {
                    $write = false;
                }
                $addressbookid = $this->hlp->getAddressbookIdForPage($id);
                $name = $this->hlp->getAddressBookSettings($addressbookid);
                $name = $name['displayname'];
                $entries = $this->hlp->getAddressbookEntries($addressbookid);
            }
            
            $addressbooklist[] = array('id' => $id, 'name' => $name, 'write' => $write);
            
            foreach($entries as $entry)
            {
                $contactdata = $this->hlp->parseVcard($entry['contactdata'], $entry['uri'], $write);
                if(!$this->contactFilterMatch($data['filter'], $contactdata))
                    continue;
                $R->doc .= '<tr><td><a href="#" class="plugin_davcard_edit_vcard" data-davcardid="'.$id.'" data-davcarduri="'.hsc($entry['uri']).'" data-write="'.($write ? 'true' : 'false').'">'.hsc($entry['formattedname']).'</a></td><td>';
                if(count($contactdata['addr']) > 0)
                {
                    $R->doc .= '<span class="adr">';
                    foreach($contactdata['addr'] as $dat)
                    {
                        if(isset($dat['type']))
                            $type = $dat['type'];
                        else
                            $type = 'other';
                        $R->doc .= '<span class="type">'.hsc($this->getLang('adr'.strtolower($type))).'</span>';
                        if($dat['address'][2] != '')
                        {
                            $R->doc .= '<span class="street-address">'.hsc($dat['address'][2]).'</span><br>';
                        }
                        if($dat['address'][5] != '')
                        {
                            $R->doc .= '<span class="postal-code">'.hsc($dat['address'][5]).' </span>';
                        }
                        if($dat['address'][3] != '')
                        {
                            $R->doc .= '<span class="locality">'.hsc($dat['address'][3]).'</span><br>';
                        }
        
                        if($dat['address'][6] != '')
                        {
                            $R->doc .= '<span class="country-name">'.hsc($dat['address'][6]).'</span>';
                        }
                    }
                    $R->doc .= '</span>';
                }
                $R->doc .= '</td><td>';
                if(count($contactdata['tel']) > 0)
                {
                    $R->doc .= '<span class="tel">';
                    foreach($contactdata['tel'] as $dat)
                    {
                        if(isset($dat['type']))
                            $type = $dat['type'];
                        else
                            $type = 'other';
                        $R->doc .= '<span class="type">'.hsc($this->getLang('tel'.strtolower($type))).' </span>';
                        $R->doc .= hsc($dat['number']).'<br>';
                    }
                    $R->doc .= '</span>';
                }
                $R->doc .= '</td><td>';
                if(count($contactdata['mail']) > 0)
                {
                    foreach($contactdata['mail'] as $dat)
                    {
                        $R->doc .= '<span class="email">'.hsc($dat['mail']).'</span><br>';
                    }
                }
                $R->doc .= '</td></tr>';
            }
        }
        $R->doc .= '</table>';
        $R->doc .= '<div id="davcardAddressbookList" class="davcardAddressbookList" style="display:none">';
        $R->doc .= '<select id="davcardAddressbookDropdown">';
        foreach($addressbooklist as $addrbk)
        {
            $R->doc .= '<option value="'.hsc($addrbk['id']).'" data-write="'.hsc($addrbk['write']).'">'.hsc($addrbk['name']).'</option>';
        }
        $R->doc .= '</select></div>';
        $R->doc .= '</div>';
        
    }

/**
 * Check if a contact matches a given filter pattern
 * 
 * @param array $filter The filter array
 * @param array $contactdata The contact's data to match
 * 
 * @return true on success, otherwise false
 */
    private function contactFilterMatch($filter, $contactdata)
    {
        if(empty($filter))
            return true;
        
        foreach($filter as $type => $params)
        {
            $params = '/'.$params.'/i';
            switch($type)
            {
                case 'name':
                    if(preg_match($params, $contactdata['formattedname']) !== 1)
                        return false;
                break;
                case 'mail':
                    $found = false;
                    foreach($contactdata['mail'] as $dat)
                    {
                        if(preg_match($params, $dat['mail']) === 1)
                            $found = true;
                    }
                    if(!$found)
                        return false;
                break;
                case 'address':
                    $found = false;
                    foreach($contactdata['addr'] as $dat)
                    {
                        foreach($dat['address'] as $da)
                        {
                            if(preg_match($params, $da) === 1)
                                $found = true;
                        }
                    }
                    if(!$found)
                        return false;
                break;
                case 'tel':
                    $found = false;
                    foreach($contactdata['tel'] as $dat)
                    {
                        if(preg_match($params, $dat['number']) === 1)
                            $found = true;
                    }
                    if(!$found)
                        return false;
                break;
            }
        }
        return true;
    }
   
}

// vim:ts=4:sw=4:et:enc=utf-8:
