416 lines
11 KiB
PHP
416 lines
11 KiB
PHP
<?php
|
|
/**
|
|
* Copyright 2009-2017 Horde LLC (http://www.horde.org/)
|
|
*
|
|
* See the enclosed file COPYING for license information (GPL). If you
|
|
* did not receive this file, see http://www.horde.org/licenses/gpl.
|
|
*
|
|
* @category Horde
|
|
* @copyright 2009-2017 Horde LLC
|
|
* @license http://www.horde.org/licenses/gpl GPL
|
|
* @package IMP
|
|
*/
|
|
|
|
/**
|
|
* Provides an interface to deal with display of flags/keywords/labels on
|
|
* messages.
|
|
*
|
|
* @author Michael Slusarz <slusarz@horde.org>
|
|
* @category Horde
|
|
* @copyright 2009-2017 Horde LLC
|
|
* @license http://www.horde.org/licenses/gpl GPL
|
|
* @package IMP
|
|
*/
|
|
class IMP_Flags implements ArrayAccess, Serializable
|
|
{
|
|
/**
|
|
* Has the object data changed?
|
|
*
|
|
* @var boolean
|
|
*/
|
|
public $changed = false;
|
|
|
|
/**
|
|
* Does the msglist_flags hook exist?
|
|
*
|
|
* @var boolean
|
|
*/
|
|
protected $_flaghook = true;
|
|
|
|
/**
|
|
* The list of internal flags.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_flags = array();
|
|
|
|
/**
|
|
* The list of user flags.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_userflags = array();
|
|
|
|
/**
|
|
* Constructor.
|
|
*/
|
|
public function __construct()
|
|
{
|
|
/* Build list of default flags. */
|
|
foreach (array('Imap', 'System') as $type) {
|
|
$di = new DirectoryIterator(IMP_BASE . '/lib/Flag/' . $type);
|
|
foreach ($di as $val) {
|
|
if ($val->isFile()) {
|
|
$cname = 'IMP_Flag_' . $type . '_' . $val->getBasename('.php');
|
|
if (class_exists($cname)) {
|
|
$ob = new $cname();
|
|
$this->_flags[$ob->id] = $ob;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($f_list = $GLOBALS['prefs']->getValue('msgflags')) {
|
|
$f_list = @unserialize($f_list);
|
|
if (is_array($f_list)) {
|
|
foreach ($f_list as $val) {
|
|
$this->_userflags[$val->id] = $val;
|
|
}
|
|
}
|
|
}
|
|
|
|
$this->changed = true;
|
|
}
|
|
|
|
/**
|
|
* Save the flag list to the prefs backend.
|
|
*/
|
|
protected function _save()
|
|
{
|
|
global $prefs;
|
|
|
|
if (!$prefs->isLocked('msgflags')) {
|
|
$prefs->setValue('msgflags', serialize($this->_userflags));
|
|
}
|
|
|
|
$this->changed = true;
|
|
}
|
|
|
|
/**
|
|
* Return the raw list of flags.
|
|
*
|
|
* @param array $opts Additional options:
|
|
* - imap: (boolean) If true, only return IMAP flags that can be set by
|
|
* the user.
|
|
* DEFAULT: false
|
|
* - mailbox: (string) A real (not virtual) IMAP mailbox. If set, will
|
|
* determine what flags are available in the mailbox.
|
|
* DEFAULT: '' (no mailbox check)
|
|
*
|
|
* @return array An array of IMP_Flag_Base elements.
|
|
*/
|
|
public function getList(array $opts = array())
|
|
{
|
|
if (!$GLOBALS['injector']->getInstance('IMP_Factory_Imap')->create()->access(IMP_Imap::ACCESS_FLAGS)) {
|
|
return array();
|
|
}
|
|
|
|
$ret = array_merge($this->_flags, $this->_userflags);
|
|
|
|
if (!empty($opts['imap'])) {
|
|
foreach ($ret as $key => $val) {
|
|
if (!($val instanceof IMP_Flag_Imap)) {
|
|
unset($ret[$key]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!isset($opts['mailbox']) ||
|
|
!strlen($opts['mailbox']) ||
|
|
IMP_Mailbox::get($opts['mailbox'])->search) {
|
|
return array_values($ret);
|
|
}
|
|
|
|
/* Alter the list of flags for a mailbox depending on the mailbox's
|
|
* PERMANENTFLAGS status. */
|
|
$permflags = IMP_Mailbox::get($opts['mailbox'])->permflags;
|
|
|
|
/* Limited flags allowed in mailbox. */
|
|
foreach ($ret as $key => $val) {
|
|
if (($val instanceof IMP_Flag_Imap) &&
|
|
!$permflags->allowed($val->imapflag)) {
|
|
unset($ret[$key]);
|
|
}
|
|
}
|
|
|
|
/* Get list of unknown flags. */
|
|
if ($GLOBALS['prefs']->getValue('show_all_flags')) {
|
|
/* Get list of IMAP flags. */
|
|
$imapflags = array();
|
|
foreach ($ret as $val) {
|
|
if ($val instanceof IMP_Flag_Imap) {
|
|
$imapflags[] = $val->imapflag;
|
|
}
|
|
}
|
|
|
|
foreach ($permflags as $val) {
|
|
if (!in_array($val, $imapflags)) {
|
|
$ret[] = new IMP_Flag_User($val);
|
|
}
|
|
}
|
|
}
|
|
|
|
return array_values($ret);
|
|
}
|
|
|
|
/**
|
|
* Add a user-defined IMAP flag.
|
|
*
|
|
* @param string $label The label to use for the new flag.
|
|
*
|
|
* @return string The IMAP flag name.
|
|
* @throws IMP_Exception
|
|
*/
|
|
public function addFlag($label)
|
|
{
|
|
if (strlen($label) === 0) {
|
|
throw new IMP_Exception(_("Flag name must not be empty."));
|
|
}
|
|
|
|
$ob = new IMP_Flag_User($label);
|
|
|
|
if (isset($this->_userflags[$ob->id])) {
|
|
throw new IMP_Exception(_("Flag name already exists."));
|
|
}
|
|
|
|
$this->_userflags[$ob->id] = $ob;
|
|
$this->_save();
|
|
|
|
return $ob->imapflag;
|
|
}
|
|
|
|
/**
|
|
* Updates flag properties.
|
|
*
|
|
* @param string $key The flag key.
|
|
* @param string $type The property to update. Either 'bgcolor' or
|
|
* 'label'.
|
|
* @param string $data The updated data.
|
|
*/
|
|
public function updateFlag($key, $type, $data)
|
|
{
|
|
if (isset($this->_userflags[$key])) {
|
|
$ob = clone $this->_userflags[$key];
|
|
} elseif (isset($this->_flags[$key])) {
|
|
$ob = clone $this->_flags[$key];
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
$ob->$type = $data;
|
|
|
|
if (isset($this->_flags[$key]) && ($this->_flags[$key] == $ob)) {
|
|
unset($this->_userflags[$key]);
|
|
} else {
|
|
$this->_userflags[$key] = $ob;
|
|
}
|
|
|
|
$this->_save();
|
|
}
|
|
|
|
/**
|
|
* Parse a list of flag information.
|
|
*
|
|
* @param array $opts Options:
|
|
* <pre>
|
|
* - flags: (array) IMAP flag info. A lowercase list of flags returned
|
|
* by the IMAP server.
|
|
* - headers: (Horde_Mime_Headers) Determines message information
|
|
* from a headers object.
|
|
* - runhook: (array) Run the msglist_flags hook? If yes, input is
|
|
* return from IMP_Mailbox_List#getMailboxArray().
|
|
* - personal: (mixed) Personal message info. Either a list of To
|
|
* addresses (Horde_Mail_Rfc822_List object) or the identity
|
|
* that matched the address list.
|
|
* </pre>
|
|
*
|
|
* @return array A list of IMP_Flag_Base objects.
|
|
*/
|
|
public function parse(array $opts = array())
|
|
{
|
|
global $injector;
|
|
|
|
$opts = array_merge(array(
|
|
'flags' => array(),
|
|
'headers' => null,
|
|
'personal' => null
|
|
), $opts);
|
|
|
|
if (!empty($opts['runhook']) && $this->_flaghook) {
|
|
try {
|
|
$opts['flags'] = array_merge(
|
|
$opts['flags'],
|
|
$injector->getInstance('Horde_Core_Hooks')->callHook(
|
|
'msglist_flags',
|
|
'imp',
|
|
array($opts['runhook'])
|
|
)
|
|
);
|
|
} catch (Horde_Exception_HookNotSet $e) {
|
|
$this->_flaghook = false;
|
|
}
|
|
}
|
|
|
|
$ret = array();
|
|
|
|
foreach (array_merge($this->_flags, $this->_userflags) as $val) {
|
|
if ($val instanceof IMP_Flag_System_Match_Address) {
|
|
if (!is_null($opts['personal']) &&
|
|
$val->match($opts['personal'])) {
|
|
$ret[] = $val;
|
|
}
|
|
} elseif (($val instanceof IMP_Flag_Imap) ||
|
|
($val instanceof IMP_Flag_System_Match_Flag)) {
|
|
if ($val->match($opts['flags'])) {
|
|
$ret[] = $val;
|
|
}
|
|
} elseif ($val instanceof IMP_Flag_System_Match_Header) {
|
|
if (!is_null($opts['headers']) &&
|
|
$val->match($opts['headers'])) {
|
|
$ret[] = $val;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* Process a flag ID formatted for use in form data.
|
|
*
|
|
* @param string $id The ID from form data.
|
|
*
|
|
* @return array Two element array:
|
|
* - flag: (string) The flag name.
|
|
* - set: (boolean) Whether the flag should be set or not.
|
|
*/
|
|
public function parseFormId($id)
|
|
{
|
|
return (strpos($id, '0\\') === 0)
|
|
? array('flag' => substr($id, 2), 'set' => false)
|
|
: array('flag' => $id, 'set' => true);
|
|
}
|
|
|
|
/**
|
|
* Returns a list of flags that have changed due to IMAP flag changes.
|
|
*
|
|
* @param array $flags The list of IMAP flags added/removed.
|
|
* @param boolean $add True if these flags were added, false if they were
|
|
* removed.
|
|
*
|
|
* @return array Array with two keys: 'add' and 'remove'. Each key
|
|
* contains a list of IMP_Flag_Base objects.
|
|
*/
|
|
public function changed($flags, $add)
|
|
{
|
|
$ret = array(
|
|
'add' => array(),
|
|
'remove' => array()
|
|
);
|
|
|
|
$obs = array();
|
|
foreach ($flags as $val) {
|
|
if ($tmp = $this[$val]) {
|
|
$obs[] = $tmp;
|
|
}
|
|
}
|
|
|
|
if ($add) {
|
|
$ret['add'] = $obs;
|
|
} else {
|
|
$ret['remove'] = $obs;
|
|
}
|
|
|
|
foreach (array_merge($this->_flags, $this->_userflags) as $val) {
|
|
$res = $val->changed($obs, $add);
|
|
|
|
if ($res === false) {
|
|
$ret['remove'][] = $val;
|
|
} elseif ($res === true) {
|
|
$ret['add'][] = $val;
|
|
}
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
|
|
/* ArrayAccess methods. */
|
|
|
|
/**
|
|
*/
|
|
public function offsetExists($offset)
|
|
{
|
|
return isset($this->_flags[$offset]) ||
|
|
isset($this->_userflags[$offset]);
|
|
}
|
|
|
|
/**
|
|
*/
|
|
public function offsetGet($offset)
|
|
{
|
|
if (isset($this->_flags[$offset])) {
|
|
return $this->_flags[$offset];
|
|
} elseif (isset($this->_userflags[$offset])) {
|
|
return $this->_userflags[$offset];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* @throws InvalidArgumentException
|
|
*/
|
|
public function offsetSet($offset, $value)
|
|
{
|
|
throw new InvalidArgumentException('Use addFlag()/updateFlag()');
|
|
}
|
|
|
|
/**
|
|
*/
|
|
public function offsetUnset($offset)
|
|
{
|
|
if (isset($this->_userflags[$offset])) {
|
|
unset($this->_userflags[$offset]);
|
|
$this->_save();
|
|
}
|
|
}
|
|
|
|
/* Serializable methods. */
|
|
|
|
/**
|
|
*/
|
|
public function serialize()
|
|
{
|
|
return $GLOBALS['injector']->getInstance('Horde_Pack')->pack(
|
|
array(
|
|
$this->_flags,
|
|
$this->_userflags
|
|
), array(
|
|
'compression' => false,
|
|
'phpob' => true
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
*/
|
|
public function unserialize($data)
|
|
{
|
|
list(
|
|
$this->_flags,
|
|
$this->_userflags
|
|
) = $GLOBALS['injector']->getInstance('Horde_Pack')->unpack($data);
|
|
}
|
|
|
|
}
|