protected  function deepCopy($patches)
    {
        $patchesCopy = array();
        foreach ($patches as $patch) {
            $patchCopy = clone $patch;
            $patchesCopy[] = $patchCopy;
        }
        return $patchesCopy;
    }

protected function deepCopy ( $ patches ) { $ patchesCopy = array ( ) ; foreach ( $ patches as $ patch ) { $ patchCopy = clone $ patch ; $ patchesCopy [ ] = $ patchCopy ; } return $ patchesCopy ; }

Given an array of patches, return another array that is identical.

@param PatchObject[] $patches Array of PatchObjects.

@return PatchObject[] Array of PatchObjects.

Given an array of patches return another array that is identical .


protected function bitapScore($errors, $matchLoc, $patternLen, $searchLoc)
    {
        $accuracy = $errors / $patternLen;
        $proximity = abs($searchLoc - $matchLoc);
        if (!$this->getDistance()) {
            // Dodge divide by zero error.
            return $proximity ? 1.0 : $accuracy;
        }
        return $accuracy + ($proximity/$this->getDistance());
    }

protected
function
bitapScore
(
$
errors
,
$
matchLoc
,
$
patternLen
,
$
searchLoc
)
{
$
accuracy
=
$
errors
/
$
patternLen
;
$
proximity
=
abs
(
$
searchLoc
$
matchLoc
)
;
if
(
!
$
this
->
getDistance
(
)
)
{
// Dodge divide by zero error.
return
$
proximity
1.0
:
$
accuracy
;
}
return
$
accuracy
+
(
$
proximity
/
$
this
->
getDistance
(
)
)
;
}

Compute and return the score for a match with e errors and x location.
Accesses loc and pattern through being a closure.

@param int    $errors            Number of errors in match.
@param int    $matchLoc          Location of match.
@param int    $patternLen        Length of pattern to search.
@param int    $searchLoc         The location to search around.
TODO refactor param usage.

@return float Overall score for match (0.0 = good, 1.0 = bad).

Compute and return the score for a match with e errors and x location . Accesses loc and pattern through being a closure .


public function alphabet($pattern)
    {
        $s = array();
        foreach (preg_split("//u", $pattern, -1, PREG_SPLIT_NO_EMPTY) as $char) {
            $s[$char] = 0;
        }
        for ($i = 0; $i < mb_strlen($pattern); $i++) {
            $s[mb_substr($pattern, $i, 1)] |= 1 << (mb_strlen($pattern) - $i - 1);
        }
        return $s;
    }

public function alphabet ( $ pattern ) { $ s = array ( ) ; foreach ( preg_split ( "//u" , $ pattern , - 1 , PREG_SPLIT_NO_EMPTY ) as $ char ) { $ s [ $ char ] = 0 ; } for ( $ i = 0 ; $ i < mb_strlen ( $ pattern ) ; $ i ++ ) { $ s [ mb_substr ( $ pattern , $ i , 1 ) ] |= 1 << ( mb_strlen ( $ pattern ) - $ i - 1 ) ; } return $ s ; }

Initialise the alphabet for the Bitap algorithm.

@param string $pattern The text to encode.

@return array Hash of character locations.

Initialise the alphabet for the Bitap algorithm .


public function prettyHtml()
    {
        $diffs = $this->getChanges();

        $html = '';
        foreach ($diffs as $change) {
            $op = $change[0];
            $data = $change[1];
            $text = str_replace(array(
                '&', '<', '>', "\n",
            ), array(
                '&', '<', '>', '¶
',
            ), $data);

            if ($op == self::INSERT) {
                $html .= '' . $text . '';
            } elseif ($op == self::DELETE) {
                $html .= '' . $text . '';
            } else {
                $html .= '' . $text . '';
            }
        }

        return $html;
    }

public
function
prettyHtml
(
)
{
$
diffs
=
$
this
->
getChanges
(
)
;
$
html
=
''
;
foreach
(
$
diffs
as
$
change
)
{
$
op
=
$
change
[
0
]
;
$
data
=
$
change
[
1
]
;
$
text
=
str_replace
(
array
(
'&'
,
'<'
,
'>'
,
"\n"
,
)
,
array
(
'&'
,
'<'
,
'>'
,
'¶
'
,
)
,
$
data
)
;
if
(
$
op
==
self
::
INSERT
)
{
$
html
.=
''
.
$
text
.
''
;
}
elseif
(
$
op
==
self
::
DELETE
)
{
$
html
.=
''
.
$
text
.
''
;
}
else
{
$
html
.=
''
.
$
text
.
''
;
}
}
return
$
html
;
}

Convert a diff array into a pretty HTML report.

@return string HTML representation.

Convert a diff array into a pretty HTML report .


public function toDelta() {
        $diffs = $this->getChanges();

        $text = array();
        foreach ($diffs as $change) {
            $op = $change[0];
            $data = $change[1];

            if ($op == self::INSERT) {
                $text[] = '+'. Utils::escapeString($data);
            } elseif ($op == self::DELETE) {
                $text[] = '-' . mb_strlen($data);
            } else {
                $text[] = '=' . mb_strlen($data);
            }
        }

        return implode("\t", $text);
    }

public function toDelta ( ) { $ diffs = $ this -> getChanges ( ) ; $ text = array ( ) ; foreach ( $ diffs as $ change ) { $ op = $ change [ 0 ] ; $ data = $ change [ 1 ] ; if ( $ op == self :: INSERT ) { $ text [ ] = '+' . Utils :: escapeString ( $ data ) ; } elseif ( $ op == self :: DELETE ) { $ text [ ] = '-' . mb_strlen ( $ data ) ; } else { $ text [ ] = '=' . mb_strlen ( $ data ) ; } } return implode ( "\t" , $ text ) ; }

Crush the diff into an encoded string which describes the operations
required to transform text1 into text2.
E.g. =3\t-2\t+ing  -> Keep 3 chars, delete 2 chars, insert 'ing'.
Operations are tab-separated.  Inserted text is escaped using %xx notation.

@return string Delta text.

Crush the diff into an encoded string which describes the operations required to transform text1 into text2 . E . g . = 3 \ t - 2 \ t + ing - > Keep 3 chars delete 2 chars insert ing . Operations are tab - separated . Inserted text is escaped using %xx notation .


public function fromDelta($text1, $delta)
    {
        $diffs = array();
        // Cursor in text1
        $pointer = 0;
        $tokens = explode("\t", $delta);
        foreach ($tokens as $token) {
            if ($token == '') {
                // Blank tokens are ok (from a trailing \t).
                continue;
            }
            // Each token begins with a one character parameter which specifies the
            // operation of this token (delete, insert, equality).
            $op = mb_substr($token, 0, 1);
            $param = mb_substr($token, 1);
            switch ($op) {
                case '+':
                    $diffs[] = array(
                        self::INSERT,
                        Utils::unescapeString($param),
                    );
                    break;
                case '-':
                case '=':
                    if (!is_numeric($param)) {
                        throw new \InvalidArgumentException('Invalid number in delta: ' . $param);
                    } elseif ($param < 0) {
                        throw new \InvalidArgumentException('Negative number in delta: ' . $param);
                    } else {
                        $n = (int) $param;
                    }
                    $text = mb_substr($text1, $pointer, $n);
                    $pointer += $n;
                    $diffs[] = array(
                        $op == '=' ? self::EQUAL : self::DELETE,
                        $text,
                    );
                    break;
                default:
                    // Anything else is an error.
                    throw new \InvalidArgumentException('Invalid diff operation in delta: ' . $op);
            }
        }
        if ($pointer != mb_strlen($text1)) {
            throw new \InvalidArgumentException('Delta length (' . $pointer . ') does not equal source text length (' . mb_strlen($text1) . ').');
        }
        $this->setChanges($diffs);

        return $this;
    }

Given the original text1, and an encoded string which describes the
operations required to transform text1 into text2, compute the full diff.

@param string $text1 Source string for the diff.
@param string $delta Delta text.

@throws \InvalidArgumentException If invalid input. TODO create exception class
@return $this.

Given the original text1 and an encoded string which describes the operations required to transform text1 into text2 compute the full diff .


public function levenshtein()
    {
        $diffs = $this->getChanges();

        $levenshtein = 0;
        $insertions = 0;
        $deletions = 0;

        foreach ($diffs as $change) {
            $op = $change[0];
            $text = $change[1];

            switch ($op) {
                case self::INSERT:
                    $insertions += mb_strlen($text);
                    break;
                case self::DELETE:
                    $deletions += mb_strlen($text);
                    break;
                case self::EQUAL:
                    // A deletion and an insertion is one substitution.
                    $levenshtein += max($insertions, $deletions);
                    $insertions = 0;
                    $deletions = 0;
                    break;
            }
        }
        $levenshtein += max($insertions, $deletions);

        return $levenshtein;
    }

Compute the Levenshtein distance; the number of inserted, deleted or substituted characters.

@return int Number of changes.

Compute the Levenshtein distance ; the number of inserted deleted or substituted characters .


protected function compute($text1, $text2, $checklines, $deadline)
    {
        if ($text1 == '') {
            // Just add some text (speedup).
            return array(
                array(self::INSERT, $text2),
            );
        }

        if ($text2 == '') {
            // Just delete some text (speedup).
            return array(
                array(self::DELETE, $text1),
            );
        }

        if (mb_strlen($text1) < mb_strlen($text2)) {
            $shortText = $text1;
            $longText = $text2;
        } else {
            $shortText = $text2;
            $longText = $text1;
        }

        $i = mb_strpos($longText, $shortText);
        if ($i !== false) {
            // Shorter text is inside the longer text (speedup).
            $diffs = array(
                array(self::INSERT, mb_substr($longText, 0, $i)),
                array(self::EQUAL, $shortText),
                array(self::INSERT, mb_substr($longText, $i + mb_strlen($shortText))),
            );
            // Swap insertions for deletions if diff is reversed.
            if (mb_strlen($text2) < mb_strlen($text1)) {
                $diffs[0][0] = self::DELETE;
                $diffs[2][0] = self::DELETE;
            }
            return $diffs;
        }

        if (mb_strlen($shortText) == 1) {
            // Single character string.
            // After the previous speedup, the character can't be an equality.
            $diffs = array(
                array(self::DELETE, $text1),
                array(self::INSERT, $text2),
            );
            return $diffs;
        }

        // Don't risk returning a non-optimal diff if we have unlimited time.
        if ($this->getTimeout() > 0) {
            // Check to see if the problem can be split in two.
            $hm = $this->getToolkit()->halfMatch($text1, $text2);
            if ($hm) {
                // A half-match was found, sort out the return data.
                list($text1_a, $text1_b, $text2_a, $text2_b, $mid_common) = $hm;
                // Send both pairs off for separate processing.
                $diffA = new Diff();
                $diffA->main($text1_a, $text2_a, $checklines, $deadline);
                $diffB = new Diff();
                $diffB->main($text1_b, $text2_b, $checklines, $deadline);
                // Merge the results.
                $diffs = array_merge(
                    $diffA->getChanges(),
                    array(
                        array(self::EQUAL, $mid_common),
                    ),
                    $diffB->getChanges()
                );
                return $diffs;
            }
        }

        if ($checklines
          && mb_strlen($text1) > Diff::LINEMODE_THRESOLD
          && mb_strlen($text2) > Diff::LINEMODE_THRESOLD) {
            return $this->lineMode($text1, $text2, $deadline);
        }

        return $this->bisect($text1, $text2, $deadline);
    }

Find the differences between two texts.  Assumes that the texts do not
have any common prefix or suffix.

@param string $text1         Old string to be diffed.
@param string $text2         New string to be diffed.
@param bool   $checklines    Speedup flag.  If false, then don't run a line-level diff
first to identify the changed areas.
If true, then run a faster, slightly less optimal diff.
@param int    $deadline      Time when the diff should be complete by.

@return array Array of changes.

Find the differences between two texts . Assumes that the texts do not have any common prefix or suffix .


