1

メールの受信トレイを検索し、その機能の一部として特定のメールを保存するアプリを開発しています。何が起こるかというと、imap接続が確立され、UNSEENとして設定されているすべての電子メールが取得されます。各電子メールは事前定義された条件に対してチェックされ、条件が満たされた場合はDBに保存されます。これらの条件はユーザーが設定でき、次のようになります。

主題

  • 文字列が含まれています
  • 文字列が含まれていません

  • 文字列が含まれています
  • 文字列が含まれていません

から

  • 特定の住所

たとえば、条件を「連鎖」させることができます。

FILTER WHERE  
Subject CONTAINS "Order Confirmation"
AND
Email FROM "billyjones26@gmail.com" OR "billyjones26@googlemail.com"

これらの条件をフォーマットして保存する方法を考えるのに苦労しています。ユーザーがこれらの条件を作成できるGUIが必要です。

私の質問は、これらの条件をどのように保存する必要があるかということです。つまり、ある種のDBテーブル構造、または文字列形式に変換されて単一のテーブルに格納される場合があります。無制限のユーザー数には無制限の条件が必要であり、どのオペレーターがいるのかなどを知る必要があります。

それが十分な情報であることを願っています!

*マイケルのために編集*

条件を作成して保存することができます。今、私はそれらを取得して、電子メールを照合しようとしています。1つの条件でフィルターを作成しました:件名に「TEST」が含まれています。これに一致するのは1つの電子メールのみですが、どういうわけかすべての電子メールが一致した配列に追加されています。

メール/条件を取得している私のコントローラー:

public function check_email(){
    $filters = $this->filters_model->get_filters($owner_id=1);
    foreach($filters->result() as $filter){
        $emails = $this->gmail->get_emails($mailbox_id = $filter->mailbox_id, $limit = 10);

        $matched = array();
        $conditions = unserialize($filter->conditions);

        foreach($emails as $email){
            if($conditions->isMet($email) == TRUE){
                $matched[] = $email;
            }
        }

        echo count($matched);
        echo '<pre>'.$filter->title.'<br /.';
        print_r($conditions);
        echo '</pre><br />-----';
        exit;
    }
}

Keyvalueprerequisite.php

のvar_dumpはstripos($subject, $this->value) !== FALSE;1通の電子メールに対してTRUEのみを表示するため、これは正常に機能しているようです。

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 

class Keyvalueprerequisite {

    private $key;
    private $comparator;
    private $value;

    public function __construct($key, $comparator, $value){
        $this->key = $key;
        $this->comparator = $comparator;
        $this->value = $value;
    }


    public function isMet(&$context)
    {
        switch ($this->key) {

            case "subject":

                $subject = $context["subject"];
                if ($this->comparator === "in"){
                    return stripos($subject, $this->value) !== FALSE;
                } else if ($this->comparator === "!in") {
                    return stripos($subject, $this->value) === FALSE;
                }

                return FALSE;

                break;

            case "body":

                $body = $context["body"];

                if ($this->comparator === "in") {
                    return stripos($body, $this->value) !== FALSE;
                } else if ($this->comparator === "!in") {
                    return stripos($body, $this->value) === FALSE;
                }

                return FALSE;

                break;

            case "from_address":

                $from = $context["from"];

                if ($this->comparator === "=") {
                    return $this->value === $from;
                } else if ($this->comparator === "!=") {
                    return $this->value !== $from;
                } else{
                    return false;
                }

                break;

            default:
        }

        return FALSE;
    }

}

Prerequisistegroup.php

ここに何かが完全に書かれていない可能性があります。var_dump of$result = $result && $is_metは、10個の電子メールのそれぞれに対してtrueを返します。

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 

class Prerequisitegroup {

    private $type;
    private $prerequisites;

    public function __construct($type = 'AND'){
        $this->type = $type;
    }

    public function add(){
        foreach(func_get_args() as $prerequisite){
          $this->prerequisites[] = $prerequisite;
        }
    }

    public function isMet(&$context)
    {
        if (empty($this->prerequisites) === FALSE) {
            $result = TRUE;

            foreach ($this->prerequisites as $prerequisite) {
                $is_met = $prerequisite->isMet($context);
                if ($this->type === 'AND') {
                    $result = $result && $is_met;
                    if ($result === FALSE) {
                        return FALSE;
                    }
                } else {
                    $result = $result || $is_met;
                    if ($result === TRUE) {
                        return TRUE;
                    }
                }
            }
            return $result;
        }

        return TRUE;
    }


}

これらはチェックされている私の状態です:

string(3) "AND"
  ["prerequisites":"Prerequisitegroup":private]=>
  array(1) {
    [0]=>
    object(Prerequisitegroup)#23 (2) {
      ["type":"Prerequisitegroup":private]=>
      string(2) "OR"
      ["prerequisites":"Prerequisitegroup":private]=>
      array(1) {
        [0]=>
        object(Keyvalueprerequisite)#24 (3) {
          ["key":"Keyvalueprerequisite":private]=>
          string(7) "subject"
          ["comparator":"Keyvalueprerequisite":private]=>
          string(2) "in"
          ["value":"Keyvalueprerequisite":private]=>
          string(4) "TEST"
        }
      }
    }
  }
}
4

