public function diff($base, $new, $mode = self::DIFF_ALL, array $field_ids = array())
    {
        if (!empty($field_ids)) {
            $field_ids = array_flip($field_ids);
            $base = array_intersect_key($base, $field_ids);
            $new = array_intersect_key($new, $field_ids);
        }
        $res = array(
            self::ADD => array(),
            self::DEL => array(),
            self::UPDATE => array()
        );
        if ($mode & self::DIFF_ADD) {
            $res[self::ADD] = array_diff_key($new, $base);
        }
        if ($mode & self::DIFF_DEL) {
            $res[self::DEL] = array_diff_key($base, $new);
        }
        if ($mode & self::DIFF_UPDATE) {
            // Update array will have common fields with different data.
            $common = array_intersect_key($new, $base);
            foreach ($common as $key => $newData) {
                $new_data = array_diff_assoc($newData, $base[$key]);
                if (!empty($new_data)) {
                    $res[self::UPDATE][$key][self::BASE] = $base[$key];
                    $res[self::UPDATE][$key][self::MODIFIED] = $new_data;
                }
            }
        }

        return $res;
    }