protected function lineMode($text1, $text2, $deadline)
    {
        // Scan the text on a line-by-line basis first.
        list($text1, $text2, $lineArray) = $this->getToolkit()->linesToChars($text1, $text2);

        $diff = new Diff();
        $diff->main($text1, $text2, false, $deadline);
        $diffs = $diff->getChanges();

        // Convert the diff back to original text.
        $this->getToolkit()->charsToLines($diffs, $lineArray);
        $diff->setChanges($diffs);

        // Eliminate freak matches (e.g. blank lines)
        $diff->cleanupSemantic();
        $diffs = $diff->getChanges();

        // Rediff any replacement blocks, this time character-by-character.
        // Add a dummy entry at the end.
        array_push($diffs, array(self::EQUAL, ''));
        $pointer = 0;
        $countDelete = 0;
        $countInsert = 0;
        $textDelete = '';
        $textInsert = '';

        while ($pointer < count($diffs)) {
            switch ($diffs[$pointer][0]) {
                case self::DELETE:
                    $countDelete++;
                    $textDelete .= $diffs[$pointer][1];
                    break;
                case self::INSERT:
                $countInsert++;
                    $textInsert .= $diffs[$pointer][1];
                    break;
                case self::EQUAL:
                    // Upon reaching an equality, check for prior redundancies.
                    if ($countDelete > 0 && $countInsert > 0) {
                        // Delete the offending records and add the merged ones.
                        $subDiff = new Diff();
                        $subDiff->main($textDelete, $textInsert, false, $deadline);
                        array_splice($diffs, $pointer - $countDelete - $countInsert, $countDelete + $countInsert, $subDiff->getChanges());
                        $pointer = $pointer - $countDelete - $countInsert + count($subDiff->getChanges());
                    }
                    $countDelete = 0;
                    $countInsert = 0;
                    $textDelete = '';
                    $textInsert = '';
                    break;
            }
            $pointer++;
        }

        // Remove the dummy entry at the end.
        array_pop($diffs);

        return $diffs;
    }

Do a quick line-level diff on both strings, then rediff the parts for greater accuracy.
This speedup can produce non-minimal diffs.

@param string $text1    Old string to be diffed.
@param string $text2    New string to be diffed.
@param int    $deadline Time when the diff should be complete by.

@return array Array of changes.

Do a quick line - level diff on both strings then rediff the parts for greater accuracy . This speedup can produce non - minimal diffs .


protected function bisectSplit($text1, $text2, $x, $y, $deadline)
    {
        $text1A = mb_substr($text1, 0, $x);
        $text2A = mb_substr($text2, 0, $y);
        $text1B = mb_substr($text1, $x);
        $text2B = mb_substr($text2, $y);

        // Compute both diffs serially.
        $diffA = new Diff();
        $diffA->main($text1A, $text2A, false, $deadline);
        $diffB = new Diff();
        $diffB->main($text1B, $text2B, false, $deadline);

        return array_merge($diffA->getChanges(), $diffB->getChanges());
    }

protected
function
bisectSplit
(
$
text1
,
$
text2
,
$
x
,
$
y
,
$
deadline
)
{
$
text1A
=
mb_substr
(
$
text1
,
0
,
$
x
)
;
$
text2A
=
mb_substr
(
$
text2
,
0
,
$
y
)
;
$
text1B
=
mb_substr
(
$
text1
,
$
x
)
;
$
text2B
=
mb_substr
(
$
text2
,
$
y
)
;
// Compute both diffs serially.
$
diffA
=
new
Diff
(
)
;
$
diffA
->
main
(
$
text1A
,
$
text2A
,
false
,
$
deadline
)
;
$
diffB
=
new
Diff
(
)
;
$
diffB
->
main
(
$
text1B
,
$
text2B
,
false
,
$
deadline
)
;
return
array_merge
(
$
diffA
->
getChanges
(
)
,
$
diffB
->
getChanges
(
)
)
;
}

Given the location of the 'middle snake', split the diff in two parts and recurse.

@param string $text1    Old string to be diffed.
@param string $text2    New string to be diffed.
@param int    $x        Index of split point in text1.
@param int    $y        Index of split point in text2.
@param int    $deadline Time at which to bail if not yet complete.

@return array Array of diff arrays.

Given the location of the middle snake split the diff in two parts and recurse .


public function commonPrefix($text1, $text2)
    {
        // Quick check for common null cases.
        if ($text1 == '' || $text2 == '' || mb_substr($text1, 0, 1) != mb_substr($text2, 0, 1)) {
            return 0;
        }
        // Binary search.
        // Performance analysis: http://neil.fraser.name/news/2007/10/09/
        $pointermin = 0;
        $pointermax = min(mb_strlen($text1), mb_strlen($text2));
        $pointermid = $pointermax;
        $pointerstart = 0;
        while ($pointermin < $pointermid) {
            if (mb_substr($text1, $pointerstart, $pointermid - $pointerstart) == mb_substr($text2, $pointerstart,
                    $pointermid - $pointerstart)
            ) {
                $pointermin = $pointermid;
                $pointerstart = $pointermin;
            } else {
                $pointermax = $pointermid;
            }
            $pointermid = (int)(($pointermax - $pointermin) / 2) + $pointermin;
        }

        return $pointermid;
    }

Determine the common prefix of two strings.

@param string $text1 First string.
@param string $text2 Second string.

@return int The number of characters common to the start of each string.

Determine the common prefix of two strings .


public function commonSuffix($text1, $text2)
    {
        // Quick check for common null cases.
        if ($text1 == '' || $text2 == '' || mb_substr($text1, -1, 1) != mb_substr($text2, -1, 1)) {
            return 0;
        }
        // Binary search.
        // Performance analysis: http://neil.fraser.name/news/2007/10/09/
        $pointermin = 0;
        $pointermax = min(mb_strlen($text1), mb_strlen($text2));
        $pointermid = $pointermax;
        $pointerend = 0;
        while ($pointermin < $pointermid) {
            if (mb_substr($text1, -$pointermid, $pointermid - $pointerend) == mb_substr($text2, -$pointermid,
                    $pointermid - $pointerend)
            ) {
                $pointermin = $pointermid;
                $pointerend = $pointermin;
            } else {
                $pointermax = $pointermid;
            }
            $pointermid = (int)(($pointermax - $pointermin) / 2) + $pointermin;
        }

        return $pointermid;
    }

Determine the common suffix of two strings.

@param string $text1 First string.
@param string $text2 Second string.

@return int The number of characters common to the end of each string.

Determine the common suffix of two strings .


public function commontOverlap($text1, $text2)
    {
        // Cache the text lengths to prevent multiple calls.
        $text1_length = mb_strlen($text1);
        $text2_length = mb_strlen($text2);

        // Eliminate the null case.
        if (!$text1_length || !$text2_length) {
            return 0;
        }

        // Truncate the longer string.
        if ($text1_length > $text2_length) {
            $text1 = mb_substr($text1, -$text2_length);
        } elseif ($text1_length < $text2_length) {
            $text2 = mb_substr($text2, 0, $text1_length);
        }
        $text_length = min($text1_length, $text2_length);

        // Quick check for the worst case.
        if ($text1 == $text2) {
            return $text_length;
        }

        // Start by looking for a single character match
        // and increase length until no match is found.
        // Performance analysis: http://neil.fraser.name/news/2010/11/04/
        $best = 0;
        $length = 1;
        while (true) {
            $pattern = mb_substr($text1, -$length);
            $found = mb_strpos($text2, $pattern);
            if ($found === false) {
                break;
            }
            $length += $found;
            if ($found == 0 || mb_substr($text1, -$length) == mb_substr($text2, 0, $length)) {
                $best = $length;
                $length += 1;
            }
        }

        return $best;
    }

Determine if the suffix of one string is the prefix of another.

@param string $text1 First string.
@param string $text2 Second string.

@return int The number of characters common to the end of the first string and the start of the second string.

Determine if the suffix of one string is the prefix of another .


public function halfMatch($text1, $text2)
    {
        if (mb_strlen($text1) > mb_strlen($text2)) {
            $longtext = $text1;
            $shorttext = $text2;
        } else {
            $shorttext = $text1;
            $longtext = $text2;
        }

        if (mb_strlen($longtext) < 4 || mb_strlen($shorttext) * 2 < mb_strlen(mb_strlen($longtext))) {
            // Pointless
            return null;
        }

        // First check if the second quarter is the seed for a half-match.
        $hm1 = $this->halfMatchI($longtext, $shorttext, (int)((mb_strlen($longtext) + 3) / 4));
        // Check again based on the third quarter.
        $hm2 = $this->halfMatchI($longtext, $shorttext, (int)((mb_strlen($longtext) + 1) / 2));

        if (empty($hm1) && empty($hm2)) {
            return null;
        } elseif (empty($hm2)) {
            $hm = $hm1;
        } elseif (empty($hm1)) {
            $hm = $hm2;
        } else {
            // Both matched.  Select the longest.
            if (mb_strlen($hm1[4] > $hm2[4])) {
                $hm = $hm1;
            } else {
                $hm = $hm2;
            }
        }

        // A half-match was found, sort out the return data.
        if (mb_strlen($text1) > mb_strlen($text2)) {
            return array($hm[0], $hm[1], $hm[2], $hm[3], $hm[4]);
        } else {
            return array($hm[2], $hm[3], $hm[0], $hm[1], $hm[4]);
        }
    }

Do the two texts share a substring which is at least half the length of the longer text?
This speedup can produce non-minimal diffs.

@param string $text1 First string.
@param string $text2 Second string.

@return null|array Five element array, containing the prefix of text1, the suffix of text1,
the prefix of text2, the suffix of text2 and the common middle.  Or null if there was no match.

Do the two texts share a substring which is at least half the length of the longer text? This speedup can produce non - minimal diffs .


protected function halfMatchI($longtext, $shorttext, $i)
    {
        $seed = mb_substr($longtext, $i, (int)(mb_strlen($longtext) / 4));
        $best_common = $best_longtext_a = $best_longtext_b = $best_shorttext_a = $best_shorttext_b = '';

        $j = mb_strpos($shorttext, $seed);
        while ($j !== false) {
            $prefixLegth = $this->commonPrefix(mb_substr($longtext, $i), mb_substr($shorttext, $j));
            $suffixLegth = $this->commonSuffix(mb_substr($longtext, 0, $i), mb_substr($shorttext, 0, $j));
            if (mb_strlen($best_common) < $suffixLegth + $prefixLegth) {
                $best_common = mb_substr($shorttext, $j - $suffixLegth, $suffixLegth) . mb_substr($shorttext, $j,
                        $prefixLegth);
                $best_longtext_a = mb_substr($longtext, 0, $i - $suffixLegth);
                $best_longtext_b = mb_substr($longtext, $i + $prefixLegth);
                $best_shorttext_a = mb_substr($shorttext, 0, $j - $suffixLegth);
                $best_shorttext_b = mb_substr($shorttext, $j + $prefixLegth);
            }
            $j = mb_strpos($shorttext, $seed, $j + 1);
        }

        if (mb_strlen($best_common) * 2 >= mb_strlen($longtext)) {
            return array($best_longtext_a, $best_longtext_b, $best_shorttext_a, $best_shorttext_b, $best_common);
        } else {
            return null;
        }
    }

protected function halfMatchI ( $ longtext , $ shorttext , $ i ) { $ seed = mb_substr ( $ longtext , $ i , ( int ) ( mb_strlen ( $ longtext ) / 4 ) ) ; $ best_common = $ best_longtext_a = $ best_longtext_b = $ best_shorttext_a = $ best_shorttext_b = '' ; $ j = mb_strpos ( $ shorttext , $ seed ) ; while ( $ j !== false ) { $ prefixLegth = $ this -> commonPrefix ( mb_substr ( $ longtext , $ i ) , mb_substr ( $ shorttext , $ j ) ) ; $ suffixLegth = $ this -> commonSuffix ( mb_substr ( $ longtext , 0 , $ i ) , mb_substr ( $ shorttext , 0 , $ j ) ) ; if ( mb_strlen ( $ best_common ) < $ suffixLegth + $ prefixLegth ) { $ best_common = mb_substr ( $ shorttext , $ j - $ suffixLegth , $ suffixLegth ) . mb_substr ( $ shorttext , $ j , $ prefixLegth ) ; $ best_longtext_a = mb_substr ( $ longtext , 0 , $ i - $ suffixLegth ) ; $ best_longtext_b = mb_substr ( $ longtext , $ i + $ prefixLegth ) ; $ best_shorttext_a = mb_substr ( $ shorttext , 0 , $ j - $ suffixLegth ) ; $ best_shorttext_b = mb_substr ( $ shorttext , $ j + $ prefixLegth ) ; } $ j = mb_strpos ( $ shorttext , $ seed , $ j + 1 ) ; } if ( mb_strlen ( $ best_common ) * 2 >= mb_strlen ( $ longtext ) ) { return array ( $ best_longtext_a , $ best_longtext_b , $ best_shorttext_a , $ best_shorttext_b , $ best_common ) ; } else { return null ; } }