1 に答える 1

1

CMSの場合、条件(Prerequisites)を2つのクラスに抽象化することで同様の問題を解決しました:PrerequisiteとPrerequisiteGroup(前者のサブクラスであり、それらをシリアル化するか、より正確にはオブジェクトです。BLOBには1つしかないためです)。 MySQLで。

これの利点は、isMet()必要条件の深さや複雑さを気にすることなく、オブジェクトを逆シリアル化して関数を呼び出すことができることでした。もちろん、このオブジェクトに対してDBクエリを実行できないという欠点もありました。しかし、この特定のケースではそれは問題ではありませんでした。あなた自身の提案から、それはあなたにも問題ではないと思います。

Prerequisiteクラス(またはインターフェース)は、条件が真であるかどうかを通知する1つのメソッドを実装しisMet($context)ます。あなたの場合のコンテキストは、調べられる$emailになります。たとえば、メールから「billyjones26@gmail.com」と一致する場合。

とを簡略化してPrerequisiteGroup表します。条件をグループ化するデフォルトの方法は、ANDOR

条件を作成して保存する例を次に示します。

$c1 = new KeyValuePrerequisite("EmailFrom", "=", "billyjones26@gmail.com");
$c2 = new KeyValuePrerequisite("EmailFrom", "=", "billyjones26@googlemail.com");
$c3 = new KeyValuePrerequisite("Subject", "in", "Order Confirmation");

$from_condition = new PrerequisiteGroup('or');
$from_condition->add($c1, $c2);

$final_condition = new PrerequisiteGroup($c3, $from_condition); // defaults to and

$db->query("INSERT INTO conditions SET user_id = %i, conditions = %l", $user_id, serialize($final_condition));

使用例は次のとおりです。

// Fetch conditions

$email_conditions = $user->getEmailConditions()

// Connect to your inbox and fetch relevant emails

$matching_emails = array();
foreach ($emails as $email) {
    if ($email_conditions->isMet($email) {
        $matching_emails[] = $email;
    }
}

前提条件のインターフェース:

interface Prerequisite 
{
    /**
     * Must return TRUE or FALSE.
     */
    public function isMet(&$context);
}

KeyValuePrerequisiteの実装(私の実装では、これは実際には抽象クラスですが、目的のためにここですべてを実装できます。EmailPrerequisiteまたはEmailConditionと呼ぶことができます):

class KeyValuePrerequisite extends PrerequisiteGroup
{
    protected $key;
    protected $comparator;
    protected $value;

    public function __construct($key, $comparator, $value = NULL)
    {
        $this->key        = $key;
        $this->comparator = $comparator;
        $this->value      = $value;
    }

    public function isMet(&$context)
    {
        switch ($this->key) {

            case "Subject":

                $subject = $context["subject"];

                if ($this->comparator === "in") }
                    return stripos($subject, $this->value) !== FALSE;
                } else if ($this->comparator === "not int") {
                    return stripos($subject, $this->value) === FALSE;
                }

                return FALSE;

                break;

            case "EmailFrom":

                $from = $context["from"];

                return $this->value === $from;

                break;

            default:
        }

        return FALSE;
    }
}

PrerequisiteGroupの実装:

class PrerequisiteGroup implements Prerequisite
{
    private $type;
    private $prerequisites;

    public function __construct($type = 'AND')
    {
        $this->type = $type;
    }

    public function add(Prerequisite $prerequisite)
    {
        if ($prerequisite instanceof Prerequisite) {
            $this->prerequisites[] = $prerequisite;
        } else {
            throw new Exception('Unknown Prerequisite type ' . get_class($prerequisite));
        }
    }

    public function isMet(&$context)
    {
        if (empty($this->prerequisites) === FALSE) {
            $result = $this->type === 'AND';
            foreach ($this->prerequisites as $prerequisite) {
                $is_met = $prerequisite->isMet($context);
                if ($this->type === 'AND') {
                    $result = $result && $is_met;
                    if ($result === FALSE) {
                        return FALSE;
                    }
                } else {
                    $result = $result || $is_met;
                    if ($result === TRUE) {
                        return TRUE;
                    }
                }
            }
            return $result;
        }

        return TRUE;
    }
}

GUI

GUIに関しては、いくつかのアプローチ/パターンがあります。電子メール関連のアプリで最も一般的なのは、AND演算された式の行の数と、条件を追加するための[+]を使用することです。

Row 1: [select: subject] [select:contains] [input:"Order Confirmation"]

fromORを表現する必要があります。これは、行だけでは実行できません。ここで、前提条件グループまたは条件グループの概念が役立ちます。グループである新しい行を追加し、ユーザーがANDまたはORのどちらを使用するかを選択できるようにするだけです。

外側のグループはANDグループです。

したがって、GUI要素はコードに変換するのはかなり簡単です。その逆も同様です。特にKeyValuePrerequisiteimplを使用するとそうです。前提条件の。

これがあなたの問題を解決するためのいくつかのアイデアを助けるか、少なくとも刺激したことを願っています。

于 2012-08-27T14:40:07.380 に答える