Does a substring of shorttext exist within longtext such that the substring
is at least half the length of longtext?

@param string $longtext  Longer string.
@param string $shorttext Shorter string.
@param int    $i         Start index of quarter length substring within longtext.

@return null|array Five element array, containing the prefix of longtext, the suffix of longtext,
the prefix of shorttext, the suffix of shorttext and the common middle.  Or null if there was no match.


public function linesToChars($text1, $text2)
    {
        // e.g. $lineArray[4] == "Hello\n"
        $lineArray = array();
        // e.g. $lineHash["Hello\n"] == 4
        $lineHash = array();

        // "\x00" is a valid character, but various debuggers don't like it.
        // So we'll insert a junk entry to avoid generating a null character.
        $lineArray[] = '';

        $chars1 = $this->linesToCharsMunge($text1, $lineArray, $lineHash);
        $chars2 = $this->linesToCharsMunge($text2, $lineArray, $lineHash);

        return array($chars1, $chars2, $lineArray);
    }

Split two texts into an array of strings.  Reduce the texts to a string of hashes where each
Unicode character represents one line.

@param string $text1 First string.
@param string $text2 Second string.

@return array Three element array, containing the encoded text1, the encoded text2 and the array
of unique strings.  The zeroth element of the array of unique strings is intentionally blank.

Split two texts into an array of strings . Reduce the texts to a string of hashes where each Unicode character represents one line .


protected function getRecipients($notifiable, Notification $notification)
    {
        $to = $notifiable->routeNotificationFor('smscru', $notification);

        if ($to === null || $to === false || $to === '') {
            return [];
        }

        return \is_array($to) ? $to : [$to];
    }

protected function getRecipients ( $ notifiable , Notification $ notification ) { $ to = $ notifiable -> routeNotificationFor ( 'smscru' , $ notification ) ; if ( $ to === null || $ to === false || $ to === '' ) { return [ ] ; } return \ is_array ( $ to ) ? $ to : [ $ to ] ; }

Gets a list of phones from the given notifiable.

@param  mixed  $notifiable
@param  Notification  $notification

@return string[]

Gets a list of phones from the given notifiable .


public function version()
    {
        $app = $this->app;
        $tab = explode('Laravel Components ', $app->version());

        return intval(empty($tab[1]) ? $app::VERSION : $tab[1]);
    }

public
function
version
(
)
{
$
app
=
$
this
->
app
;
$
tab
=
explode
(
'Laravel Components '
,
$
app
->
version
(
)
)
;
return
intval
(
empty
(
$
tab
[
1
]
)
$
app
::
VERSION
:
$
tab
[
1
]
)
;
}

Get the major Laravel version number.

@return int


public function registerPugCompiler($subExtension = '')
    {
        // Add resolver
        $this->getEngineResolver()->register('pug' . $subExtension, function () use ($subExtension) {
            return new CompilerEngine($this->app['Bkwld\LaravelPug\Pug' . ucfirst(ltrim($subExtension, '.')) . 'Compiler']);
        });

        // Add extensions
        $this->app['view']->addExtension('pug' . $subExtension, 'pug' . $subExtension);
        $this->app['view']->addExtension('pug' . $subExtension . '.php', 'pug' . $subExtension);
        $this->app['view']->addExtension('jade' . $subExtension, 'pug' . $subExtension);
        $this->app['view']->addExtension('jade' . $subExtension . '.php', 'pug' . $subExtension);
    }

public
function
registerPugCompiler
(
$
subExtension
=
''
)
{
// Add resolver
$
this
->
getEngineResolver
(
)
->
register
(
'pug'
.
$
subExtension
,
function
(
)
use
(
$
subExtension
)
{
return
new
CompilerEngine
(
$
this
->
app
[
'Bkwld\LaravelPug\Pug'
.
ucfirst
(
ltrim
(
$
subExtension
,
'.'
)
)
.
'Compiler'
]
)
;
}
)
;
// Add extensions
$
this
->
app
[
'view'
]
->
addExtension
(
'pug'
.
$
subExtension
,
'pug'
.
$
subExtension
)
;
$
this
->
app
[
'view'
]
->
addExtension
(
'pug'
.
$
subExtension
.
'.php'
,
'pug'
.
$
subExtension
)
;
$
this
->
app
[
'view'
]
->
addExtension
(
'jade'
.
$
subExtension
,
'pug'
.
$
subExtension
)
;
$
this
->
app
[
'view'
]
->
addExtension
(
'jade'
.
$
subExtension
.
'.php'
,
'pug'
.
$
subExtension
)
;
}

Register the regular Pug compiler.

@return void


public function getConfig()
    {
        $key = $this->version() >= 5 ? 'laravel-pug' : 'laravel-pug::config';

        return array_merge(array(
            'allow_composite_extensions' => true,
        ), $this->app->make('config')->get($key));
    }

public function getConfig ( ) { $ key = $ this -> version ( ) >= 5 ? 'laravel-pug' : 'laravel-pug::config' ; return array_merge ( array ( 'allow_composite_extensions' => true , ) , $ this -> app -> make ( 'config' ) -> get ( $ key ) ) ; }

Get the configuration, which is keyed differently in L5 vs l4.

@return array

Get the configuration which is keyed differently in L5 vs l4 .


public function construct(array $pugTarget, Filesystem $files, array $config, $defaultCachePath = null)
    {
        $this->pugTarget = $pugTarget;
        $cachePath = null;

        foreach (array('cache_dir', 'cache', 'defaultCache') as $name) {
            if (isset($config[$name])) {
                $cachePath = $config[$name];

                break;
            }
        }

        if (!$cachePath) {
            $cachePath = $defaultCachePath ?: $this->getCachePath();
        }

        parent::__construct($files, $cachePath);
    }

public function construct ( array $ pugTarget , Filesystem $ files , array $ config , $ defaultCachePath = null ) { $ this -> pugTarget = $ pugTarget ; $ cachePath = null ; foreach ( array ( 'cache_dir' , 'cache' , 'defaultCache' ) as $ name ) { if ( isset ( $ config [ $ name ] ) ) { $ cachePath = $ config [ $ name ] ; break ; } } if ( ! $ cachePath ) { $ cachePath = $ defaultCachePath ? : $ this -> getCachePath ( ) ; } parent :: __construct ( $ files , $ cachePath ) ; }

Common pug compiler constructor.

@param array      $pugTarget
@param Filesystem $files
@param array      $config


public function getPug()
    {
        if (!$this->pug) {
            $this->pug = $this->pugTarget[0][$this->pugTarget[1]];
        }

        return $this->pug;
    }

public function getPug ( ) { if ( ! $ this -> pug ) { $ this -> pug = $ this -> pugTarget [ 0 ] [ $ this -> pugTarget [ 1 ] ] ; } return $ this -> pug ; }

Lazy load Pug and return the instance.

@return Pug


public function getCachePath()
    {
        if ($this->cachePath) {
            return $this->cachePath;
        }

        $cachePath = $this->getOption('cache');

        return is_string($cachePath) ? $cachePath : $this->getOption('defaultCache');
    }

public function getCachePath ( ) { if ( $ this -> cachePath ) { return $ this -> cachePath ; } $ cachePath = $ this -> getOption ( 'cache' ) ; return is_string ( $ cachePath ) ? $ cachePath : $ this -> getOption ( 'defaultCache' ) ; }

Returns cache path.

@return string $cachePath


public function getOption($name, $default = null)
    {
        $pug = $this->getPug();

        try {
            if (method_exists($pug, 'hasOption') && !$pug->hasOption($name)) {
                throw new \InvalidArgumentException('invalid option');
            }

            return $pug->getOption($name);
        } catch (\InvalidArgumentException $exception) {
            return $default;
        }
    }

public
function
getOption
(
$
name
,
$
default
=
)
{
$
pug
=
$
this
->
getPug
(
)
;
try
{
if
(
method_exists
(
$
pug
,
'hasOption'
)
&&
!
$
pug
->
hasOption
(
$
name
)
)
{
throw
new
\
InvalidArgumentException
(
'invalid option'
)
;
}
return
$
pug
->
getOption
(
$
name
)
;
}
catch
(
\
InvalidArgumentException
$
exception
)
{
return
$
default
;
}
}

Get an option from pug engine or default value.

@param string $name
@param null   $default

@return mixed|null

Get an option from pug engine or default value .


public function isExpired($path)
    {
        if (!$this->cachePath || parent::isExpired($path)) {
            return true;
        }

        return is_subclass_of('\Pug\Pug', '\Phug\Renderer') && $this->hasExpiredImport($path);
    }

public function isExpired ( $ path ) { if ( ! $ this -> cachePath || parent :: isExpired ( $ path ) ) { return true ; } return is_subclass_of ( '\Pug\Pug' , '\Phug\Renderer' ) && $ this -> hasExpiredImport ( $ path ) ; }

Determine if the view at the given path is expired.

@param string $path

@return bool

Determine if the view at the given path is expired .


public function extractPath($path)
    {
        if ($path && method_exists($this, 'setPath')) {
            $this->setPath($path);
        }

        if (!$path && method_exists($this, 'getPath')) {
            $path = $this->getPath();
        }

        if (!$path) {
            throw new InvalidArgumentException('Missing path argument.');
        }

        return $path;
    }

public
function
extractPath
(
$
path
)
{
if
(
$
path
&&
method_exists
(
$
this
,
'setPath'
)
)
{
$
this
->
setPath
(
$
path
)
;
}
if
(
!
$
path
&&
method_exists
(
$
this
,
'getPath'
)
)
{
$
path
=
$
this
->
getPath
(
)
;
}
if
(
!
$
path
)
{
throw
new
InvalidArgumentException
(
'Missing path argument.'
)
;
}
return
$
path
;
}

Return path and set it or get it from the instance.

@param string $path

@throws \InvalidArgumentException

@return string

Return path and set it or get it from the instance .


public function getClient()
    {
        if (!$this->client instanceof Client) {
            $this->client = new Client(
                $this->config->get('amocrm.domain'),
                $this->config->get('amocrm.login'),
                $this->config->get('amocrm.hash')
            );
        }

        return $this->client;
    }

public function getClient ( ) { if ( ! $ this -> client instanceof Client ) { $ this -> client = new Client ( $ this -> config -> get ( 'amocrm.domain' ) , $ this -> config -> get ( 'amocrm.login' ) , $ this -> config -> get ( 'amocrm.hash' ) ) ; } return $ this -> client ; }

Get the AmoCRM client instance.

@return \AmoCRM\Client


public function getB2BFamily()
    {
        $client = $this->getClient();

        return new B2BFamily($client,
            $this->config->get('amocrm.b2bfamily.appkey'),
            $this->config->get('amocrm.b2bfamily.secret'),
            $this->config->get('amocrm.b2bfamily.email'),
            $this->config->get('amocrm.b2bfamily.password')
        );
    }

public function getB2BFamily ( ) { $ client = $ this -> getClient ( ) ; return new B2BFamily ( $ client , $ this -> config -> get ( 'amocrm.b2bfamily.appkey' ) , $ this -> config -> get ( 'amocrm.b2bfamily.secret' ) , $ this -> config -> get ( 'amocrm.b2bfamily.email' ) , $ this -> config -> get ( 'amocrm.b2bfamily.password' ) ) ; }

Get the AmoCRM B2BFamily helper instance.

@return \AmoCRM\Helpers\B2BFamily

Get the AmoCRM B2BFamily helper instance .


private function hashPrint($input)
    {
        // Get the stronger hashing algorithm available to minimize collision risks
        $algorithms = hash_algos();
        $algorithm = $algorithms[0];
        $number = 0;
        foreach ($algorithms as $hashAlgorithm) {
            $lettersLength = substr($hashAlgorithm, 0, 2) === 'md'
                ? 2
                : (substr($hashAlgorithm, 0, 3) === 'sha'
                    ? 3
                    : 0
                );
            if ($lettersLength) {
                $hashNumber = substr($hashAlgorithm, $lettersLength);
                if ($hashNumber > $number) {
                    $number = $hashNumber;
                    $algorithm = $hashAlgorithm;
                }

                continue;
            }
        }

        return rtrim(strtr(base64_encode(hash($algorithm, $input, true)), '+/', '-_'), '=');
    }

Return a hashed print from input file or content.

@param string $input

@return string

Return a hashed print from input file or content .


public function resolve($file)
    {
        return $this->locator->locate(
            $file,
            $this->paths,
            isset($this->options['extensions'])
                ? $this->options['extensions']
                : ['', '.pug', '.jade']
        );
    }

public function resolve ( $ file ) { return $ this -> locator -> locate ( $ file , $ this -> paths , isset ( $ this -> options [ 'extensions' ] ) ? $ this -> options [ 'extensions' ] : [ '' , '.pug' , '.jade' ] ) ; }

Resolve a template file path.

@param string $file

@return bool|null|string


public function displayFile($__pug_file, array $__pug_parameters = [])
    {
        if ($this->isExpired($__pug_file, $__pug_cache_file)) {
            if (isset($this->options['render'])) {
                call_user_func($this->options['render'], $__pug_file, $__pug_parameters, $this->options);

                return;
            }
            if (isset($this->options['renderer'])) {
                $this->options['renderer']->displayFile($__pug_file, $__pug_parameters);

                return;
            }
            if (isset($this->options['renderer_class_name'])) {
                $className = $this->options['renderer_class_name'];
                $renderer = new $className($this->options);
                $renderer->displayFile($__pug_file, $__pug_parameters);

                return;
            }
            $facade = isset($this->options['facade'])
                ? $this->options['facade']
                : static::FACADE;
            if (is_callable([$facade, 'displayFile'])) {
                $facade::displayFile($__pug_file, $__pug_parameters, $this->options);

                return;
            }

            throw new \RuntimeException(
                'No valid render method, renderer engine, renderer class or facade provided.'
            );
        }

        if (isset($this->options['shared_variables'])) {
            $__pug_parameters = array_merge($this->options['shared_variables'], $__pug_parameters);
        }
        if (isset($this->options['globals'])) {
            $__pug_parameters = array_merge($this->options['globals'], $__pug_parameters);
        }
        if (isset($this->options['self']) && $this->options['self']) {
            $self = $this->options['self'] === true ? 'self' : strval($this->options['self']);
            $__pug_parameters = [$self => $__pug_parameters];
        }

        extract($__pug_parameters);
        include $__pug_cache_file;
    }

Display a template.

@param string $__pug_file
@param array  $__pug_parameters


public static function getExtensionsOptions(array $extensions, array $options = [])
    {
        $methods = static::getExtensionsGetters();
        foreach ($extensions as $extensionClassName) {
            if (is_a($extensionClassName, ModuleInterface::class, true)) {
                if (!isset($options['modules'])) {
                    $options['modules'] = [];
                }
                $options['modules'][] = $extensionClassName;

                continue;
            }

            static::extractExtensionOptions($options, $extensionClassName, $methods);
        }

        return $options;
    }

public static function getExtensionsOptions ( array $ extensions , array $ options = [ ] ) { $ methods = static :: getExtensionsGetters ( ) ; foreach ( $ extensions as $ extensionClassName ) { if ( is_a ( $ extensionClassName , ModuleInterface :: class , true ) ) { if ( ! isset ( $ options [ 'modules' ] ) ) { $ options [ 'modules' ] = [ ] ; } $ options [ 'modules' ] [ ] = $ extensionClassName ; continue ; } static :: extractExtensionOptions ( $ options , $ extensionClassName , $ methods ) ; } return $ options ; }

Get options from extensions list and default options.

@param array $extensions list of extensions instances of class names
@param array $options    optional default options to merge with

@return array

Get options from extensions list and default options .


public static function removeOptions($path, $options)
    {
        if (self::$renderer && (empty($path) || self::$renderer->hasOption($path))) {
            if (is_array($options)) {
                foreach ($options as $key => $value) {
                    if (is_int($key)) {
                        $callbacks = self::$renderer->getOption($path);
                        if (!is_array($callbacks) || is_callable($callbacks)) {
                            $callbacks = [$callbacks];
                        }
                        self::$renderer->setOption($path, array_filter(
                            $callbacks,
                            function ($item) use ($value) {
                                return $item !== $value;
                            }
                        ));

                        continue;
                    }

                    static::removeOptions(array_merge($path, [$key]), $value);
                }

                return;
            }

            self::$renderer->unsetOption($path);
        }
    }

public static function removeOptions ( $ path , $ options ) { if ( self :: $ renderer && ( empty ( $ path ) || self :: $ renderer -> hasOption ( $ path ) ) ) { if ( is_array ( $ options ) ) { foreach ( $ options as $ key => $ value ) { if ( is_int ( $ key ) ) { $ callbacks = self :: $ renderer -> getOption ( $ path ) ; if ( ! is_array ( $ callbacks ) || is_callable ( $ callbacks ) ) { $ callbacks = [ $ callbacks ] ; } self :: $ renderer -> setOption ( $ path , array_filter ( $ callbacks , function ( $ item ) use ( $ value ) { return $ item !== $ value ; } ) ) ; continue ; } static :: removeOptions ( array_merge ( $ path , [ $ key ] ) , $ value ) ; } return ; } self :: $ renderer -> unsetOption ( $ path ) ; } }

Cleanup previously set options.

@example Phug::removeOptions(['filters'], ['coffee' => null]])

@param array $path    option base path
@param mixed $options options to remove


public static function reset()
    {
        static::resetFacadeOptions();
        self::$renderer = null;
        self::$extensions = [];
        self::$filters = [];
        self::$keywords = [];
    }

public static function reset ( ) { static :: resetFacadeOptions ( ) ; self :: $ renderer = null ; self :: $ extensions = [ ] ; self :: $ filters = [ ] ; self :: $ keywords = [ ] ; }

Reset all static options, filters and extensions.

Reset all static options filters and extensions .


public static function getRenderer(array $options = [])
    {
        $options = static::getOptions($options);

        if (!self::$renderer) {
            $rendererClassName = self::getRendererClassName();
            self::$renderer = new $rendererClassName($options);
        } elseif (!empty($options)) {
            self::$renderer->reInitOptions($options);
            self::$renderer->getCompiler()->getFormatter()->initFormats();
        }

        return self::$renderer;
    }

public static function getRenderer ( array $ options = [ ] ) { $ options = static :: getOptions ( $ options ) ; if ( ! self :: $ renderer ) { $ rendererClassName = self :: getRendererClassName ( ) ; self :: $ renderer = new $ rendererClassName ( $ options ) ; } elseif ( ! empty ( $ options ) ) { self :: $ renderer -> reInitOptions ( $ options ) ; self :: $ renderer -> getCompiler ( ) -> getFormatter ( ) -> initFormats ( ) ; } return self :: $ renderer ; }

Get a renderer with global options and argument options merged.

@example Phug::getRenderer([])

@param array $options

@return Renderer

Get a renderer with global options and argument options merged .


public static function addFilter($name, $filter)
    {
        $key = self::normalizeFilterName($name);

        if (isset(self::$filters[$key])) {
            throw new PhugException(
                'Filter '.$name.' is already set.'
            );
        }

        self::setFilter($name, $filter);
    }

public
static
function
addFilter
(
$
name
,
$
filter
)
{
$
key
=
self
::
normalizeFilterName
(
$
name
)
;
if
(
isset
(
self
::
$
filters
[
$
key
]
)
)
{
throw
new
PhugException
(
'Filter '
.
$
name
.
' is already set.'
)
;
}
self
::
setFilter
(
$
name
,
$
filter
)
;
}

Add a filter. Throws an exception if the name is already taken.

@param string          $name
@param callable|string $filter

@throws PhugException

Add a filter . Throws an exception if the name is already taken .


public static function addKeyword($name, $keyword)
    {
        $key = self::normalizeKeywordName($name);

        if (isset(self::$keywords[$key])) {
            throw new PhugException(
                'Keyword '.$name.' is already set.'
            );
        }

        self::setKeyword($name, $keyword);
    }

public
static
function
addKeyword
(
$
name
,
$
keyword
)
{
$
key
=
self
::
normalizeKeywordName
(
$
name
)
;
if
(
isset
(
self
::
$
keywords
[
$
key
]
)
)
{
throw
new
PhugException
(
'Keyword '
.
$
name
.
' is already set.'
)
;
}
self
::
setKeyword
(
$
name
,
$
keyword
)
;
}

Add a keyword. Throws an exception if the name is already taken.

@param string          $name
@param callable|string $keyword

@throws PhugException

Add a keyword . Throws an exception if the name is already taken .


public static function textualCacheDirectory($source, $destination = null, $options = null)
    {
        list($success, $errors, $errorDetails) = static::cacheDirectory($source, $destination, $options);

        return
            "$success templates cached.\n".
            "$errors templates failed to be cached.\n".
            implode('', array_map(function ($detail) {
                return $detail['inputFile']."\n".
                    $detail['error']->getMessage()."\n".
                    $detail['error']->getTraceAsString();
            }, $errorDetails));
    }

Same method as cacheDirectory but with textual human-friendly output.

@param string      $source      input directories containing pug files
@param string|null $destination output for compiled PHP files
(if array given, will be used as options array)
@param array|null  $options     optional options

@throws RendererException

@return string

Same method as cacheDirectory but with textual human - friendly output .


public function run($arguments)
    {
        $outputFile = $this->getNamedArgument($arguments, ['--output-file', '-o']);
        $bootstrapFile = $this->getNamedArgument($arguments, ['--bootstrap', '-b']);
        if ($bootstrapFile) {
            include $bootstrapFile;
        } elseif (file_exists('phugBootstrap.php')) {
            include 'phugBootstrap.php';
        }
        list(, $action) = array_pad($arguments, 2, null);
        $arguments = array_slice($arguments, 2);
        $facade = $this->facade;
        $method = $this->convertToCamelCase($action);
        $customMethods = $this->getCustomMethods();

        if (!$action) {
            echo "You must provide a method.\n";
            $this->listAvailableMethods($customMethods);

            return false;
        }

        if (!in_array($method, iterator_to_array($this->getAvailableMethods($customMethods)))) {
            echo "The method $action is not available as CLI command in the $facade facade.\n";
            $this->listAvailableMethods($customMethods);

            return false;
        }

        return $this->execute($facade, $method, $arguments, $outputFile);
    }

Run the CLI applications with arguments list, return true for a success status, false for an error status.

@param $arguments

@return bool

Run the CLI applications with arguments list return true for a success status false for an error status .


public function getAvailableMethods($customMethods = null)
    {
        foreach ([$this->methods, $customMethods ?: $this->getCustomMethods()] as $methods) {
            foreach ($methods as $method => $action) {
                $method = is_int($method) ? $action : $method;
                if (substr($method, 0, 2) !== '__') {
                    yield $method;
                }
            }
        }
    }

public function getAvailableMethods ( $ customMethods = null ) { foreach ( [ $ this -> methods , $ customMethods ? : $ this -> getCustomMethods ( ) ] as $ methods ) { foreach ( $ methods as $ method => $ action ) { $ method = is_int ( $ method ) ? $ action : $ method ; if ( substr ( $ method , 0 , 2 ) !== '__' ) { yield $ method ; } } } }

Yield all available methods.

@param array|null $customMethods pass custom methods list (calculated from the facade if missing)

@return \Generator


public function listAvailableMethods($customMethods = null)
    {
        echo "Available methods are:\n";
        foreach ($this->getAvailableMethods($customMethods ?: $this->getCustomMethods()) as $method) {
            $action = $this->convertToKebabCase($method);
            $target = isset($this->methods[$method]) ? $this->methods[$method] : $method;
            $key = array_search($target, $this->methods);
            if (is_int($key)) {
                $key = $this->methods[$key];
            }

            echo ' - '.$action.($key && $key !== $method
                    ? ' ('.$this->convertToKebabCase($key).' alias)'
                    : ''
                )."\n";
        }
    }

public
function
listAvailableMethods
(
$
customMethods
=
)
{
echo
"Available methods are:\n"
;
foreach
(
$
this
->
getAvailableMethods
(
$
customMethods
:
$
this
->
getCustomMethods
(
)
)
as
$
method
)
{
$
action
=
$
this
->
convertToKebabCase
(
$
method
)
;
$
target
=
isset
(
$
this
->
methods
[
$
method
]
)
$
this
->
methods
[
$
method
]
:
$
method
;
$
key
=
array_search
(
$
target
,
$
this
->
methods
)
;
if
(
is_int
(
$
key
)
)
{
$
key
=
$
this
->
methods
[
$
key
]
;
}
echo
' - '
.
$
action
.
(
$
key
&&
$
key
!==
$
method
' ('
.
$
this
->
convertToKebabCase
(
$
key
)
.
' alias)'
:
''
)
.
"\n"
;
}
}

Dump the list of available methods as textual output.

@param array|null $customMethods pass custom methods list (calculated from the facade if missing)

Dump the list of available methods as textual output .


public function getErrors(DataObject $record)
    {
        $errors = [];

        if (strlen($record->MetaDescription) < 10) {
            $errors[] = 'seo-editor-error-too-short';
        }
        if (strlen($record->MetaDescription) > 160) {
            $errors[] = 'seo-editor-error-too-long';
        }
        if (strlen(SiteTree::get()->filter('MetaDescription', $record->MetaDescription)->count() > 1)) {
            $errors[] = 'seo-editor-error-duplicate';
        }

        return $errors;
    }

public function getErrors ( DataObject $ record ) { $ errors = [ ] ; if ( strlen ( $ record -> MetaDescription ) < 10 ) { $ errors [ ] = 'seo-editor-error-too-short' ; } if ( strlen ( $ record -> MetaDescription ) > 160 ) { $ errors [ ] = 'seo-editor-error-too-long' ; } if ( strlen ( SiteTree :: get ( ) -> filter ( 'MetaDescription' , $ record -> MetaDescription ) -> count ( ) > 1 ) ) { $ errors [ ] = 'seo-editor-error-duplicate' ; } return $ errors ; }

Get the errors which are specific to MetaDescription

@param DataObject $record
@return array


public function getList()
    {
        $list = parent::getList();
        $params = $this->request->requestVar('q');

        if (isset($params['RemoveEmptyMetaTitles']) && $params['RemoveEmptyMetaTitles']) {
            $list = $this->removeEmptyAttributes($list, 'MetaTitle');
        }

        if (isset($params['RemoveEmptyMetaDescriptions']) && $params['RemoveEmptyMetaDescriptions']) {
            $list = $this->removeEmptyAttributes($list, 'MetaDescription');
        }

        $list = $this->markDuplicates($list);

        if (isset($params['DuplicatesOnly']) && $params['DuplicatesOnly']) {
            $list = $list->filter('IsDuplicate', true);
        }

        $list = $list->sort('ID');

        return $list;
    }

public function getList ( ) { $ list = parent :: getList ( ) ; $ params = $ this -> request -> requestVar ( 'q' ) ; if ( isset ( $ params [ 'RemoveEmptyMetaTitles' ] ) && $ params [ 'RemoveEmptyMetaTitles' ] ) { $ list = $ this -> removeEmptyAttributes ( $ list , 'MetaTitle' ) ; } if ( isset ( $ params [ 'RemoveEmptyMetaDescriptions' ] ) && $ params [ 'RemoveEmptyMetaDescriptions' ] ) { $ list = $ this -> removeEmptyAttributes ( $ list , 'MetaDescription' ) ; } $ list = $ this -> markDuplicates ( $ list ) ; if ( isset ( $ params [ 'DuplicatesOnly' ] ) && $ params [ 'DuplicatesOnly' ] ) { $ list = $ list -> filter ( 'IsDuplicate' , true ) ; } $ list = $ list -> sort ( 'ID' ) ; return $ list ; }

Get the list for the GridField

@return SS_List


private function markDuplicates($list)
    {
        $duplicates = $this->findDuplicates($list, 'MetaTitle')->map('ID', 'ID')->toArray();
        $duplicateList = new ArrayList();

        foreach ($list as $item) {
            if (in_array($item->ID, $duplicates)) {
                $item->IsDuplicate = true;
                $duplicateList->push($item);
            }
        }

        $duplicates = $this->findDuplicates($list, 'MetaDescription')->map('ID', 'ID')->toArray();
        foreach ($list as $item) {
            if (in_array($item->ID, $duplicates)) {
                $item->IsDuplicate = true;
                if (!$list->byID($item->ID)) {
                    $duplicateList->push($item);
                }
            }
        }

        $duplicateList->merge($list);
        $duplicateList->removeDuplicates();
        return $duplicateList;
    }

private function markDuplicates ( $ list ) { $ duplicates = $ this -> findDuplicates ( $ list , 'MetaTitle' ) -> map ( 'ID' , 'ID' ) -> toArray ( ) ; $ duplicateList = new ArrayList ( ) ; foreach ( $ list as $ item ) { if ( in_array ( $ item -> ID , $ duplicates ) ) { $ item -> IsDuplicate = true ; $ duplicateList -> push ( $ item ) ; } } $ duplicates = $ this -> findDuplicates ( $ list , 'MetaDescription' ) -> map ( 'ID' , 'ID' ) -> toArray ( ) ; foreach ( $ list as $ item ) { if ( in_array ( $ item -> ID , $ duplicates ) ) { $ item -> IsDuplicate = true ; if ( ! $ list -> byID ( $ item -> ID ) ) { $ duplicateList -> push ( $ item ) ; } } } $ duplicateList -> merge ( $ list ) ; $ duplicateList -> removeDuplicates ( ) ; return $ duplicateList ; }

Mark duplicate attributes

@param SS_List $list
@return SS_List


private function findDuplicates(SS_List $list, $type)
    {
        $pageAttributes = $list->map('ID', $type)->toArray();

        $potentialDuplicateAttributes = array_unique(
            array_diff_assoc(
                $pageAttributes,
                array_unique($pageAttributes)
            )
        );
        $duplicateAttributes = array_filter($pageAttributes, function ($value) use ($potentialDuplicateAttributes) {
            return in_array($value, $potentialDuplicateAttributes);
        });

        if (!count($duplicateAttributes)) {
            return $list;
        }

        return $list->filter([
            'ID' => array_keys($duplicateAttributes),
        ]);
    }

private function findDuplicates ( SS_List $ list , $ type ) { $ pageAttributes = $ list -> map ( 'ID' , $ type ) -> toArray ( ) ; $ potentialDuplicateAttributes = array_unique ( array_diff_assoc ( $ pageAttributes , array_unique ( $ pageAttributes ) ) ) ; $ duplicateAttributes = array_filter ( $ pageAttributes , function ( $ value ) use ( $ potentialDuplicateAttributes ) { return in_array ( $ value , $ potentialDuplicateAttributes ) ; } ) ; if ( ! count ( $ duplicateAttributes ) ) { return $ list ; } return $ list -> filter ( [ 'ID' => array_keys ( $ duplicateAttributes ) , ] ) ; }

Find duplicate attributes within a list

@param SS_List $list
@param string $type
@return SS_List


private function removeEmptyAttributes(SS_List $list, $type)
    {
        $pageAttributes = $list->map('ID', $type)->toArray();

        $emptyAttributess = array_map(function ($value) {
            return $value == '';
        }, $pageAttributes);

        if (!count($emptyAttributess)) {
            return $list;
        }

        return $list->filter([
            'ID:not' => array_keys(
                array_filter($emptyAttributess, function ($value) {
                    return $value == 1;
                })
            )
        ]);
    }

private function removeEmptyAttributes ( SS_List $ list , $ type ) { $ pageAttributes = $ list -> map ( 'ID' , $ type ) -> toArray ( ) ; $ emptyAttributess = array_map ( function ( $ value ) { return $ value == '' ; } , $ pageAttributes ) ; if ( ! count ( $ emptyAttributess ) ) { return $ list ; } return $ list -> filter ( [ 'ID:not' => array_keys ( array_filter ( $ emptyAttributess , function ( $ value ) { return $ value == 1 ; } ) ) ] ) ; }

Remove pages with empty attributes

@param SS_List $list
@param string $type
@return SS_List


public function processRecord($record, $columnMap, &$results, $preview = false)
    {
        $page = $this->findExistingObject($record, $columnMap);

        if (!$page || !$page->exists()) {
            return false;
        }

        foreach ($record as $fieldName => $val) {
            if ($fieldName == 'MetaTitle' || $fieldName == 'MetaDescription') {
                $sqlValue = Convert::raw2sql($val);
                DB::query("UPDATE SiteTree SET {$fieldName} = '{$sqlValue}' WHERE ID = {$page->ID}");
                if ($page->isPublished()) {
                    DB::query("UPDATE SiteTree_Live SET {$fieldName} = '{$sqlValue}' WHERE ID = {$page->ID}");
                }
            }
        }

        return $page->ID;
    }

Update the columns needed when importing from CSV

@param array $record
@param array $columnMap
@param BulkLoader_Result $results
@param bool $preview
@return bool|int


public function handle($request, $next)
    {
        return resolve(AllReleases::class)->authorize($request) ? $next($request) : abort(403);
    }

public function handle ( $ request , $ next ) { return resolve ( AllReleases :: class ) -> authorize ( $ request ) ? $ next ( $ request ) : abort ( 403 ) ; }

Handle the incoming request.

@param  \Illuminate\Http\Request  $request
@param  \Closure  $next
@return \Illuminate\Http\Response


public function getElapsedTime($decimals = null)
    {
        if (!$this->hasStopped()) {
            return false;
        }

        $elapsedTime = $this->_stopTime - $this->_startTime;

        if ($decimals) {
            return number_format($elapsedTime, $decimals);
        } else {
            return $elapsedTime;
        }
    }

public function getElapsedTime ( $ decimals = null ) { if ( ! $ this -> hasStopped ( ) ) { return false ; } $ elapsedTime = $ this -> _stopTime - $ this -> _startTime ; if ( $ decimals ) { return number_format ( $ elapsedTime , $ decimals ) ; } else { return $ elapsedTime ; } }

Get elapsed time

@param ineger[optioanl] $decimals
@return integer|false


public function read()
    {
        $responses = array();

        if (!$this->_isWritten) {
            throw new Rediska_Command_Exception('You need write before');
        }

        foreach ($this->_execs as $exec) {
            $responses[] = $exec->read();
        }

        if (isset($responses[0]) && $responses[0] === self::QUEUED) {
            $this->_isQueued = true;

            return true;
        } else {
            $this->_isWritten = false;
            return $this->parseResponses($responses);
        }
    }

public
function
read
(
)
{
$
responses
=
array
(
)
;
if
(
!
$
this
->
_isWritten
)
{
throw
new
Rediska_Command_Exception
(
'You need write before'
)
;
}
foreach
(
$
this
->
_execs
as
$
exec
)
{
$
responses
[
]
=
$
exec
->
read
(
)
;
}
if
(
isset
(
$
responses
[
0
]
)
&&
$
responses
[
0
]
===
self
::
QUEUED
)
{
$
this
->
_isQueued
=
true
;
return
true
;
}
else
{
$
this
->
_isWritten
=
false
;
return
$
this
->
parseResponses
(
$
responses
)
;
}
}

Read reponses from connection

@return array


protected function _argumentsToString($arguments)
    {
        $strings = array();
        foreach($arguments as $name => $value) {
            $key = !is_integer($name) ? "'$name' => " : '';

            if (is_object($value)) {
                $argument = get_class($value) . ' $' . $name;
            } else if (is_numeric($value)) {
                $argument = $value;
            } else if (is_string($value)) {
                $argument = "'$value'";
            } else if (is_array($value)) {
                $argument = 'array(' . $this->_argumentsToString($value) . ')';
            } else if (is_null($value)) {
                $argument = 'null';
            } else if ($value === true) {
                $argument = 'true';
            } else if ($value === false) {
                $argument = 'false';
            }

            $strings[] = $key . $argument;
        }

        return implode(', ', $strings);
    }

protected
function
_argumentsToString
(
$
arguments
)
{
$
strings
=
array
(
)
;
foreach
(
$
arguments
as
$
name
=>
$
value
)
{
$
key
=
!
is_integer
(
$
name
)
"'$name' => "
:
''
;
if
(
is_object
(
$
value
)
)
{
$
argument
=
get_class
(
$
value
)
.
' $'
.
$
name
;
}
else
if
(
is_numeric
(
$
value
)
)
{
$
argument
=
$
value
;
}
else
if
(
is_string
(
$
value
)
)
{
$
argument
=
"'$value'"
;
}
else
if
(
is_array
(
$
value
)
)
{
$
argument
=
'array('
.
$
this
->
_argumentsToString
(
$
value
)
.
')'
;
}
else
if
(
is_null
(
$
value
)
)
{
$
argument
=
'null'
;
}
else
if
(
$
value
===
true
)
{
$
argument
=
'true'
;
}
else
if
(
$
value
===
false
)
{
$
argument
=
'false'
;
}
$
strings
[
]
=
$
key
.
$
argument
;
}
return
implode
(
', '
,
$
strings
)
;
}

Convert arguments to string

@param string $string
@param array $arguments
@return string


protected function _getAndValidateArguments($arguments)
    {
        $className = get_class($this);
        if (!isset(self::$_argumentNames[$className])) {
            $reflection = new ReflectionMethod($this, 'create');
            self::$_argumentNames[$className] = array();
            foreach($reflection->getParameters() as $parameter) {
                self::$_argumentNames[$className][] = $parameter;
            }
        }

        $count = 0;
        $argumentNamesAndValues = array();
        foreach(self::$_argumentNames[$className] as $parameter) {
            if (array_key_exists($count, $arguments)) {
                $value = $arguments[$count];
            } else if ($parameter->isOptional()) {
                $value = $parameter->getDefaultValue();
            } else {
                throw new Rediska_Command_Exception("Argument '{$parameter->getName()}' not present for command '$this->_name'");
            }
            $argumentNamesAndValues[$parameter->getName()] = $value;
            $count++;
        }

        return $argumentNamesAndValues;
    }

Get and validate command arguments

@param array $arguments
@return array


protected function _throwExceptionIfNotSupported($version = null)
    {
        if (null === $version) {
            $version = $this->_version;
        }

        $redisVersion = $this->_rediska->getOption('redisVersion');

        if (version_compare($version, $redisVersion) == 1) {
            throw new Rediska_Command_Exception("Command '{$this->_name}' requires {$version}+ version of Redis server. Current version is {$redisVersion}. To change it specify 'redisVersion' option.");
        }
    }

Throw exception if command not supported by this version of Redis

@param string $version


public static function register($prepend = false)
    {
        if (self::isRegistered()) {
            return false;
        }
        if (!is_bool($prepend)) {
            $prepend = (bool) $prepend;
        }

        if (version_compare(PHP_VERSION, '5.3.0', '<')) {
            self::$_isRegistered = spl_autoload_register(self::$_callback);
        } else {
            self::$_isRegistered = spl_autoload_register(
                self::$_callback,
                true,
                $prepend
            );
        }
        return self::$_isRegistered;
    }

public static function register ( $ prepend = false ) { if ( self :: isRegistered ( ) ) { return false ; } if ( ! is_bool ( $ prepend ) ) { $ prepend = ( bool ) $ prepend ; } if ( version_compare ( PHP_VERSION , '5.3.0' , '<' ) ) { self :: $ _isRegistered = spl_autoload_register ( self :: $ _callback ) ; } else { self :: $ _isRegistered = spl_autoload_register ( self :: $ _callback , true , $ prepend ) ; } return self :: $ _isRegistered ; }

Register Rediska autoload

@param boolean $prepend Prepend the autoloader in the chain, the default is
'false'. This parameter is available since PHP 5.3.0
and will be silently disregarded otherwise.
@return boolean


public static function unregister()
    {
        if (!self::isRegistered()) {
            return false;
        }

        self::$_isRegistered = !spl_autoload_unregister(self::$_callback);

        return self::$_isRegistered;
    }

public static function unregister ( ) { if ( ! self :: isRegistered ( ) ) { return false ; } self :: $ _isRegistered = ! spl_autoload_unregister ( self :: $ _callback ) ; return self :: $ _isRegistered ; }

Unregister Rediska autoload

@return boolean


public static function getRediskaPath()
    {
        if (!self::$_rediskaPath) {
            self::$_rediskaPath = realpath(dirname(__FILE__) . '/..');
        }

        return self::$_rediskaPath;
    }

public static function getRediskaPath ( ) { if ( ! self :: $ _rediskaPath ) { self :: $ _rediskaPath = realpath ( dirname ( __FILE__ ) . '/..' ) ; } return self :: $ _rediskaPath ; }


public function getConnectionsByKeyName($name, $count)
    {
        // If we have only one backend, return it.
        if ($this->_backendsCount == 1) {
            return array_keys($this->_backends);
        }

        if (!$this->_hashringIsInitialized) {
            $this->_initializeHashring();
            $this->_hashringIsInitialized = true;
        }

        // If the key has already been mapped, return the cached entry.
        if ($this->_cacheMax > 0 && isset($this->_cache[$name])) {
            return $this->_cache[$name];
        }

        // If $count is greater than or equal to the number of available backends, return all.
        if ($count >= $this->_backendsCount) return array_keys($this->_backends);

        // Initialize the return array.
        $return = array();

        $crc32 = crc32($name);

        // Select the slice to begin with.
        $slice = floor($crc32 / $this->_slicesDiv) + $this->_slicesHalf;

        // This counter prevents going through more than 1 loop.
        $looped = false;

        while (true) {
            // Go through the hashring, one slice at a time.
            foreach ($this->_hashring[$slice] as $position => $backend) {
                // If we have a usable backend, add to the return array.
                if ($position >= $crc32) {
                    // If $count = 1, no more checks are necessary.
                    if ($count === 1) {
                        $return = array($backend);
                        break 2;
                    } elseif (!in_array($backend, $return)) {
                        $return[] = $backend;
                        if (count($return) >= $count) break 2;
                    }

                    $return = array($backend);
                    break 1;
                }
            }

            // Continue to the next slice.
            $slice++;

            // If at the end of the hashring.
            if ($slice >= $this->_slicesCount) {
                // If already looped once, something is wrong.
                if ($looped) {
                    break;
                }

                // Otherwise, loop back to the beginning.
                $crc32 = -2147483648;
                $slice = 0;
                $looped = true;
            }
        }

        // Cache the result for quick retrieval in the future.
        if ($this->_cacheMax > 0) {
            // Add to internal cache.
            $this->_cache[$name] = $return;
            $this->_cacheCount++;

            // If the cache is getting too big, clear it.
            if ($this->_cacheCount > $this->_cacheMax) {
                $this->_cleanCache();
            }
        }

        // Return the result.

        return $return;
    }

Get a list of connections by key name

@param string $name Key name
@param int $requestedCount The length of the list to return
@return array List of connections


public function getConnectionByChannelName($name)
    {
        // Get connection
        if ($this->_specifiedConnection) {
            $connection = $this->_specifiedConnection;
        } else {
            $connection = $this->_channel->getRediska()->getConnectionByKeyName($name);
        }

        if (!array_key_exists($connection->getAlias(), $this->_connections)) {
            $this->_connections[$connection->getAlias()] = clone $connection;

            // If more than one - move to non blocking mode
            if (count($this->_connections) > 1) {
                foreach($this->_connections as $connection) {
                    if ($connection->getOption('blockingMode')) {
                        $connection->setOption('blockingMode', false);
                    }
                }
            }
        }
        $connection = $this->_connections[$connection->getAlias()];

        return $connection;
    }

Get connection by channel name

@param string $name Channel name
@return Rediska_Connection


public function getChannelsByConnection(Rediska_Connection $connection)
    {
        if (!isset($this->_channelsByConnections[$connection->getAlias()])) {
            throw new Rediska_PubSub_Exception("Channels by this connection not present");
        }

        return $this->_channelsByConnections[$connection->getAlias()];
    }

Get channels by connection

@param $connection
@return array


public function get($nameOrPattern)
    {
        $configGet = new Rediska_Connection_Exec($this->_connection, array('CONFIG', 'GET', $nameOrPattern));
        $valuesAfterNames = $configGet->execute();

        if (preg_match('/\W/i', $nameOrPattern)) { // Pattern
            $isParameter = true;
            $namesAndValues = array();
            foreach($valuesAfterNames as $nameOrValue) {
                if ($isParameter) {
                    $name = $nameOrValue;
                } else {
                    $namesAndValues[$name] = $this->_sanitizeValue($nameOrValue);
                }

                $isParameter = !$isParameter;
            }

            return $namesAndValues;
        } else { // Parameter name
            if (empty($valuesAfterNames)) {
                return null;
            } else {
                return $this->_sanitizeValue($valuesAfterNames[1]);
            }
        }
    }

public
function
get
(
$
nameOrPattern
)
{
$
configGet
=
new
Rediska_Connection_Exec
(
$
this
->
_connection
,
array
(
'CONFIG'
,
'GET'
,
$
nameOrPattern
)
)
;
$
valuesAfterNames
=
$
configGet
->
execute
(
)
;
if
(
preg_match
(
'/\W/i'
,
$
nameOrPattern
)
)
{
// Pattern
$
isParameter
=
true
;
$
namesAndValues
=
array
(
)
;
foreach
(
$
valuesAfterNames
as
$
nameOrValue
)
{
if
(
$
isParameter
)
{
$
name
=
$
nameOrValue
;
}
else
{
$
namesAndValues
[
$
name
]
=
$
this
->
_sanitizeValue
(
$
nameOrValue
)
;
}
$
isParameter
=
!
$
isParameter
;
}
return
$
namesAndValues
;
}
else
{
// Parameter name
if
(
empty
(
$
valuesAfterNames
)
)
{
return
;
}
else
{
return
$
this
->
_sanitizeValue
(
$
valuesAfterNames
[
1
]
)
;
}
}
}

Get parameter or parameters by pattern

@param string $nameOrPattern Name or pattern
@return string|array


public function set($name, $value)
    {
        $exec = new Rediska_Connection_Exec($this->_connection, array('CONFIG', 'SET', $name, $value));
        $exec->execute();

        return $this;
    }

public function set ( $ name , $ value ) { $ exec = new Rediska_Connection_Exec ( $ this -> _connection , array ( 'CONFIG' , 'SET' , $ name , $ value ) ) ; $ exec -> execute ( ) ; return $ this ; }

Set value to parameter

@param string $name  Name
@param string $value Value
@return Rediska_Config


protected function _throwIfNotSupported()
    {
        $version = '2.0';
        $redisVersion = $this->_rediska->getOption('redisVersion');
        if (version_compare($version, $this->_rediska->getOption('redisVersion')) == 1) {
            throw new Rediska_Transaction_Exception("Transaction requires {$version}+ version of Redis server. Current version is {$redisVersion}. To change it specify 'redisVersion' option.");
        }
    }


public function create($name, $timeout = null)
    {
        $this->_queues->add($name);
        $this->_queueObjects[$name] = new Rediska_Key_List($this->_getKeyName("queue_$name"), array('rediska' => $this->_rediska));

        return true;
    }

public function create ( $ name , $ timeout = null ) { $ this -> _queues -> add ( $ name ) ; $ this -> _queueObjects [ $ name ] = new Rediska_Key_List ( $ this -> _getKeyName ( "queue_$name" ) , array ( 'rediska' => $ this -> _rediska ) ) ; return true ; }

Create a new queue

Visibility timeout is how long a message is left in the queue "invisible"
to other readers.  If the message is acknowleged (deleted) before the
timeout, then the message is deleted.  However, if the timeout expires
then the message will be made available to other queue readers.

@param  string  $name    queue name
@param  integer $timeout default visibility timeout
@return boolean


public function delete($name)
    {
        if ($this->_queues->remove($name)) {
            if (isset($this->_queueObjects[$name])) {
                unset($this->_queueObjects[$name]);
            }

            return $this->_rediska->delete($this->_getKeyName("queue_$name"));
        }
    }

public function delete ( $ name ) { if ( $ this -> _queues -> remove ( $ name ) ) { if ( isset ( $ this -> _queueObjects [ $ name ] ) ) { unset ( $ this -> _queueObjects [ $ name ] ) ; } return $ this -> _rediska -> delete ( $ this -> _getKeyName ( "queue_$name" ) ) ; } }

Delete a queue and all of it's messages

Returns false if the queue is not found, true if the queue exists

@param  string  $name queue name
@return boolean


public function count(Zend_Queue $queue=null)
    {
        if ($queue === null) {
            $queue = $this->_queue;
        }

        $queueName = $queue->getName();

        if (!$this->isExists($queueName)) {
            require_once 'Zend/Queue/Exception.php';
            throw new Zend_Queue_Exception('Queue does not exist:' . $queueName);
        }

        if (!isset($this->_queueObjects[$queueName])) {
            $this->_queueObjects[$queueName] = new Rediska_Key_List($this->_getKeyName("queue_$queueName"), array('rediska' => $this->_rediska));
        }

        return count($this->_queueObjects[$queueName]);
    }

public
function
count
(
Zend_Queue
$
queue
=
)
{
if
(
$
queue
===
)
{
$
queue
=
$
this
->
_queue
;
}
$
queueName
=
$
queue
->
getName
(
)
;
if
(
!
$
this
->
isExists
(
$
queueName
)
)
{
require_once
'Zend/Queue/Exception.php'
;
throw
new
Zend_Queue_Exception
(
'Queue does not exist:'
.
$
queueName
)
;
}
if
(
!
isset
(
$
this
->
_queueObjects
[
$
queueName
]
)
)
{
$
this
->
_queueObjects
[
$
queueName
]
=
new
Rediska_Key_List
(
$
this
->
_getKeyName
(
"queue_$queueName"
)
,
array
(
'rediska'
=>
$
this
->
_rediska
)
)
;
}
return
count
(
$
this
->
_queueObjects
[
$
queueName
]
)
;
}

Return the approximate number of messages in the queue

@param  Zend_Queue $queue
@return integer


public function send($message, Zend_Queue $queue=null)
    {
        if ($queue === null) {
            $queue = $this->_queue;
        }

        $queueName = $queue->getName();

        if (!$this->isExists($queueName)) {
            require_once 'Zend/Queue/Exception.php';
            throw new Zend_Queue_Exception('Queue does not exist:' . $queueName);
        }

        if (!isset($this->_queueObjects[$queueName])) {
            $this->_queueObjects[$queueName] = new Rediska_Key_List($this->_getKeyName("queue_$queueName"), array('rediska' => $this->_rediska));
        }

        $result = $this->_queueObjects[$queueName]->prepend($message);

        if ($result === false) {
            require_once 'Zend/Queue/Exception.php';
            throw new Zend_Queue_Exception('Failed to insert message into queue:' . $queueName);
        }

        $options = array(
            'queue' => $queue,
            'data'  => array('body' => $message),
        );

        $classname = $queue->getMessageClass();
        if (!class_exists($classname)) {
            require_once 'Zend/Loader.php';
            Zend_Loader::loadClass($classname);
        }
        return new $classname($options);
    }

public
function
send
(
$
message
,
Zend_Queue
$
queue
=
)
{
if
(
$
queue
===
)
{
$
queue
=
$
this
->
_queue
;
}
$
queueName
=
$
queue
->
getName
(
)
;
if
(
!
$
this
->
isExists
(
$
queueName
)
)
{
require_once
'Zend/Queue/Exception.php'
;
throw
new
Zend_Queue_Exception
(
'Queue does not exist:'
.
$
queueName
)
;
}
if
(
!
isset
(
$
this
->
_queueObjects
[
$
queueName
]
)
)
{
$
this
->
_queueObjects
[
$
queueName
]
=
new
Rediska_Key_List
(
$
this
->
_getKeyName
(
"queue_$queueName"
)
,
array
(
'rediska'
=>
$
this
->
_rediska
)
)
;
}
$
result
=
$
this
->
_queueObjects
[
$
queueName
]
->
prepend
(
$
message
)
;
if
(
$
result
===
false
)
{
require_once
'Zend/Queue/Exception.php'
;
throw
new
Zend_Queue_Exception
(
'Failed to insert message into queue:'
.
$
queueName
)
;
}
$
options
=
array
(
'queue'
=>
$
queue
,
'data'
=>
array
(
'body'
=>
$
message
)
,
)
;
$
classname
=
$
queue
->
getMessageClass
(
)
;
if
(
!
class_exists
(
$
classname
)
)
{
require_once
'Zend/Loader.php'
;
Zend_Loader
::
loadClass
(
$
classname
)
;
}
return
new
$
classname
(
$
options
)
;
}

Send a message to the queue

@param  string     $message Message to send to the active queue
@param  Zend_Queue $queue
@return Zend_Queue_Message
@throws Zend_Queue_Exception


public function receive($maxMessages=null, $timeout=null, Zend_Queue $queue=null)
    {
        if ($maxMessages === null) {
            $maxMessages = 1;
        }
        if ($queue === null) {
            $queue = $this->_queue;
        }

        $queueName = $queue->getName();

        if (!$this->isExists($queueName)) {
            require_once 'Zend/Queue/Exception.php';
            throw new Zend_Queue_Exception('Queue does not exist:' . $queueName);
        }

        if (!isset($this->_queueObjects[$queueName])) {
            $this->_queueObjects[$queueName] = new Rediska_Key_List($this->_getKeyName("queue_$queueName"), array('rediska' => $this->_rediska));
        }

        $messages = array();
        for ($i = 0; $i < $maxMessages; $i++) {
            $message = $this->_queueObjects[$queueName]->pop();
            if (!is_null($message)) {
                $messages[] = array('body' => $message);
            }
        }

        $options = array(
            'queue'        => $queue,
            'data'         => $messages,
            'messageClass' => $queue->getMessageClass(),
        );

        $classname = $queue->getMessageSetClass();
        if (!class_exists($classname)) {
            require_once 'Zend/Loader.php';
            Zend_Loader::loadClass($classname);
        }
        return new $classname($options);
    }

public
function
receive
(
$
maxMessages
=
,
$
timeout
=
,
Zend_Queue
$
queue
=
)
{
if
(
$
maxMessages
===
)
{
$
maxMessages
=
1
;
}
if
(
$
queue
===
)
{
$
queue
=
$
this
->
_queue
;
}
$
queueName
=
$
queue
->
getName
(
)
;
if
(
!
$
this
->
isExists
(
$
queueName
)
)
{
require_once
'Zend/Queue/Exception.php'
;
throw
new
Zend_Queue_Exception
(
'Queue does not exist:'
.
$
queueName
)
;
}
if
(
!
isset
(
$
this
->
_queueObjects
[
$
queueName
]
)
)
{
$
this
->
_queueObjects
[
$
queueName
]
=
new
Rediska_Key_List
(
$
this
->
_getKeyName
(
"queue_$queueName"
)
,
array
(
'rediska'
=>
$
this
->
_rediska
)
)
;
}
$
messages
=
array
(
)
;
for
(
$
i
=
0
;
$
i
<
$
maxMessages
;
$
i
++
)
{
$
message
=
$
this
->
_queueObjects
[
$
queueName
]
->
pop
(
)
;
if
(
!
is_null
(
$
message
)
)
{
$
messages
[
]
=
array
(
'body'
=>
$
message
)
;
}
}
$
options
=
array
(
'queue'
=>
$
queue
,
'data'
=>
$
messages
,
'messageClass'
=>
$
queue
->
getMessageClass
(
)
,
)
;
$
classname
=
$
queue
->
getMessageSetClass
(
)
;
if
(
!
class_exists
(
$
classname
)
)
{
require_once
'Zend/Loader.php'
;
Zend_Loader
::
loadClass
(
$
classname
)
;
}
return
new
$
classname
(
$
options
)
;
}

Get messages in the queue

@param  integer    $maxMessages  Maximum number of messages to return
@param  integer    $timeout      Visibility timeout for these messages
@param  Zend_Queue $queue
@return Zend_Queue_Message_Iterator


public function deleteMessage(Zend_Queue_Message $message)
    {
        $queueName = $this->_queue->getName();

        if (!isset($this->_queueObjects[$queueName])) {
            $this->_queueObjects[$queueName] = new Rediska_Key_List($this->_getKeyName("queue_$queueName"), array('rediska' => $this->_rediska));
        }

        return (boolean)$this->_queueObjects[$queueName]->remove($message->body);
    }

public function deleteMessage ( Zend_Queue_Message $ message ) { $ queueName = $ this -> _queue -> getName ( ) ; if ( ! isset ( $ this -> _queueObjects [ $ queueName ] ) ) { $ this -> _queueObjects [ $ queueName ] = new Rediska_Key_List ( $ this -> _getKeyName ( "queue_$queueName" ) , array ( 'rediska' => $ this -> _rediska ) ) ; } return ( boolean ) $ this -> _queueObjects [ $ queueName ] -> remove ( $ message -> body ) ; }

Delete a message from the queue

Returns true if the message is deleted, false if the deletion is
unsuccessful.

@param  Zend_Queue_Message $message
@return boolean


public function getTotalElapsedTime($decimals = null)
    {
        $totalElapsedTime = 0;
        foreach ($this->getProfiles() as $profile) {
            if ($profile->hasStopped()) {
                $totalElapsedTime += $profile->getElapsedTime();
            }
        }

        if ($decimals) {
            return number_format($totalElapsedTime, $decimals);
        } else {
            return $totalElapsedTime;
        }
    }

public function getTotalElapsedTime ( $ decimals = null ) { $ totalElapsedTime = 0 ; foreach ( $ this -> getProfiles ( ) as $ profile ) { if ( $ profile -> hasStopped ( ) ) { $ totalElapsedTime += $ profile -> getElapsedTime ( ) ; } } if ( $ decimals ) { return number_format ( $ totalElapsedTime , $ decimals ) ; } else { return $ totalElapsedTime ; } }

Get total elapsed time

@param integer[optional] $decimals
@return integer


public function set($fieldOrData, $value = null, $overwrite = true)
    {
        $result = $this->_getRediskaOn()->setToHash($this->getName(), $fieldOrData, $value, $overwrite);

        if (!is_null($this->getExpire()) && ((!$overwrite && $result) || ($overwrite))) {
            $this->expire($this->getExpire(), $this->isExpireTimestamp());
        }

        return $result;
    }

public function set ( $ fieldOrData , $ value = null , $ overwrite = true ) { $ result = $ this -> _getRediskaOn ( ) -> setToHash ( $ this -> getName ( ) , $ fieldOrData , $ value , $ overwrite ) ; if ( ! is_null ( $ this -> getExpire ( ) ) && ( ( ! $ overwrite && $ result ) || ( $ overwrite ) ) ) { $ this -> expire ( $ this -> getExpire ( ) , $ this -> isExpireTimestamp ( ) ) ; } return $ result ; }

Set value to a hash field or fields

@param array|string  $fieldOrData  Field or array of many fields and values: field => value
@param mixed         $value        Value for single field
@param boolean       $overwrite    Overwrite for single field (if false don't set and return false if key already exist). For default true.
@return boolean


public function offsetSet($field, $value)
    {
        if (is_null($field)) {
            throw new Rediska_Key_Exception('Field must be present');
        }

        $this->set($field, $value);

        return $value;
    }

public
function
offsetSet
(
$
field
,
$
value
)
{
if
(
is_null
(
$
field
)
)
{
throw
new
Rediska_Key_Exception
(
'Field must be present'
)
;
}
$
this
->
set
(
$
field
,
$
value
)
;
return
$
value
;
}

Array magic for set a field

@param string $field
@param mixed $value
@return boolean


public function increment($field, $amount = 1)
    {
        $result = $this->_getRediskaOn()->incrementInHash($this->getName(), $field, $amount);

        if (!is_null($this->getExpire()) && $result) {
            $this->expire($this->getExpire(), $this->isExpireTimestamp());
        }

        return $result;
    }

public function increment ( $ field , $ amount = 1 ) { $ result = $ this -> _getRediskaOn ( ) -> incrementInHash ( $ this -> getName ( ) , $ field , $ amount ) ; if ( ! is_null ( $ this -> getExpire ( ) ) && $ result ) { $ this -> expire ( $ this -> getExpire ( ) , $ this -> isExpireTimestamp ( ) ) ; } return $ result ; }

Increment field value in hash

@param mixed  $field            Field
@param number $amount[optional] Increment amount. Default: 1
@return integer


public function remove($field)
    {
        $result = $this->_getRediskaOn()->deleteFromHash($this->getName(), $field);

        if (!is_null($this->getExpire()) && $result) {
            $this->expire($this->getExpire(), $this->isExpireTimestamp());
        }

        return $result;
    }

public function remove ( $ field ) { $ result = $ this -> _getRediskaOn ( ) -> deleteFromHash ( $ this -> getName ( ) , $ field ) ; if ( ! is_null ( $ this -> getExpire ( ) ) && $ result ) { $ this -> expire ( $ this -> getExpire ( ) , $ this -> isExpireTimestamp ( ) ) ; } return $ result ; }

Remove field from hash

@param mixed  $field Field
@return boolean


public function write($id, $data)
    {
        try {
            $timestamp = time();
            $this->_set[$timestamp] = $id;
        } catch (Rediska_Connection_Exec_Exception $e) {
            $this->_deleteSetOrThrowException($e);
        }

        return $this->getRediska()->setAndExpire(
            $this->_getKeyName($id),
            $data,
            $this->getOption('lifetime')
        );
    }

public function write ( $ id , $ data ) { try { $ timestamp = time ( ) ; $ this -> _set [ $ timestamp ] = $ id ; } catch ( Rediska_Connection_Exec_Exception $ e ) { $ this -> _deleteSetOrThrowException ( $ e ) ; } return $ this -> getRediska ( ) -> setAndExpire ( $ this -> _getKeyName ( $ id ) , $ data , $ this -> getOption ( 'lifetime' ) ) ; }

Write session data

@param string $id
@param string $data
@return boolean


public function subscribe($channelOrChannels)
    {
        if (!is_array($channelOrChannels)) {
            $channels = array($channelOrChannels);
        } else {
            $channels = $channelOrChannels;
        }

        $this->_execCommand(self::SUBSCRIBE, $channels);

        return $this;
    }

public function subscribe ( $ channelOrChannels ) { if ( ! is_array ( $ channelOrChannels ) ) { $ channels = array ( $ channelOrChannels ) ; } else { $ channels = $ channelOrChannels ; } $ this -> _execCommand ( self :: SUBSCRIBE , $ channels ) ; return $ this ; }

Subscribe to channel or channels

@param string|array $channelOrChannels Channel name or names
@return Rediska_PubSub_Channel


public function publish($message)
    {
        $rediska = $this->getRediska();

        if ($this->getServerAlias() !== null) {
            $rediska = $rediska->on($this->getServerAlias());
        }

        return $rediska->publish($this->_subscriptions, $message);
    }

public function publish ( $ message ) { $ rediska = $ this -> getRediska ( ) ; if ( $ this -> getServerAlias ( ) !== null ) { $ rediska = $ rediska -> on ( $ this -> getServerAlias ( ) ) ; } return $ rediska -> publish ( $ this -> _subscriptions , $ message ) ; }

Publish a message to channel

@param $message
@return int


protected function _addMessageToBuffer(Rediska_PubSub_Response_Message $message)
    {
        $key = "{$message->getConnection()->getAlias()}-{$message->getChannel()}";

        if (!isset(self::$_messages[$key])) {
            self::$_messages[$key] = array();
        }

        self::$_messages[$key][] = $message;
    }

Add message response to buffer

@param Rediska_PubSub_Response_Message $message


protected function _throwIfNotSupported()
    {
        $version = '1.3.8';
        $redisVersion = $this->getRediska()->getOption('redisVersion');
        if (version_compare($version, $this->getRediska()->getOption('redisVersion')) == 1) {
            throw new Rediska_PubSub_Exception("Publish/Subscribe requires {$version}+ version of Redis server. Current version is {$redisVersion}. To change it specify 'redisVersion' option.");
        }
    }


public function catchUnserializeNotice($errno, $errstr, $errfile, $errline, $errcontext)
    {
        if (!error_reporting() && strpos($errstr, 'unserialize()') !== false) {
            $this->_unserialized = false;
            return true;
        } else {
            return false;
        }
    }

public function catchUnserializeNotice ( $ errno , $ errstr , $ errfile , $ errline , $ errcontext ) { if ( ! error_reporting ( ) && strpos ( $ errstr , 'unserialize()' ) !== false ) { $ this -> _unserialized = false ; return true ; } else { return false ; } }


public function add($name)
    {
        $result = $this->_queuesSet->add($name);

        if ($result) {
            $queuesCache = $this->_getQueuesCache();
            $queuesCache[] = $name;
            $this->_setQueuesCache($queuesCache);
        }

        return $result;
    }

public function add ( $ name ) { $ result = $ this -> _queuesSet -> add ( $ name ) ; if ( $ result ) { $ queuesCache = $ this -> _getQueuesCache ( ) ; $ queuesCache [ ] = $ name ; $ this -> _setQueuesCache ( $ queuesCache ) ; } return $ result ; }

Create a new queue in the queues set

@param string $name
@return bool


public function remove($name)
    {
        $result = $this->_queuesSet->remove($name);

        if ($result) {
            $queuesCache = $this->_getQueuesCache();

            $key = array_search($name, $queuesCache);
            unset($queuesCache[$key]);

            $this->_setQueuesCache($queuesCache);
        }

        return $result;
    }

public function remove ( $ name ) { $ result = $ this -> _queuesSet -> remove ( $ name ) ; if ( $ result ) { $ queuesCache = $ this -> _getQueuesCache ( ) ; $ key = array_search ( $ name , $ queuesCache ) ; unset ( $ queuesCache [ $ key ] ) ; $ this -> _setQueuesCache ( $ queuesCache ) ; } return $ result ; }

Delete a queue from the queues set

@param $name
@return bool


protected function _getQueuesCache()
    {
        if ($this->_queuesCache === null) {
            $this->_queuesCache = $this->_queuesSet->toArray();
        }

        return $this->_queuesCache;
    }

protected function _getQueuesCache ( ) { if ( $ this -> _queuesCache === null ) { $ this -> _queuesCache = $ this -> _queuesSet -> toArray ( ) ; } return $ this -> _queuesCache ; }

Get queues cache. Fetches data from redis on first call.

@return array

Get queues cache . Fetches data from redis on first call .


public function watch($keyOrKeys)
    {
        $this->_throwIfNotSupported('Watch', '2.1');

        $command = array('WATCH');

        if (!is_array($keyOrKeys)) {
            $keys = array($keyOrKeys);
        } else {
            $keys = $keyOrKeys;
        }

        foreach($keys as $key) {
            $command[] = $this->_rediska->getOption('namespace') . $key;
        }

        $exec = new Rediska_Connection_Exec($this->_connection, $command);
        $exec->execute();

        $this->_isWatched = true;

        return $this;
    }

public function watch ( $ keyOrKeys ) { $ this -> _throwIfNotSupported ( 'Watch' , '2.1' ) ; $ command = array ( 'WATCH' ) ; if ( ! is_array ( $ keyOrKeys ) ) { $ keys = array ( $ keyOrKeys ) ; } else { $ keys = $ keyOrKeys ; } foreach ( $ keys as $ key ) { $ command [ ] = $ this -> _rediska -> getOption ( 'namespace' ) . $ key ; } $ exec = new Rediska_Connection_Exec ( $ this -> _connection , $ command ) ; $ exec -> execute ( ) ; $ this -> _isWatched = true ; return $ this ; }

Marks the given keys to be watched for conditional execution of a transaction.

@throws Rediska_Transaction_Exception
@param  $keyOrKeys Key or array of keys
@return Rediska_Transaction

Marks the given keys to be watched for conditional execution of a transaction .


public function unwatch()
    {
        $this->_throwIfNotSupported('Unwatch', '2.1');

        $command = 'UNWATCH';

        $exec = new Rediska_Connection_Exec($this->_connection, $command);
        $exec->execute();

        $this->_isWatched = false;

        return $this;
    }

public function unwatch ( ) { $ this -> _throwIfNotSupported ( 'Unwatch' , '2.1' ) ; $ command = 'UNWATCH' ; $ exec = new Rediska_Connection_Exec ( $ this -> _connection , $ command ) ; $ exec -> execute ( ) ; $ this -> _isWatched = false ; return $ this ; }

Flushes all the previously watched keys for a transaction.

@return Rediska_Transaction

Flushes all the previously watched keys for a transaction .


protected function _addCommand($name, $args = array())
    {
        $this->_specifiedConnection->setConnection($this->_connection);

        $command = Rediska_Commands::get($this->_rediska, $name, $args);
        $command->initialize();

        if (!$command->isAtomic()) {
            throw new Rediska_Exception("Command '$name' doesn't work properly (not atomic) in transaction on multiple servers");
        }

        $this->_commands[] = $command;

        $this->_specifiedConnection->resetConnection();

        return $this;
    }

Add command to transaction

@param string $name Command name
@param array  $args Arguments
@return Rediska_Transaction


public function newAction()
    {
        $currentUser = Zend_Auth::getInstance()->getStorage()->read();

        $form = new Form_Post;

        if ($this->getRequest()->isPost() && $form->isValid($this->getRequest()->getPost())) {

            $postData = $form->getValues();
            $postData['id'] = Post::fetchNextId();
            $postData['userId'] = $currentUser['id'];

            // save post
            $post = new Post($postData['id']);
            $post->setValue($postData);

            $userPosts = new UserPosts($currentUser['id']);
            $userPosts->add($postData['id']);

            // save post in the follower feeds
            $followers = new Followers($currentUser['id']);
            foreach ($followers as $followerId) {
                $feed = new Feed($followerId);
                $feed->prepend($postData['id']);
            }

            $this->_redirect('/post/my');
        }

        $this->view->form = $form;
    }

public
function
newAction
(
)
{
$
currentUser
=
Zend_Auth
::
getInstance
(
)
->
getStorage
(
)
->
read
(
)
;
$
form
=
new
Form_Post
;
if
(
$
this
->
getRequest
(
)
->
isPost
(
)
&&
$
form
->
isValid
(
$
this
->
getRequest
(
)
->
getPost
(
)
)
)
{
$
postData
=
$
form
->
getValues
(
)
;
$
postData
[
'id'
]
=
Post
::
fetchNextId
(
)
;
$
postData
[
'userId'
]
=
$
currentUser
[
'id'
]
;
// save post
$
post
=
new
Post
(
$
postData
[
'id'
]
)
;
$
post
->
setValue
(
$
postData
)
;
$
userPosts
=
new
UserPosts
(
$
currentUser
[
'id'
]
)
;
$
userPosts
->
add
(
$
postData
[
'id'
]
)
;
// save post in the follower feeds
$
followers
=
new
Followers
(
$
currentUser
[
'id'
]
)
;
foreach
(
$
followers
as
$
followerId
)
{
$
feed
=
new
Feed
(
$
followerId
)
;
$
feed
->
prepend
(
$
postData
[
'id'
]
)
;
}
$
this
->
_redirect
(
'/post/my'
)
;
}
$
this
->
view
->
form
=
$
form
;
}


public function indexAction()
    {
        $currentUser = Zend_Auth::getInstance()->getStorage()->read();

        $feed = new Feed($currentUser['id']);

        $this->view->posts = array();

        // just for example, better use multiget
        foreach ($feed as $postId) {
            $post = new Post($postId);
            $postData = $post->getValue();

            $user = new User($postData['userId']);
            $userData = $user->getValue();

            $this->view->posts[] = array('post' => $postData, 'user' => $userData);
        }
    }


static public function factory($config)
    {
        $config = self::_parseConfig($config);

        if (!isset($config['keyName'])) {
            throw new Zend_Log_Exception('keyName not present');
        }

        if (!isset($config['rediska'])) {
            $config['rediska'] = Rediska::DEFAULT_NAME;
        }

        return new self($config['keyName'], $config['rediska']);
    }

static
public
function
factory
(
$
config
)
{
$
config
=
self
::
_parseConfig
(
$
config
)
;
if
(
!
isset
(
$
config
[
'keyName'
]
)
)
{
throw
new
Zend_Log_Exception
(
'keyName not present'
)
;
}
if
(
!
isset
(
$
config
[
'rediska'
]
)
)
{
$
config
[
'rediska'
]
=
Rediska
::
DEFAULT_NAME
;
}
return
new
self
(
$
config
[
'keyName'
]
,
$
config
[
'rediska'
]
)
;
}

Create a new instance of Rediska_Zend_Log_Writer_Redis

@param  array|Zend_Config $config
@return Zend_Log_Writer_Mock
@throws Zend_Log_Exception


public function add($value, $score)
    {
        $result = $this->_getRediskaOn()->addToSortedSet($this->getName(), $value, $score);

        if (!is_null($this->getExpire()) && $result) {
            $this->expire($this->getExpire(), $this->isExpireTimestamp());
        }

        return $result;
    }

public function add ( $ value , $ score ) { $ result = $ this -> _getRediskaOn ( ) -> addToSortedSet ( $ this -> getName ( ) , $ value , $ score ) ; if ( ! is_null ( $ this -> getExpire ( ) ) && $ result ) { $ this -> expire ( $ this -> getExpire ( ) , $ this -> isExpireTimestamp ( ) ) ; } return $ result ; }

Add the specified member to the Sorted set

@param mixed $value Value
@param numeric $score Score
@return boolean