diff options
author | Pierre Schmitz <pierre@archlinux.de> | 2015-08-16 08:22:05 +0200 |
---|---|---|
committer | Pierre Schmitz <pierre@archlinux.de> | 2015-08-16 08:22:05 +0200 |
commit | 1a365e77dfb8825136626202b1df462731b42060 (patch) | |
tree | 1dc4468eaabf070e051e790a9e67a9a9a2c63d99 | |
parent | a72fd280f7acb4d2a1ba579a0f1b2b2ae8958530 (diff) |
Update to MediaWiki 1.25.2
863 files changed, 55632 insertions, 3666 deletions
diff --git a/RELEASE-NOTES-1.25 b/RELEASE-NOTES-1.25 index 223cf97c..6d32a445 100644 --- a/RELEASE-NOTES-1.25 +++ b/RELEASE-NOTES-1.25 @@ -1,16 +1,41 @@ Security reminder: If you have PHP's register_globals option set, you must turn it off. MediaWiki will not work with it enabled. +== MediaWiki 1.25.2 == + +This is a security and maintenance release of the MediaWiki 1.25 branch. + +=== Changes since 1.25.1 === + +* (T94116) SECURITY: Compare API watchlist token in constant time +* (T97391) SECURITY: Escape error message strings in thumb.php +* (T106893) SECURITY: Don't leak autoblocked IP addresses on + Special:DeletedContributions +* (T102562) Fix InstantCommons parameters to handle the new HTTPS-only + policy of Wikimedia Commons. +* (T100767) Setting a configuration setting for skin or extension to + false in LocalSettings.php was not working. +* (T100635) API action=opensearch json output no longer breaks when + $wgDebugToolbar is enabled. +* (T102522) Using an extension.json or skin.json file which has + a "manifest_version" property for 1.26 compatability will no longer + trigger warnings. +* (T86156) Running updateSearchIndex.php will not throw an error as + page_restrictions has been added to the locked table list. +* Special:Version would throw notices if using SVN due to an incorrectly + named variable. Add an additional check that an index is defined. + == MediaWiki 1.25.1 == This is a bug fix release of the MediaWiki 1.25 branch. -== Changes since 1.25.1 == - +=== Changes since 1.25 === * (T100351) Fix syntax errors in extension.json of ConfirmEdit extension == MediaWiki 1.25 == +MediaWiki 1.25.x is the stable branch and is recommended for use in production. + === Configuration changes in 1.25 === * $wgPageShowWatchingUsers was removed. * $wgLocalVirtualHosts has been added to replace $wgConf->localVHosts. @@ -513,7 +538,6 @@ changes to languages because of Bugzilla reports. loadedScripts object, from wikibits.js (deprecated since 1.17) now emit warnings through mw.log.warn when accessed. - == Compatibility == MediaWiki 1.25 requires PHP 5.3.3 or later. There is experimental support for diff --git a/docs/hooks.txt b/docs/hooks.txt index 6f2050cc..e9c0e205 100644 --- a/docs/hooks.txt +++ b/docs/hooks.txt @@ -1840,6 +1840,11 @@ $param: Associative Array with the following additional options: "<div ...>$1</div>"). - flags Integer display flags (NO_ACTION_LINK,NO_EXTRA_USER_LINKS) +'LogException': Called before an exception (or PHP error) is logged. This is meant for integration +with external error aggregation services; returning false will NOT prevent logging. +$e: The exception (in case of a plain old PHP error, a wrapping ErrorException) +$suppressed: true if the error was suppressed via error_reporting()/wfSuppressWarnings() + 'LoginAuthenticateAudit': A login attempt for a valid user account either succeeded or failed. No return data is accepted; this hook is for auditing only. $user: the User object being authenticated against diff --git a/extensions/ConfirmEdit/ApiFancyCaptchaReload.php b/extensions/ConfirmEdit/FancyCaptcha/ApiFancyCaptchaReload.php index 8cd28631..8cd28631 100644 --- a/extensions/ConfirmEdit/ApiFancyCaptchaReload.php +++ b/extensions/ConfirmEdit/FancyCaptcha/ApiFancyCaptchaReload.php diff --git a/extensions/ConfirmEdit/FancyCaptcha/extension.json b/extensions/ConfirmEdit/FancyCaptcha/extension.json index 11b877be..dba07d9b 100644 --- a/extensions/ConfirmEdit/FancyCaptcha/extension.json +++ b/extensions/ConfirmEdit/FancyCaptcha/extension.json @@ -38,9 +38,7 @@ "localBasePath": "resources", "remoteExtPath": "ConfirmEdit/FancyCaptcha/resources" }, - "callback": [ - "ConfirmEditHooks::onFancyCaptchaSetup" - ], + "callback": "ConfirmEditHooks::onFancyCaptchaSetup", "config": { "CaptchaClass": "FancyCaptcha", "CaptchaFileBackend": "", diff --git a/extensions/ConfirmEdit/ReCaptcha/extension.json b/extensions/ConfirmEdit/ReCaptcha/extension.json index 5f97810a..79c90491 100644 --- a/extensions/ConfirmEdit/ReCaptcha/extension.json +++ b/extensions/ConfirmEdit/ReCaptcha/extension.json @@ -1,7 +1,7 @@ { "name": "ReCaptcha", "ExtensionFunctions": [ - "efReCaptcha" + "ConfirmEditHooks::efReCaptcha" ], "MessagesDirs": { "ReCaptcha": [ diff --git a/extensions/ConfirmEdit/includes/ConfirmEditHooks.php b/extensions/ConfirmEdit/includes/ConfirmEditHooks.php index 5f9c3384..41c990f1 100644 --- a/extensions/ConfirmEdit/includes/ConfirmEditHooks.php +++ b/extensions/ConfirmEdit/includes/ConfirmEditHooks.php @@ -139,11 +139,36 @@ class ConfirmEditHooks { $wgCaptchaDirectory = "$wgUploadDirectory/captcha"; } } + /** * Callback for extension.json of ReCaptcha to require the recaptcha library php file. * FIXME: This should be done in a better way, e.g. only load the libraray, if really needed. */ public static function onReCaptchaSetup() { - require_once( "ReCaptcha/recaptchalib.php" ); + require_once( __DIR__ . '/../ReCaptcha/recaptchalib.php' ); + } + + /** + * Extension function, moved from ReCaptcha.php when that was decimated. + * Make sure the keys are defined. + */ + public static function efReCaptcha() { + global $wgReCaptchaPublicKey, $wgReCaptchaPrivateKey; + global $recaptcha_public_key, $recaptcha_private_key; + global $wgServerName; + + // Backwards compatibility + if ( $wgReCaptchaPublicKey == '' ) { + $wgReCaptchaPublicKey = $recaptcha_public_key; + } + if ( $wgReCaptchaPrivateKey == '' ) { + $wgReCaptchaPrivateKey = $recaptcha_private_key; + } + + if ( $wgReCaptchaPublicKey == '' || $wgReCaptchaPrivateKey == '' ) { + die ( 'You need to set $wgReCaptchaPrivateKey and $wgReCaptchaPublicKey in LocalSettings.php to ' . + "use the reCAPTCHA plugin. You can sign up for a key <a href='" . + htmlentities( recaptcha_get_signup_url ( $wgServerName, "mediawiki" ) ) . "'>here</a>." ); + } } } diff --git a/extensions/SyntaxHighlight_GeSHi/geshi/contrib/aliased.php b/extensions/SyntaxHighlight_GeSHi/geshi/contrib/aliased.php deleted file mode 100644 index 0d4b2838..00000000 --- a/extensions/SyntaxHighlight_GeSHi/geshi/contrib/aliased.php +++ /dev/null @@ -1,122 +0,0 @@ -<?php -/** - * Another GeSHi example script - * - * Configure your Apache server with 'AcceptPathInfo true' and something like - * 'Alias /viewmysource /var/www/geshi/contrib/aliased.php'. Don't forget - * to protect this alias as necessary. - * - * Usage - visit /viewmysource/file.name.ext to see that file with syntax - * highlighting, where "viewmysource" is the name of the alias you set up. - * You can use this without an alias too, just by visiting - * aliased.php/file.name.ext. - * - * @author Ross Golder <ross@golder.org> - * @version $Id$ - */ - -// Your config here -define("SOURCE_ROOT", "/var/www/your/source/root/"); - -// Assume you've put geshi in the include_path already -require_once("geshi.php"); - -// Get path info -$path = SOURCE_ROOT.$_SERVER['PATH_INFO']; - -// Check for dickheads trying to use '../' to get to sensitive areas -$base_path_len = strlen(SOURCE_ROOT); -$real_path = realpath($path); -if(strncmp($real_path, SOURCE_ROOT, $base_path_len)) { - exit("Access outside acceptable path."); -} - -// Check file exists -if(!file_exists($path)) { - exit("File not found ($path)."); -} - -// Prepare GeSHi instance -$geshi = new GeSHi(); -$geshi->set_language('text'); -$geshi->load_from_file($path); -$geshi->set_header_type(GESHI_HEADER_PRE); -$geshi->enable_classes(); -$geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS, 10); -$geshi->set_overall_style('color: #000066; border: 1px solid #d0d0d0; background-color: #f0f0f0;', true); -$geshi->set_line_style('font: normal normal 95% \'Courier New\', Courier, monospace; color: #003030;', 'font-weight: bold; color: #006060;', true); -$geshi->set_code_style('color: #000020;', 'color: #000020;'); -$geshi->set_link_styles(GESHI_LINK, 'color: #000060;'); -$geshi->set_link_styles(GESHI_HOVER, 'background-color: #f0f000;'); -$geshi->set_header_content('Source code viewer - ' . $path . ' - ' . $geshi->get_language_name()); -$geshi->set_header_content_style('font-family: Verdana, Arial, sans-serif; color: #808080; font-size: 70%; font-weight: bold; background-color: #f0f0ff; border-bottom: 1px solid #d0d0d0; padding: 2px;'); -$geshi->set_footer_content('Parsed in <TIME> seconds, using GeSHi <VERSION>'); -$geshi->set_footer_content_style('font-family: Verdana, Arial, sans-serif; color: #808080; font-size: 70%; font-weight: bold; background-color: #f0f0ff; border-top: 1px solid #d0d0d0; padding: 2px;'); - -?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head> - <title>Source code viewer - <?php echo $path; ?> - <?php $geshi->get_language_name(); ?></title> - <style type="text/css"> - <!-- - <?php - // Output the stylesheet. Note it doesn't output the <style> tag - echo $geshi->get_stylesheet(); - ?> - html { - background-color: #f0f0f0; - } - body { - font-family: Verdana, Arial, sans-serif; - margin: 10px; - border: 2px solid #e0e0e0; - background-color: #fcfcfc; - padding: 5px; - } - h2 { - margin: .1em 0 .2em .5em; - border-bottom: 1px solid #b0b0b0; - color: #b0b0b0; - font-weight: normal; - font-size: 150%; - } - h3 { - margin: .1em 0 .2em .5em; - color: #b0b0b0; - font-weight: normal; - font-size: 120%; - } - #footer { - text-align: center; - font-size: 80%; - color: #a9a9a9; - } - #footer a { - color: #9999ff; - } - textarea { - border: 1px solid #b0b0b0; - font-size: 90%; - color: #333; - margin-left: 20px; - } - select, input { - margin-left: 20px; - } - p { - font-size: 90%; - margin-left: .5em; - } - --> - </style> -</head> -<body> -<?php -// The fun part :) -echo $geshi->parse_code(); -?> -<hr/> -</body> -</html> diff --git a/extensions/SyntaxHighlight_GeSHi/geshi/contrib/cssgen.php b/extensions/SyntaxHighlight_GeSHi/geshi/contrib/cssgen.php deleted file mode 100644 index d0dac0f9..00000000 --- a/extensions/SyntaxHighlight_GeSHi/geshi/contrib/cssgen.php +++ /dev/null @@ -1,464 +0,0 @@ -<?php -/************************************************************************************* - * cssgen.php - * ---------- - * Author: Nigel McNie (nigel@geshi.org) - * Copyright: (c) 2004 Nigel McNie - * Release Version: 1.0.8.12 - * Date Started: 2004/05/20 - * - * Application to generate custom CSS files for GeSHi (based on an idea by Andreas - * Gohr) - * - ************************************************************************************* - * - * This file is part of GeSHi. - * - * GeSHi is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GeSHi is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GeSHi; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - ************************************************************************************/ - -set_magic_quotes_runtime(0); -// -// Functions -// - -function make_header ( $title ) -{ - echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head> - <title>GeSHi CSS Generator :: ' . $title . ' </title> - <style type="text/css" media="screen"> - <!-- - html { - font-family: Verdana, Arial, sans-serif; - font-size: 80%; - background-color: #d0d0d0; - } - body { - margin: 10px; - padding: 5px; - border: 1px solid #f0f0f0; - background-color: #f6f6f6; - } - h1 { - border-bottom: 2px solid #e0e0e0; - font-weight: normal; - font-size: 150%; - color: #c0c0c0; - } - input, textarea { - border: 1px solid #d0d0d0; - } - th { - text-align: right; - font-weight: normal; - } - pre { - font-size: 110%; - color: #202020; - } - #footer { - color: #b0b0b0; - text-align: center; - font-size: 90%; - margin: 0 auto; - border-top: 1px solid #e0e0e0; - } - #footer a { - color: #c0c0c0; - } - --> - </style> - <script type="text/javascript"> - function select (state) - { - var cboxes = document.getElementsByTagName(\'input\'); - for (var i = 0; i < cboxes.length; i++) { - if (cboxes[i].type == "checkbox") { - if (state == "true") { - cboxes[i].checked = true; - } elseif (state == "false") { - cboxes[i].checked = false; - } elseif (state == "invert") { - cboxes[i].checked = !cboxes[i].checked; - } - } - } - } - </script> -</head> -<body> -<h1>' . $title . '</h1> -'; -} - -function make_footer () -{ - echo '<div id="footer"><a href="http://qbnz.com/highlighter/">GeSHi</a> © Nigel McNie, 2004, released under the GPL</div></body> -</html>'; -} - - -function get_var ( $var_name ) -{ - if ( isset($_GET[$var_name]) ) - { - return str_replace("\'", "'", $_GET[$var_name]); - } - elseif ( isset($_POST[$var_name]) ) - { - return str_replace("\'", "'", $_POST[$var_name]); - } - return null; -} - - - -// -// Unset everything -// -foreach ( $_REQUEST as $var ) -{ - unset($$var); -} -foreach ( array( - '_POST' => 'HTTP_POST_VARS', - '_GET' => 'HTTP_GET_VARS', - '_COOKIE' => 'HTTP_COOKIE_VARS', - '_SERVER' => 'HTTP_SERVER_VARS', - '_ENV' => 'HTTP_ENV_VARS', - '_FILES' => 'HTTP_POST_FILES') as $array => $other ) -{ - if ( !isset($$array) ) - { - $$array = $$other; - } - unset($$other); -} - - -// Get what step we're up to -$step = get_var('step'); - -if ( !$step || $step == 1 ) -{ - $errors = 0; - make_header('Step 1'); - echo "Welcome to the GeSHi CSS generator.<br /><pre>Searching for GeSHi... "; - - // Find GeSHi - $geshi_path = get_var('geshi-path'); - $geshi_lang_path = get_var('geshi-lang-path'); - - if(strstr($geshi_path, '..')) { - unset($geshi_path); - } - if(strstr($geshi_lang_path, '..')) { - unset($geshi_lang_path); - } - - if ( !$geshi_path ) - { - $geshi_path = '../geshi.php'; - } - if ( !$geshi_lang_path ) - { - $geshi_lang_path = '../geshi/'; - } - - if ( is_file($geshi_path) && is_readable($geshi_path) ) - { - // Get file contents and see if GeSHi is in here - $file = @file($geshi_path); - $contents = ''; - foreach ( $file as $line ) - { - $contents .= $line; - } - if ( strpos($contents, '<?php -/** - * GeSHi - Generic Syntax Highlighter') !== false ) - { - echo '<span style="color: green;">Found at ' . realpath($geshi_path) . '</span>'; - } - else - { - ++$errors; - $no_geshi_dot_php_error = true; - echo '<span style="color: red;">Not found</span>'; - } - } - else - { - ++$errors; - $no_geshi_dot_php_error = true; - echo '<span style="color: red;">Not found</span>'; - } - - // Find language files - echo "\nSearching for language files... "; - if ( is_readable($geshi_lang_path . 'css-gen.cfg') ) - { - - echo '<span style="color: green;">Found at ' . realpath($geshi_lang_path) . '</span>'; - } - else - { - ++$errors; - $no_lang_dir_error = true; - echo '<span style="color: red;">Not found</span>'; - } - echo "</pre>\n"; - - if ( $errors > 0 ) - { - // We're gonna have to ask for the paths... - echo 'Unfortunately CSSGen could not detect the following paths. Please input them and press "submit" to try again.'; - echo " -<form action=\"cssgen.php\" method=\"post\">"; - if ( $no_geshi_dot_php_error ) - { - echo " -<br />geshi.php: <input type=\"text\" name=\"geshi-path\" value=\"" . realpath('../geshi.php') . "\" size=\"50\" />"; - } - else - { - echo '<input type="hidden" name="geshi-path" value="' . htmlspecialchars($geshi_path) . '" />'; - } - if ( $no_lang_dir_error ) - { - echo " -<br />language files directory: <input type=\"text\" name=\"geshi-lang-path\" value=\"" . realpath('../geshi/') . "/\" size=\"50\" /> (should have a trailing slash)"; - } - else - { - echo '<input type="hidden" name="geshi-lang-path" value="' . $geshi_lang_path . '" />'; - } - - echo " -<br /><input type=\"submit\" value=\"Search\" /></form>"; - } - else - { - // no errors - echo continue form - echo 'Everything seems to be detected successfully. Use the button to continue. -<br /><br /><form action="cssgen.php?step=2" method="post"> -<input type="hidden" name="geshi-path" value="' . realpath($geshi_path) . '" /><input type="hidden" name="geshi-lang-path" value="' . realpath($geshi_lang_path) . '" /> -<input type="submit" value="Step 2" />'; - } - - make_footer(); -} -// Step 2 -elseif ( $step == 2 ) -{ - make_header('Step 2'); - - $geshi_path = get_var('geshi-path'); - $geshi_lang_path = get_var('geshi-lang-path'); - - $dh = opendir($geshi_lang_path); - $lang_files = array(); - $file = readdir($dh); - while ( $file !== false ) - { - if ( $file == '.' || $file == '..' || $file == 'CVS' || $file == 'css-gen.cfg' ) - { - $file = readdir($dh); - continue; - } - if(!strstr(file_get_contents($dh . DIRECTORY_SEPARATOR . $file), '$language_data')) { - $file = readdir($dh); - continue; - } - $lang_files[] = $file; - $file = readdir($dh); - } - closedir($dh); - sort($lang_files); - - // Now installed languages are in $lang_files - - echo '<form action="cssgen.php?step=3" method="post" id="step2"> -What languages are you wanting to make this stylesheet for?<br /><br /> -Detected languages:<br />'; - - foreach ( $lang_files as $lang ) - { - $lang = substr($lang, 0, strpos($lang, '.')); - if ($lang) { - echo "<input type=\"checkbox\" name=\"langs[$lang]\" checked=\"checked\" /> $lang<br />\n"; - } - } - - echo "Select: <a href=\"javascript:select('true')\">All</a>, <a href=\"javascript:select('false')\">None</a>, <a href=\"javascript:select('invert')\">Invert</a><br />\n"; - - echo 'If you\'d like any other languages not detected here to be supported, please enter -them here, one per line:<br /><textarea rows="4" cols="20" name="extra-langs"></textarea><br /> -'; - - echo '<br />Styles: -<table> - <tr><th>Style for the overall code block:</th><td><input type="text" name="overall" value="border: 1px dotted #a0a0a0; font-family: \'Courier New\', Courier, monospace; background-color: #f0f0f0; color: #0000bb;" /></td></tr> - <tr><th>Default Styles</th><td><input type="text" name="default-styles" value="font-weight:normal;background:transparent;color:#000; padding-left: 5px;" /></td></tr> - <tr><th>Keywords I (if, do, while etc)</th><td><input type="text" name="keywords-1" value="color: #a1a100;" /></td></tr> - <tr><th>Keywords II (null, true, false etc)</th><td><input type="text" name="keywords-2" value="color: #000; font-weight: bold;" /></td></tr> - <tr><th>Inbuilt Functions (echo, print etc)</th><td><input type="text" name="keywords-3" value="color: #000066;" /></td></tr> - <tr><th>Data Types (int, boolean etc)</th><td><input type="text" name="keywords-4" value="color: #f63333;" /></td></tr> - - <tr><th>Comments (//, <!-- --> etc)</th><td><input type="text" name="comments" value="color: #808080;" /></td></tr> - <tr><th>Escaped Characters (\n, \t etc)</th><td><input type="text" name="escaped-chars" value="color: #000033; font-weight: bold;" /></td></tr> - <tr><th>Brackets ( ([{}]) etc)</th><td><input type="text" name="brackets" value="color: #66cc66;" /></td></tr> - <tr><th>Strings ("foo" etc)</th><td><input type="text" name="strings" value="color: #ff0000;" /></td></tr> - <tr><th>Numbers (1, -54, 2.5 etc)</th><td><input type="text" name="numbers" value="color: #ff33ff;" /></td></tr> - <tr><th>Methods (Foo.bar() etc)</th><td><input type="text" name="methods" value="color: #006600;" /></td></tr> -</table>'; - - echo '<input type="hidden" name="geshi-path" value="' . realpath($geshi_path) . '" /><input type="hidden" name="geshi-lang-path" value="' . realpath($geshi_lang_path) . '" /> -<input type="submit" value="Step 3" /></form>'; - - make_footer(); -} -// Step 3 -elseif ( $step == 3 ) -{ - make_header('Step 3'); - echo '<p>Here is your completed stylesheet. Note that it may not be perfect - no regular expression styles are included for one thing, -you\'ll have to add those yourself (php and xml are just two languages that use them), and line numbers are not included, however -it includes most of the basic information.</p>'; - - // Make the stylesheet - $part_selector_1 = ''; - $part_selector_2 = ''; - $part_selector_3 = ''; - - $langs = get_var('langs'); - $extra_langs = trim(get_var('extra-langs')); - if ( $extra_langs != '' ) - { - $l = explode("\r\n", $extra_langs); - foreach ( $l as $lng ) - { - $langs[$lng] = true; - } - } - - - foreach ( $langs as $lang => $dummy ) - { - $part_selector_1 .= ".$lang {PART}, "; - $part_selector_2 .= ".$lang {PART1}, .$lang {PART2}, "; - $part_selector_3 .= ".$lang {PART1}, .$lang {PART2}, .$lang {PART3}, "; - } - $part_selector_1 = substr($part_selector_1, 0, -2); - $part_selector_2 = substr($part_selector_2, 0, -2); - $part_selector_3 = substr($part_selector_3, 0, -2); - - - $default_styles = get_var('default-styles'); - $ol_selector = str_replace('{PART}', 'ol', $part_selector_1); - $overall_styles = get_var('overall'); - $overall_selector = str_replace('{PART}', '', $part_selector_1); - - $stylesheet = "/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */"; - - if ( $overall != '' ) - { - $stylesheet .= "\n$overall_selector {{$overall_styles}}"; - } - if ( $default_styles != '' ) - { - $default_selector = str_replace(array('{PART1}', '{PART2}'), array('.de1', '.de2'), $part_selector_2); - $stylesheet .= "\n$default_selector {{$default_styles}}"; - } - - // Do keywords - $keywords_1 = get_var('keywords-1'); - $keyword_selector_1 = str_replace('{PART}', '.kw1', $part_selector_1); - if ( $keywords_1 != '' ) - { - $stylesheet .= "\n$keyword_selector_1 {{$keywords_1}}"; - } - - $keywords_2 = get_var('keywords-2'); - $keyword_selector_2 = str_replace('{PART}', '.kw2', $part_selector_1); - if ( $keywords_2 != '' ) - { - $stylesheet .= "\n$keyword_selector_2 {{$keywords_2}}"; - } - - $keywords_3 = get_var('keywords-3'); - $keyword_selector_3 = str_replace('{PART}', '.kw3', $part_selector_1); - if ( $keywords_3 != '' ) - { - $stylesheet .= "\n$keyword_selector_3 {{$keywords_3}}"; - } - - $keywords_4 = get_var('keywords-4'); - $keyword_selector_4 = str_replace('{PART}', '.kw4', $part_selector_1); - if ( $keywords_4 != '' ) - { - $stylesheet .= "\n$keyword_selector_4 {{$keywords_4}}"; - } - - // Do other lexics - $comments = get_var('comments'); - $comment_selector = str_replace(array('{PART1}', '{PART2}', '{PART3}'), array('.co1', '.co2', '.coMULTI'), $part_selector_3); - if ( $comments != '' ) - { - $stylesheet .= "\n$comment_selector {{$comments}}"; - } - - $esc = get_var('escaped-chars'); - $esc_selector = str_replace('{PART}', '.es0', $part_selector_1); - if ( $esc != '' ) - { - $stylesheet .= "\n$esc_selector {{$esc}}"; - } - - $brackets = get_var('brackets'); - $brk_selector = str_replace('{PART}', '.br0', $part_selector_1); - if ( $brackets != '' ) - { - $stylesheet .= "\n$brk_selector {{$brackets}}"; - } - - $strings = get_var('strings'); - $string_selector = str_replace('{PART}', '.st0', $part_selector_1); - if ( $strings != '' ) - { - $stylesheet .= "\n$string_selector {{$strings}}"; - } - - $numbers = get_var('numbers'); - $num_selector = str_replace('{PART}', '.nu0', $part_selector_1); - if ( $numbers != '' ) - { - $stylesheet .= "\n$num_selector {{$numbers}}"; - } - - $methods = get_var('methods'); - $method_selector = str_replace('{PART}', '.me0', $part_selector_1); - if ( $methods != '' ) - { - $stylesheet .= "\n$method_selector {{$methods}}"; - } - - echo "<pre>$stylesheet</pre>"; - - make_footer(); -} diff --git a/extensions/SyntaxHighlight_GeSHi/geshi/contrib/cssgen2.php b/extensions/SyntaxHighlight_GeSHi/geshi/contrib/cssgen2.php deleted file mode 100644 index cc3c39cb..00000000 --- a/extensions/SyntaxHighlight_GeSHi/geshi/contrib/cssgen2.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php -/** - * A simple script which outputs the CSS classes for all languages - * supported by GeSHi. You can access it directly to download - * the CSS file. On *NIX you can also do a simple `php cssgen.php > geshi.css`. - * - * This file is part of GeSHi. - * - * GeSHi is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GeSHi is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GeSHi; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * @package geshi - * @subpackage contrib - * @author revulo <revulon@gmail.com> - * @copyright 2008 revulo - * @license http://gnu.org/copyleft/gpl.html GNU GPL - * - */ - -require dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'geshi.php'; -$geshi = new GeSHi; - -$languages = array(); -if ($handle = opendir($geshi->language_path)) { - while (($file = readdir($handle)) !== false) { - $pos = strpos($file, '.'); - if ($pos > 0 && substr($file, $pos) == '.php') { - $languages[] = substr($file, 0, $pos); - } - } - closedir($handle); -} -sort($languages); - -header('Content-Type: application/octet-stream'); -header('Content-Disposition: attachment; filename="geshi.css"'); - -echo "/**\n". - " * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann\n" . - " * (http://qbnz.com/highlighter/ and http://geshi.org/)\n". - " */\n"; - -foreach ($languages as $language) { - $geshi->set_language($language); - // note: the false argument is required for stylesheet generators, see API documentation - $css = $geshi->get_stylesheet(false); - echo preg_replace('/^\/\*\*.*?\*\//s', '', $css); -} diff --git a/extensions/SyntaxHighlight_GeSHi/geshi/contrib/example.php b/extensions/SyntaxHighlight_GeSHi/geshi/contrib/example.php deleted file mode 100644 index 1ad923d0..00000000 --- a/extensions/SyntaxHighlight_GeSHi/geshi/contrib/example.php +++ /dev/null @@ -1,217 +0,0 @@ -<?php -/** - * GeSHi example script - * - * Just point your browser at this script (with geshi.php in the parent directory, - * and the language files in subdirectory "../geshi/") - * - * @author Nigel McNie - * @version $Id$ - */ -header('Content-Type: text/html; charset=utf-8'); - -error_reporting(E_ALL); - -// Rudimentary checking of where GeSHi is. In a default install it will be in ../, but -// it could be in the current directory if the include_path is set. There's nowhere else -// we can reasonably guess. -if (is_readable('../geshi.php')) { - $path = '../'; -} elseif (is_readable('geshi.php')) { - $path = './'; -} else { - die('Could not find geshi.php - make sure it is in your include path!'); -} -require $path . 'geshi.php'; - -$fill_source = false; -if (isset($_POST['submit'])) { - if (get_magic_quotes_gpc()) { - $_POST['source'] = stripslashes($_POST['source']); - } - if (!strlen(trim($_POST['source']))) { - $_POST['language'] = preg_replace('#[^a-zA-Z0-9\-_]#', '', $_POST['language']); - $_POST['source'] = implode('', @file($path . 'geshi/' . $_POST['language'] . '.php')); - $_POST['language'] = 'php'; - } else { - $fill_source = true; - } - - // Here's a free demo of how GeSHi works. - - // First the initialisation: source code to highlight and the language to use. Make sure - // you sanitise correctly if you use $_POST of course - this very script has had a security - // advisory against it in the past because of this. Please try not to use this script on a - // live site. - $geshi = new GeSHi($_POST['source'], $_POST['language']); - - // Use the PRE_VALID header. This means less output source since we don't have to output - // everywhere. Of course it also means you can't set the tab width. - // HEADER_PRE_VALID puts the <pre> tag inside the list items (<li>) thus producing valid HTML markup. - // HEADER_PRE puts the <pre> tag around the list (<ol>) which is invalid in HTML 4 and XHTML 1 - // HEADER_DIV puts a <div> tag arount the list (valid!) but needs to replace whitespaces with   - // thus producing much larger overhead. You can set the tab width though. - $geshi->set_header_type(GESHI_HEADER_PRE_VALID); - - // Enable CSS classes. You can use get_stylesheet() to output a stylesheet for your code. Using - // CSS classes results in much less output source. - $geshi->enable_classes(); - - // Enable line numbers. We want fancy line numbers, and we want every 5th line number to be fancy - $geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS, 5); - - // Set the style for the PRE around the code. The line numbers are contained within this box (not - // XHTML compliant btw, but if you are liberally minded about these things then you'll appreciate - // the reduced source output). - $geshi->set_overall_style('font: normal normal 90% monospace; color: #000066; border: 1px solid #d0d0d0; background-color: #f0f0f0;', false); - - // Set the style for line numbers. In order to get style for line numbers working, the <li> element - // is being styled. This means that the code on the line will also be styled, and most of the time - // you don't want this. So the set_code_style reverts styles for the line (by using a <div> on the line). - // So the source output looks like this: - // - // <pre style="[set_overall_style styles]"><ol> - // <li style="[set_line_style styles]"><div style="[set_code_style styles]>...</div></li> - // ... - // </ol></pre> - $geshi->set_line_style('color: #003030;', 'font-weight: bold; color: #006060;', true); - $geshi->set_code_style('color: #000020;', true); - - // Styles for hyperlinks in the code. GESHI_LINK for default styles, GESHI_HOVER for hover style etc... - // note that classes must be enabled for this to work. - $geshi->set_link_styles(GESHI_LINK, 'color: #000060;'); - $geshi->set_link_styles(GESHI_HOVER, 'background-color: #f0f000;'); - - // Use the header/footer functionality. This puts a div with content within the PRE element, so it is - // affected by the styles set by set_overall_style. So if the PRE has a border then the header/footer will - // appear inside it. - $geshi->set_header_content('<SPEED> <TIME> GeSHi © 2004-2007, Nigel McNie, 2007-2008 Benny Baumann. View source of example.php for example of using GeSHi'); - $geshi->set_header_content_style('font-family: sans-serif; color: #808080; font-size: 70%; font-weight: bold; background-color: #f0f0ff; border-bottom: 1px solid #d0d0d0; padding: 2px;'); - - // You can use <TIME> and <VERSION> as placeholders - $geshi->set_footer_content('Parsed in <TIME> seconds at <SPEED>, using GeSHi <VERSION>'); - $geshi->set_footer_content_style('font-family: sans-serif; color: #808080; font-size: 70%; font-weight: bold; background-color: #f0f0ff; border-top: 1px solid #d0d0d0; padding: 2px;'); -} else { - // make sure we don't preselect any language - $_POST['language'] = null; -} -?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head> - <title>GeSHi examples</title> - <style type="text/css"> - <!-- - <?php - if (isset($_POST['submit'])) { - // Output the stylesheet. Note it doesn't output the <style> tag - echo $geshi->get_stylesheet(true); - } - ?> - html { - background-color: #f0f0f0; - } - body { - font-family: Verdana, Arial, sans-serif; - margin: 10px; - border: 2px solid #e0e0e0; - background-color: #fcfcfc; - padding: 5px; - } - h2 { - margin: .1em 0 .2em .5em; - border-bottom: 1px solid #b0b0b0; - color: #b0b0b0; - font-weight: normal; - font-size: 150%; - } - h3 { - margin: .1em 0 .2em .5em; - color: #b0b0b0; - font-weight: normal; - font-size: 120%; - } - #footer { - text-align: center; - font-size: 80%; - color: #a9a9a9; - } - #footer a { - color: #9999ff; - } - textarea { - border: 1px solid #b0b0b0; - font-size: 90%; - color: #333; - margin-left: 20px; - } - select, input { - margin-left: 20px; - } - p { - font-size: 90%; - margin-left: .5em; - } - --> - </style> -</head> -<body> -<h2>GeSHi Example Script</h2> -<p>To use this script, make sure that <strong>geshi.php</strong> is in the parent directory or in your -include_path, and that the language files are in a subdirectory of GeSHi's directory called <strong>geshi/</strong>.</p> -<p>Enter your source and a language to highlight the source in and submit, or just choose a language to -have that language file highlighted in PHP.</p> -<?php -if (isset($_POST['submit'])) { - // The fun part :) - echo $geshi->parse_code(); - echo '<hr />'; -} -?> -<form action="?" method="post"> -<h3>Source to highlight</h3> -<p> -<textarea rows="10" cols="60" name="source" id="source"><?php echo $fill_source ? htmlspecialchars($_POST['source']) : '' ?></textarea> -</p> -<h3>Choose a language</h3> -<p> -<select name="language" id="language"> -<?php -if (!($dir = @opendir(dirname(__FILE__) . '/geshi'))) { - if (!($dir = @opendir(dirname(__FILE__) . '/../geshi'))) { - echo '<option>No languages available!</option>'; - } -} -$languages = array(); -while ($file = readdir($dir)) { - if ( $file[0] == '.' || strpos($file, '.', 1) === false) { - continue; - } - $lang = substr($file, 0, strpos($file, '.')); - $languages[] = $lang; -} -closedir($dir); -sort($languages); -foreach ($languages as $lang) { - if (isset($_POST['language']) && $_POST['language'] == $lang) { - $selected = 'selected="selected"'; - } else { - $selected = ''; - } - echo '<option value="' . $lang . '" '. $selected .'>' . $lang . "</option>\n"; -} - -?> -</select> -</p> -<p> -<input type="submit" name="submit" value="Highlight Source" /> -<input type="submit" name="clear" onclick="document.getElementById('source').value='';document.getElementById('language').value='';return false" value="clear" /> -</p> -</form> -<div id="footer">GeSHi © Nigel McNie, 2004, released under the GNU GPL<br /> -For a better demonstration, check out the <a href="http://qbnz.com/highlighter/demo.php">online demo</a> -</div> -</body> -</html> diff --git a/extensions/SyntaxHighlight_GeSHi/geshi/contrib/langcheck.php b/extensions/SyntaxHighlight_GeSHi/geshi/contrib/langcheck.php deleted file mode 100644 index ce5aed1f..00000000 --- a/extensions/SyntaxHighlight_GeSHi/geshi/contrib/langcheck.php +++ /dev/null @@ -1,778 +0,0 @@ -<?php -/** - * GeSHi language file validation script - * - * Just point your browser at this script (with geshi.php in the parent directory) - * and the language files in subdirectory "../geshi/" are being validated - * - * CLI mode is supported - * - * @author Benny Baumann - * @version $Id$ - */ -header('Content-Type: text/html; charset=utf-8'); - -set_time_limit(0); -error_reporting(E_ALL); -$time_start = explode(' ', microtime()); - -function colorize($level, $string) { - static $colors, $end; - if ( !isset($colors) ) { - if ( PHP_SAPI != 'cli' ) { - $end = '</span>'; - $colors = array( - TYPE_NOTICE => '<span style="color:#080;font-weight:bold;">', - TYPE_WARNING => '<span style="color:#CC0; font-weight: bold;">', - TYPE_ERROR => '<span style="color:#F00; font-weight: bold;">', - TYPE_OK => '<span style="color: #080; font-weight: bold;">' - ); - } else { - $end = chr(27).'[0m'; - $colors = array( - TYPE_NOTICE => chr(27).'[1m', - TYPE_WARNING => chr(27).'[1;33m', - TYPE_ERROR => chr(27).'[1;31m', - TYPE_OK => chr(27).'[1;32m' - ); - } - } - - if ( !isset($colors[$level]) ) { - trigger_error("no colors for level $level", E_USER_ERROR); - } - - return $colors[$level].$string.$end; -} - -define ('TYPE_NOTICE', 0); -define ('TYPE_WARNING', 1); -define ('TYPE_ERROR', 2); -define ('TYPE_OK', 3); - -$error_abort = false; -$error_cache = array(); -function output_error_cache(){ - global $error_cache; - - if(count($error_cache)) { - echo colorize(TYPE_ERROR, "Failed"); - if ( PHP_SAPI == 'cli' ) { - echo "\n\n"; - } else { - echo "<br /><ol>\n"; - } - foreach($error_cache as $error_msg) { - if ( PHP_SAPI == 'cli' ) { - echo "\n"; - } else { - echo "<li>"; - } - switch($error_msg['t']) { - case TYPE_NOTICE: - $msg = 'NOTICE'; - break; - case TYPE_WARNING: - $msg = 'WARNING'; - break; - case TYPE_ERROR: - $msg = 'ERROR'; - break; - } - echo colorize($error_msg['t'], $msg); - if ( PHP_SAPI == 'cli' ) { - echo "\t" . $error_msg['m']; - } else { - echo " " . $error_msg['m'] . "</li>"; - } - } - if ( PHP_SAPI == 'cli' ) { - echo "\n"; - } else { - echo "</ol>\n"; - } - } else { - echo colorize(TYPE_OK, "OK"); - if ( PHP_SAPI == 'cli' ) { - echo "\n"; - } else { - echo "\n<br />"; - } - } - echo "\n"; - - $error_cache = array(); -} - -function report_error($type, $message) { - global $error_cache, $error_abort; - - $error_cache[] = array('t' => $type, 'm' => $message); - if(TYPE_ERROR == $type) { - $error_abort = true; - } -} - -function dupfind_strtolower(&$value){ - $value = strtolower($value); -} - -if ( PHP_SAPI != 'cli' ) { ?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head> - <title>GeSHi Language File Validation Script</title> - <style type="text/css"> - <!-- - html { - background-color: #f0f0f0; - } - body { - font-family: Verdana, Arial, sans-serif; - margin: 10px; - border: 2px solid #e0e0e0; - background-color: #fcfcfc; - padding: 5px; - font-size: 10pt; - } - h2 { - margin: .1em 0 .2em .5em; - border-bottom: 1px solid #b0b0b0; - color: #b0b0b0; - font-weight: normal; - font-size: 150%; - } - h3 { - margin: .1em 0 .2em .5em; - color: #b0b0b0; - font-weight: normal; - font-size: 120%; - } - #footer { - text-align: center; - font-size: 80%; - color: #a9a9a9; - } - #footer a { - color: #9999ff; - } - textarea { - border: 1px solid #b0b0b0; - font-size: 90%; - color: #333; - margin-left: 20px; - } - select, input { - margin-left: 20px; - } - p { - font-size: 90%; - margin-left: .5em; - } - --> - </style> -</head> -<body> -<h2>GeSHi Language File Validation Script</h2> -<p>To use this script, make sure that <strong>geshi.php</strong> is in the -parent directory or in your include_path, and that the language files are in a -subdirectory of GeSHi's directory called <strong>geshi/</strong>.</p> -<p>Everything else will be done by this script automatically. After the script -finished you should see messages of what could cause trouble with GeSHi or where -your language files can be improved. Please be patient, as this might take some time.</p> - -<ol> -<li>Checking where to find GeSHi installation ...<?php -} else { ?> -<?php echo colorize(TYPE_NOTICE, "#### GeSHi Language File Validation Script ####") ?> - - -To use this script, make sure that <?php echo colorize(TYPE_NOTICE, "geshi.php"); ?> is in the -parent directory or in your include_path, and that the language files are in a -subdirectory of GeSHi's directory called <?php echo colorize(TYPE_NOTICE, "geshi/"); ?>. - -Everything else will be done by this script automatically. After the script -finished you should see messages of what could cause trouble with GeSHi or where -your language files can be improved. Please be patient, as this might take some time. - - -Checking where to find GeSHi installation ...<?php echo "\t"; -} - -// Rudimentary checking of where GeSHi is. In a default install it will be in ../, but -// it could be in the current directory if the include_path is set. There's nowhere else -// we can reasonably guess. -if (is_readable('../geshi.php')) { - $path = '../'; -} elseif (is_readable('geshi.php')) { - $path = './'; -} else { - report_error(TYPE_ERROR, 'Could not find geshi.php - make sure it is in your include path!'); -} - -if(!$error_abort) { - require $path . 'geshi.php'; - - if(!class_exists('GeSHi')) { - report_error(TYPE_ERROR, 'The GeSHi class was not found, although it seemed we loaded the correct file!'); - } -} - -if(!$error_abort) { - if(!defined('GESHI_LANG_ROOT')) { - report_error(TYPE_ERROR, 'There\'s no information present on where to find the language files!'); - } elseif(!is_dir(GESHI_LANG_ROOT)) { - report_error(TYPE_ERROR, 'The path "'.GESHI_LANG_ROOT.'" given, does not ressemble a directory!'); - } elseif(!is_readable(GESHI_LANG_ROOT)) { - report_error(TYPE_ERROR, 'The path "'.GESHI_LANG_ROOT.'" is not readable to this script!'); - } -} - -output_error_cache(); - -if(!$error_abort) { - if ( PHP_SAPI == 'cli' ) { - echo "Listing available language files ...\t\t"; - } else { - echo "</li>\n<li>Listing available language files ... "; - } - - if (!($dir = @opendir(GESHI_LANG_ROOT))) { - report_error(TYPE_ERROR, 'Error requesting listing for available language files!'); - } - - $languages = array(); - - if(!$error_abort) { - while ($file = readdir($dir)) { - if (!$file || $file[0] == '.' || strpos($file, '.php') === false) { - continue; - } - $lang = substr($file, 0, strpos($file, '.')); - if(4 != strlen($file) - strlen($lang)) { - continue; - } - $languages[] = $lang; - } - closedir($dir); - } - - $languages = array_unique($languages); - sort($languages); - - if(!count($languages)) { - report_error(TYPE_WARNING, 'Unable to locate any usable language files in "'.GESHI_LANG_ROOT.'"!'); - } - - output_error_cache(); -} - -if ( PHP_SAPI == 'cli' ) { - if (isset($_SERVER['argv'][1]) && in_array($_SERVER['argv'][1], $languages)) { - $languages = array($_SERVER['argv'][1]); - } -} else { - if (isset($_REQUEST['show']) && in_array($_REQUEST['show'], $languages)) { - $languages = array($_REQUEST['show']); - } -} - -if(!$error_abort) { - foreach ($languages as $lang) { - - if ( PHP_SAPI == 'cli' ) { - echo "Validating language file for '$lang' ...\t\t"; - } else { - echo "</li>\n<li>Validating language file for '$lang' ... "; - } - - $langfile = GESHI_LANG_ROOT . $lang . '.php'; - - $language_data = array(); - - if(!is_file($langfile)) { - report_error(TYPE_ERROR, 'The path "' .$langfile. '" does not ressemble a regular file!'); - } elseif(!is_readable($langfile)) { - report_error(TYPE_ERROR, 'Cannot read file "' .$langfile. '"!'); - } else { - $langfile_content = file_get_contents($langfile); - if(preg_match("/\?>(?:\r?\n|\r(?!\n)){2,}\Z/", $langfile_content)) { - report_error(TYPE_ERROR, 'Language file contains trailing empty lines at EOF!'); - } - if(preg_match("/\?>(?:\r?\n|\r(?!\n))?\Z/", $langfile_content)) { - report_error(TYPE_ERROR, 'Language file contains an PHP end marker at EOF!'); - } - if(!preg_match("/(?:\r?\n|\r(?!\n))\Z/", $langfile_content)) { - report_error(TYPE_ERROR, 'Language file contains no newline at EOF!'); - } - if(preg_match("/(\r?\n|\r(?!\n))\\1\Z/", $langfile_content)) { - report_error(TYPE_ERROR, 'Language file contains trailing empty line before EOF!'); - } - if(preg_match("/[\x20\t]$/m", $langfile_content)) { - report_error(TYPE_ERROR, 'Language file contains trailing whitespace at EOL!'); - } - if(preg_match("/\t/", $langfile_content)) { - report_error(TYPE_NOTICE, 'Language file contains unescaped tabulator chars (probably for indentation)!'); - } - if(preg_match('/^(?: )*(?! )(?! \*) /m', $langfile_content)) { - report_error(TYPE_NOTICE, 'Language file contains irregular indentation (other than 4 spaces per indentation level)!'); - } - - if(!preg_match("/\/\*\*((?!\*\/).)*?Author:((?!\*\/).)*?\*\//s", $langfile_content)) { - report_error(TYPE_WARNING, 'Language file does not contain a specification of an author!'); - } - if(!preg_match("/\/\*\*((?!\*\/).)*?Copyright:((?!\*\/).)*?\*\//s", $langfile_content)) { - report_error(TYPE_WARNING, 'Language file does not contain a specification of the copyright!'); - } - if(!preg_match("/\/\*\*((?!\*\/).)*?Release Version:((?!\*\/).)*?\*\//s", $langfile_content)) { - report_error(TYPE_WARNING, 'Language file does not contain a specification of the release version!'); - } - if(!preg_match("/\/\*\*((?!\*\/).)*?Date Started:((?!\*\/).)*?\*\//s", $langfile_content)) { - report_error(TYPE_WARNING, 'Language file does not contain a specification of the date it was started!'); - } - if(!preg_match("/\/\*\*((?!\*\/).)*?This file is part of GeSHi\.((?!\*\/).)*?\*\//s", $langfile_content)) { - report_error(TYPE_WARNING, 'Language file does not state that it belongs to GeSHi!'); - } - if(!preg_match("/\/\*\*((?!\*\/).)*?language file for GeSHi\.((?!\*\/).)*?\*\//s", $langfile_content)) { - report_error(TYPE_WARNING, 'Language file does not state that it is a language file for GeSHi!'); - } - if(!preg_match("/\/\*\*((?!\*\/).)*?GNU General Public License((?!\*\/).)*?\*\//s", $langfile_content)) { - report_error(TYPE_WARNING, 'Language file does not state that it is provided under the terms of the GNU GPL!'); - } - - unset($langfile_content); - - include $langfile; - - if(!isset($language_data)) { - report_error(TYPE_ERROR, 'Language file does not contain a $language_data structure to check!'); - } elseif (!is_array($language_data)) { - report_error(TYPE_ERROR, 'Language file contains a $language_data structure which is not an array!'); - } - } - - if(!$error_abort) { - if(!isset($language_data['LANG_NAME'])) { - report_error(TYPE_ERROR, 'Language file contains no $language_data[\'LANG_NAME\'] specification!'); - } elseif (!is_string($language_data['LANG_NAME'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'LANG_NAME\'] specification which is not a string!'); - } - - if(!isset($language_data['COMMENT_SINGLE'])) { - report_error(TYPE_ERROR, 'Language file contains no $language_data[\'COMMENT_SIGNLE\'] structure to check!'); - } elseif (!is_array($language_data['COMMENT_SINGLE'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'COMMENT_SINGLE\'] structure which is not an array!'); - } - - if(!isset($language_data['COMMENT_MULTI'])) { - report_error(TYPE_ERROR, 'Language file contains no $language_data[\'COMMENT_MULTI\'] structure to check!'); - } elseif (!is_array($language_data['COMMENT_MULTI'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'COMMENT_MULTI\'] structure which is not an array!'); - } - - if(isset($language_data['COMMENT_REGEXP'])) { - if (!is_array($language_data['COMMENT_REGEXP'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'COMMENT_REGEXP\'] structure which is not an array!'); - } - } - - if(!isset($language_data['QUOTEMARKS'])) { - report_error(TYPE_ERROR, 'Language file contains no $language_data[\'QUOTEMARKS\'] structure to check!'); - } elseif (!is_array($language_data['QUOTEMARKS'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'QUOTEMARKS\'] structure which is not an array!'); - } - - if(isset($language_data['HARDQUOTE'])) { - if (!is_array($language_data['HARDQUOTE'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'HARDQUOTE\'] structure which is not an array!'); - } - } - - if(!isset($language_data['ESCAPE_CHAR'])) { - report_error(TYPE_ERROR, 'Language file contains no $language_data[\'ESCAPE_CHAR\'] specification to check!'); - } elseif (!is_string($language_data['ESCAPE_CHAR'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'ESCAPE_CHAR\'] specification which is not a string!'); - } elseif (1 < strlen($language_data['ESCAPE_CHAR'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'ESCAPE_CHAR\'] specification is not empty or exactly one char!'); - } - - if(!isset($language_data['CASE_KEYWORDS'])) { - report_error(TYPE_ERROR, 'Language file contains no $language_data[\'CASE_KEYWORDS\'] specification!'); - } elseif (!is_int($language_data['CASE_KEYWORDS'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'CASE_KEYWORDS\'] specification which is not an integer!'); - } elseif (GESHI_CAPS_NO_CHANGE != $language_data['CASE_KEYWORDS'] && - GESHI_CAPS_LOWER != $language_data['CASE_KEYWORDS'] && - GESHI_CAPS_UPPER != $language_data['CASE_KEYWORDS']) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'CASE_KEYWORDS\'] specification which is neither of GESHI_CAPS_NO_CHANGE, GESHI_CAPS_LOWER nor GESHI_CAPS_UPPER!'); - } - - if(!isset($language_data['KEYWORDS'])) { - report_error(TYPE_ERROR, 'Language file contains no $language_data[\'KEYWORDS\'] structure to check!'); - } elseif (!is_array($language_data['KEYWORDS'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'KEYWORDS\'] structure which is not an array!'); - } else { - foreach($language_data['KEYWORDS'] as $kw_key => $kw_value) { - if(!is_integer($kw_key)) { - report_error(TYPE_WARNING, "Language file contains an key '$kw_key' in \$language_data['KEYWORDS'] that is not integer!"); - } elseif (!is_array($kw_value)) { - report_error(TYPE_ERROR, "Language file contains a \$language_data['KEYWORDS']['$kw_value'] structure which is not an array!"); - } - } - } - - if(!isset($language_data['SYMBOLS'])) { - report_error(TYPE_ERROR, 'Language file contains no $language_data[\'SYMBOLS\'] structure to check!'); - } elseif (!is_array($language_data['SYMBOLS'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'SYMBOLS\'] structure which is not an array!'); - } - - if(!isset($language_data['CASE_SENSITIVE'])) { - report_error(TYPE_ERROR, 'Language file contains no $language_data[\'CASE_SENSITIVE\'] structure to check!'); - } elseif (!is_array($language_data['CASE_SENSITIVE'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'CASE_SENSITIVE\'] structure which is not an array!'); - } else { - foreach($language_data['CASE_SENSITIVE'] as $cs_key => $cs_value) { - if(!is_integer($cs_key)) { - report_error(TYPE_WARNING, "Language file contains an key '$cs_key' in \$language_data['CASE_SENSITIVE'] that is not integer!"); - } elseif (!is_bool($cs_value)) { - report_error(TYPE_ERROR, "Language file contains a Case Sensitivity specification for \$language_data['CASE_SENSITIVE']['$cs_value'] which is not a boolean!"); - } - } - } - - if(!isset($language_data['URLS'])) { - report_error(TYPE_ERROR, 'Language file contains no $language_data[\'URLS\'] structure to check!'); - } elseif (!is_array($language_data['URLS'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'URLS\'] structure which is not an array!'); - } else { - foreach($language_data['URLS'] as $url_key => $url_value) { - if(!is_integer($url_key)) { - report_error(TYPE_WARNING, "Language file contains an key '$url_key' in \$language_data['URLS'] that is not integer!"); - } elseif (!is_string($url_value)) { - report_error(TYPE_ERROR, "Language file contains a Documentation URL specification for \$language_data['URLS']['$url_value'] which is not a string!"); - } elseif (preg_match('#&([^;]*(=|$))#U', $url_value)) { - report_error(TYPE_ERROR, "Language file contains unescaped ampersands (&) in \$language_data['URLS']!"); - } - } - } - - if(!isset($language_data['OOLANG'])) { - report_error(TYPE_ERROR, 'Language file contains no $language_data[\'OOLANG\'] specification!'); - } elseif (!is_int($language_data['OOLANG']) && !is_bool($language_data['OOLANG'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'OOLANG\'] specification which is neither boolean nor integer!'); - } elseif (false !== $language_data['OOLANG'] && - true !== $language_data['OOLANG'] && - 2 !== $language_data['OOLANG']) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'OOLANG\'] specification which is neither of false, true or 2!'); - } - - if(!isset($language_data['OBJECT_SPLITTERS'])) { - report_error(TYPE_ERROR, 'Language file contains no $language_data[\'OBJECT_SPLITTERS\'] structure to check!'); - } elseif (!is_array($language_data['OBJECT_SPLITTERS'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'OBJECT_SPLITTERS\'] structure which is not an array!'); - } - - if(!isset($language_data['REGEXPS'])) { - report_error(TYPE_ERROR, 'Language file contains no $language_data[\'REGEXPS\'] structure to check!'); - } elseif (!is_array($language_data['REGEXPS'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'REGEXPS\'] structure which is not an array!'); - } - - if(!isset($language_data['STRICT_MODE_APPLIES'])) { - report_error(TYPE_ERROR, 'Language file contains no $language_data[\'STRICT_MODE_APPLIES\'] specification!'); - } elseif (!is_int($language_data['STRICT_MODE_APPLIES'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'STRICT_MODE_APPLIES\'] specification which is not an integer!'); - } elseif (GESHI_MAYBE != $language_data['STRICT_MODE_APPLIES'] && - GESHI_ALWAYS != $language_data['STRICT_MODE_APPLIES'] && - GESHI_NEVER != $language_data['STRICT_MODE_APPLIES']) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'STRICT_MODE_APPLIES\'] specification which is neither of GESHI_MAYBE, GESHI_ALWAYS nor GESHI_NEVER!'); - } - - if(!isset($language_data['SCRIPT_DELIMITERS'])) { - report_error(TYPE_ERROR, 'Language file contains no $language_data[\'SCRIPT_DELIMITERS\'] structure to check!'); - } elseif (!is_array($language_data['SCRIPT_DELIMITERS'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'SCRIPT_DELIMITERS\'] structure which is not an array!'); - } - - if(!isset($language_data['HIGHLIGHT_STRICT_BLOCK'])) { - report_error(TYPE_ERROR, 'Language file contains no $language_data[\'HIGHLIGHT_STRICT_BLOCK\'] structure to check!'); - } elseif (!is_array($language_data['HIGHLIGHT_STRICT_BLOCK'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'HIGHLIGHT_STRICT_BLOCK\'] structure which is not an array!'); - } - - if(isset($language_data['TAB_WIDTH'])) { - if (!is_int($language_data['TAB_WIDTH'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'TAB_WIDTH\'] specification which is not an integer!'); - } elseif (1 > $language_data['TAB_WIDTH']) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'TAB_WIDTH\'] specification which is less than 1!'); - } - } - - if(isset($language_data['PARSER_CONTROL'])) { - if (!is_array($language_data['PARSER_CONTROL'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'PARSER_CONTROL\'] structure which is not an array!'); - } - } - - if(!isset($language_data['STYLES'])) { - report_error(TYPE_ERROR, 'Language file contains no $language_data[\'STYLES\'] structure to check!'); - } elseif (!is_array($language_data['STYLES'])) { - report_error(TYPE_ERROR, 'Language file contains a $language_data[\'STYLES\'] structure which is not an array!'); - } else { - $style_arrays = array('KEYWORDS', 'COMMENTS', 'ESCAPE_CHAR', - 'BRACKETS', 'STRINGS', 'NUMBERS', 'METHODS', 'SYMBOLS', - 'REGEXPS', 'SCRIPT'); - foreach($style_arrays as $style_kind) { - if(!isset($language_data['STYLES'][$style_kind])) { - report_error(TYPE_ERROR, "Language file contains no \$language_data['STYLES']['$style_kind'] structure to check!"); - } elseif (!is_array($language_data['STYLES'][$style_kind])) { - report_error(TYPE_ERROR, "Language file contains a \$language_data['STYLES\']['$style_kind'] structure which is not an array!"); - } else { - foreach($language_data['STYLES'][$style_kind] as $sk_key => $sk_value) { - if(!is_int($sk_key) && ('COMMENTS' != $style_kind && 'MULTI' != $sk_key) - && !(('STRINGS' == $style_kind || 'ESCAPE_CHAR' == $style_kind) && 'HARD' == $sk_key)) { - report_error(TYPE_WARNING, "Language file contains an key '$sk_key' in \$language_data['STYLES']['$style_kind'] that is not integer!"); - } elseif (!is_string($sk_value)) { - report_error(TYPE_WARNING, "Language file contains a CSS specification for \$language_data['STYLES']['$style_kind'][$key] which is not a string!"); - } - } - } - } - - unset($style_arrays); - } - } - - if(!$error_abort) { - //Initial sanity checks survived? --> Let's dig deeper! - foreach($language_data['KEYWORDS'] as $key => $keywords) { - if(!isset($language_data['CASE_SENSITIVE'][$key])) { - report_error(TYPE_ERROR, "Language file contains no \$language_data['CASE_SENSITIVE'] specification for keyword group $key!"); - } - if(!isset($language_data['URLS'][$key])) { - report_error(TYPE_ERROR, "Language file contains no \$language_data['URLS'] specification for keyword group $key!"); - } - if(empty($keywords)) { - report_error(TYPE_WARNING, "Language file contains an empty keyword list in \$language_data['KEYWORDS'] for group $key!"); - } - foreach($keywords as $id => $kw) { - if(!is_string($kw)) { - report_error(TYPE_WARNING, "Language file contains an non-string entry at \$language_data['KEYWORDS'][$key][$id]!"); - } elseif (!strlen($kw)) { - report_error(TYPE_ERROR, "Language file contains an empty string entry at \$language_data['KEYWORDS'][$key][$id]!"); - } elseif (preg_match('/^([\(\)\{\}\[\]\^=.,:;\-+\*\/%\$\"\'\?]|&[\w#]\w*;)+$/i', $kw)) { - report_error(TYPE_NOTICE, "Language file contains an keyword ('$kw') at \$language_data['KEYWORDS'][$key][$id] which seems to be better suited for the symbols section!"); - } - } - if(isset($language_data['CASE_SENSITIVE'][$key]) && !$language_data['CASE_SENSITIVE'][$key]) { - array_walk($keywords, 'dupfind_strtolower'); - } - if(count($keywords) != count(array_unique($keywords))) { - $kw_diffs = array_count_values($keywords); - foreach($kw_diffs as $kw => $kw_count) { - if($kw_count > 1) { - report_error(TYPE_WARNING, "Language file contains per-group duplicate keyword '$kw' in \$language_data['KEYWORDS'][$key]!"); - } - } - } - } - - $disallowed_before = "(?<![a-zA-Z0-9\$_\|\#;>|^&"; - $disallowed_after = "(?![a-zA-Z0-9_\|%\\-&;"; - - foreach($language_data['KEYWORDS'] as $key => $keywords) { - foreach($language_data['KEYWORDS'] as $key2 => $keywords2) { - if($key2 <= $key) { - continue; - } - $kw_diffs = array_intersect($keywords, $keywords2); - foreach($kw_diffs as $kw) { - if(isset($language_data['PARSER_CONTROL']['KEYWORDS'])) { - //Check the precondition\post-cindition for the involved keyword groups - $g1_pre = $disallowed_before; - $g2_pre = $disallowed_before; - $g1_post = $disallowed_after; - $g2_post = $disallowed_after; - if(isset($language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'])) { - $g1_pre = $language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE']; - $g2_pre = $language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE']; - } - if(isset($language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'])) { - $g1_post = $language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER']; - $g2_post = $language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER']; - } - - if(isset($language_data['PARSER_CONTROL']['KEYWORDS'][$key]['DISALLOWED_BEFORE'])) { - $g1_pre = $language_data['PARSER_CONTROL']['KEYWORDS'][$key]['DISALLOWED_BEFORE']; - } - if(isset($language_data['PARSER_CONTROL']['KEYWORDS'][$key]['DISALLOWED_AFTER'])) { - $g1_post = $language_data['PARSER_CONTROL']['KEYWORDS'][$key]['DISALLOWED_AFTER']; - } - - if(isset($language_data['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_BEFORE'])) { - $g2_pre = $language_data['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_BEFORE']; - } - if(isset($language_data['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_AFTER'])) { - $g2_post = $language_data['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_AFTER']; - } - - if($g1_pre != $g2_pre || $g1_post != $g2_post) { - continue; - } - } - report_error(TYPE_WARNING, "Language file contains cross-group duplicate keyword '$kw' in \$language_data['KEYWORDS'][$key] and \$language_data['KEYWORDS'][$key2]!"); - } - } - } - foreach($language_data['CASE_SENSITIVE'] as $key => $keywords) { - if(!isset($language_data['KEYWORDS'][$key]) && $key != GESHI_COMMENTS) { - report_error(TYPE_WARNING, "Language file contains an superfluous \$language_data['CASE_SENSITIVE'] specification for non-existing keyword group $key!"); - } - } - foreach($language_data['URLS'] as $key => $keywords) { - if(!isset($language_data['KEYWORDS'][$key])) { - report_error(TYPE_WARNING, "Language file contains an superfluous \$language_data['URLS'] specification for non-existing keyword group $key!"); - } - } - foreach($language_data['STYLES']['KEYWORDS'] as $key => $keywords) { - if(!isset($language_data['KEYWORDS'][$key])) { - report_error(TYPE_WARNING, "Language file contains an superfluous \$language_data['STYLES']['KEYWORDS'] specification for non-existing keyword group $key!"); - } - } - - foreach($language_data['COMMENT_SINGLE'] as $ck => $cv) { - if(!is_int($ck)) { - report_error(TYPE_WARNING, "Language file contains an key '$ck' in \$language_data['COMMENT_SINGLE'] that is not integer!"); - } - if(!is_string($cv)) { - report_error(TYPE_WARNING, "Language file contains an non-string entry at \$language_data['COMMENT_SINGLE'][$ck]!"); - } - if(!isset($language_data['STYLES']['COMMENTS'][$ck])) { - report_error(TYPE_WARNING, "Language file contains no \$language_data['STYLES']['COMMENTS'] specification for comment group $ck!"); - } - } - if(isset($language_data['COMMENT_REGEXP'])) { - foreach($language_data['COMMENT_REGEXP'] as $ck => $cv) { - if(!is_int($ck)) { - report_error(TYPE_WARNING, "Language file contains an key '$ck' in \$language_data['COMMENT_REGEXP'] that is not integer!"); - } - if(!is_string($cv)) { - report_error(TYPE_WARNING, "Language file contains an non-string entry at \$language_data['COMMENT_REGEXP'][$ck]!"); - } - if(!isset($language_data['STYLES']['COMMENTS'][$ck])) { - report_error(TYPE_WARNING, "Language file contains no \$language_data['STYLES']['COMMENTS'] specification for comment group $ck!"); - } - } - } - foreach($language_data['STYLES']['COMMENTS'] as $ck => $cv) { - if($ck != 'MULTI' && !isset($language_data['COMMENT_SINGLE'][$ck]) && - !isset($language_data['COMMENT_REGEXP'][$ck])) { - report_error(TYPE_NOTICE, "Language file contains an superfluous \$language_data['STYLES']['COMMENTS'] specification for Single Line or Regular-Expression Comment key $ck!"); - } - } - if (isset($language_data['STYLES']['STRINGS']['HARD'])) { - if (empty($language_data['HARDQUOTE'])) { - report_error(TYPE_NOTICE, "Language file contains superfluous \$language_data['STYLES']['STRINGS'] specification for key 'HARD', but no 'HARDQUOTE's are defined!"); - } - unset($language_data['STYLES']['STRINGS']['HARD']); - } - foreach($language_data['STYLES']['STRINGS'] as $sk => $sv) { - if($sk && !isset($language_data['QUOTEMARKS'][$sk])) { - report_error(TYPE_NOTICE, "Language file contains an superfluous \$language_data['STYLES']['STRINGS'] specification for non-existing quotemark key $sk!"); - } - } - - foreach($language_data['REGEXPS'] as $rk => $rv) { - if(!is_int($rk)) { - report_error(TYPE_WARNING, "Language file contains an key '$rk' in \$language_data['REGEXPS'] that is not integer!"); - } - if(is_string($rv)) { - //Check for unmasked / in regular expressions ... - if(empty($rv)) { - report_error(TYPE_WARNING, "Language file contains an empty regular expression at \$language_data['REGEXPS'][$rk]!"); - } else { - if(preg_match("/(?<!\\\\)\//s", $rv)) { - report_error(TYPE_WARNING, "Language file contains a regular expression with an unmasked / character at \$language_data['REGEXPS'][$rk]!"); - } elseif (preg_match("/(?<!<)(\\\\\\\\)*\\\\\|(?!>)/s", $rv)) { - report_error(TYPE_WARNING, "Language file contains a regular expression with an unescaped match for a pipe character '|' which needs escaping as '<PIPE>' instead at \$language_data['REGEXPS'][$rk]!"); - } - } - } elseif(is_array($rv)) { - if(!isset($rv[GESHI_SEARCH])) { - report_error(TYPE_ERROR, "Language file contains no GESHI_SEARCH entry in extended regular expression at \$language_data['REGEXPS'][$rk]!"); - } elseif(!is_string($rv[GESHI_SEARCH])) { - report_error(TYPE_ERROR, "Language file contains a GESHI_SEARCH entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!"); - } else { - if(preg_match("/(?<!\\\\)\//s", $rv[GESHI_SEARCH])) { - report_error(TYPE_WARNING, "Language file contains a regular expression with an unmasked / character at \$language_data['REGEXPS'][$rk]!"); - } elseif (preg_match("/(?<!<)(\\\\\\\\)*\\\\\|(?!>)/s", $rv[GESHI_SEARCH])) { - report_error(TYPE_WARNING, "Language file contains a regular expression with an unescaped match for a pipe character '|' which needs escaping as '<PIPE>' instead at \$language_data['REGEXPS'][$rk]!"); - } - } - if(!isset($rv[GESHI_REPLACE])) { - report_error(TYPE_WARNING, "Language file contains no GESHI_REPLACE entry in extended regular expression at \$language_data['REGEXPS'][$rk]!"); - } elseif(!is_string($rv[GESHI_REPLACE])) { - report_error(TYPE_ERROR, "Language file contains a GESHI_REPLACE entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!"); - } - if(!isset($rv[GESHI_MODIFIERS])) { - report_error(TYPE_WARNING, "Language file contains no GESHI_MODIFIERS entry in extended regular expression at \$language_data['REGEXPS'][$rk]!"); - } elseif(!is_string($rv[GESHI_MODIFIERS])) { - report_error(TYPE_ERROR, "Language file contains a GESHI_MODIFIERS entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!"); - } - if(!isset($rv[GESHI_BEFORE])) { - report_error(TYPE_WARNING, "Language file contains no GESHI_BEFORE entry in extended regular expression at \$language_data['REGEXPS'][$rk]!"); - } elseif(!is_string($rv[GESHI_BEFORE])) { - report_error(TYPE_ERROR, "Language file contains a GESHI_BEFORE entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!"); - } - if(!isset($rv[GESHI_AFTER])) { - report_error(TYPE_WARNING, "Language file contains no GESHI_AFTER entry in extended regular expression at \$language_data['REGEXPS'][$rk]!"); - } elseif(!is_string($rv[GESHI_AFTER])) { - report_error(TYPE_ERROR, "Language file contains a GESHI_AFTER entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!"); - } - } else { - report_error(TYPE_WARNING, "Language file contains an non-string and non-array entry at \$language_data['REGEXPS'][$rk]!"); - } - if(!isset($language_data['STYLES']['REGEXPS'][$rk])) { - report_error(TYPE_WARNING, "Language file contains no \$language_data['STYLES']['REGEXPS'] specification for regexp group $rk!"); - } - } - foreach($language_data['STYLES']['REGEXPS'] as $rk => $rv) { - if(!isset($language_data['REGEXPS'][$rk])) { - report_error(TYPE_NOTICE, "Language file contains an superfluous \$language_data['STYLES']['REGEXPS'] specification for regexp key $rk!"); - } - } - - - } - - output_error_cache(); - - flush(); - - if($error_abort) { - break; - } - } -} - -$time_end = explode(' ', microtime()); -$time_diff = $time_end[0] + $time_end[1] - $time_start[0] - $time_start[1]; - -if ( PHP_SAPI != 'cli' ) { -?></li> -</ol> - -<p>Validation process completed in <?php printf("%.2f", $time_diff); ?> seconds.</p> - -<div id="footer">GeSHi © 2004-2007 Nigel McNie, 2007-2008 Benny Baumann, released under the GNU GPL</div> -</body> -</html> - -<?php } else { ?> - -Validation process completed in <?php printf("%.2f", $time_diff); ?> seconds. - -GeSHi © 2004-2007 Nigel McNie, 2007-2014 Benny Baumann, released under the GNU GPL - -<?php } ?> diff --git a/extensions/SyntaxHighlight_GeSHi/geshi/contrib/langwiz.php b/extensions/SyntaxHighlight_GeSHi/geshi/contrib/langwiz.php deleted file mode 100644 index 3338fa66..00000000 --- a/extensions/SyntaxHighlight_GeSHi/geshi/contrib/langwiz.php +++ /dev/null @@ -1,1153 +0,0 @@ -<?php -/** - * GeSHi example script - * - * Just point your browser at this script (with geshi.php in the parent directory, - * and the language files in subdirectory "../geshi/") - * - *This script - * - * @author Nigel McNie, Benny Baumann (BenBE@geshi.org), Andreas 'Segaja' Schleifer (webmaster at segaja dot de) - * @version $Id$ - */ -header('Content-Type: text/html; charset=utf-8'); - -set_time_limit(0); -error_reporting(E_ALL); -$time_start = explode(' ', microtime()); - -//Handle crappy PHP magic: -if (get_magic_quotes_gpc()) { - function stripslashes_deep($value) { - $value = is_array($value) ? - array_map('stripslashes_deep', $value) : - stripslashes($value); - - return $value; - } - - $_POST = array_map('stripslashes_deep', $_POST); - $_GET = array_map('stripslashes_deep', $_GET); - $_COOKIE = array_map('stripslashes_deep', $_COOKIE); - $_REQUEST = array_map('stripslashes_deep', $_REQUEST); -} - -function htmlspecialchars_deep($value) { - return is_array($value) ? array_map('htmlspecialchars_deep', $value) : htmlspecialchars($value); -} - -define ('TYPE_NOTICE', 0); -define ('TYPE_WARNING', 1); -define ('TYPE_ERROR', 2); - -$error_abort = false; -$error_cache = array(); -function output_error_cache(){ - global $error_cache; - - if(count($error_cache)) { - echo "<span style=\"color: #F00; font-weight: bold;\">Failed</span><br />"; - echo "<ol>\n"; - foreach($error_cache as $error_msg) { - echo "<li>"; - switch($error_msg['t']) { - case TYPE_NOTICE: - echo "<span style=\"color: #080; font-weight: bold;\">NOTICE:</span>"; - break; - case TYPE_WARNING: - echo "<span style=\"color: #CC0; font-weight: bold;\">WARNING:</span>"; - break; - case TYPE_ERROR: - echo "<span style=\"color: #F00; font-weight: bold;\">ERROR:</span>"; - break; - } - echo " " . $error_msg['m'] . "</li>"; - } - echo "</ol>\n"; - } else { - echo "<span style=\"color: #080; font-weight: bold;\">OK</span><br />"; - } - echo "\n"; - - $error_cache = array(); -} - -function report_error($type, $message) { - global $error_cache, $error_abort; - - $error_cache[] = array('t' => $type, 'm' => $message); - if(TYPE_ERROR == $type) { - $error_abort = true; - } -} - -?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head> - <title>GeSHi Language File Generator Script</title> - <style type="text/css"> - <!-- - html { - background-color: #f0f0f0; - } - body { - font-family: Verdana, Arial, sans-serif; - margin: 10px; - border: 2px solid #e0e0e0; - background-color: #fcfcfc; - padding: 5px; - font-size: 10pt; - } - h2 { - margin: .1em 0 .2em .5em; - border-bottom: 1px solid #b0b0b0; - color: #b0b0b0; - font-weight: normal; - font-size: 150%; - } - h3 { - margin: .1em 0 .2em .5em; - color: #b0b0b0; - font-weight: normal; - font-size: 120%; - } - #footer { - text-align: center; - font-size: 80%; - color: #a9a9a9; - } - #footer a { - color: #9999ff; - } - textarea { - border: 1px solid #b0b0b0; - font-size: 90%; - color: #333; - margin-left: 20px; - } - select, input { - margin-left: 2px; - border: 1px solid #808080; - } - p { - font-size: 90%; - margin-left: .5em; - } - fieldset { - border: 1px dotted gray; - background-color: #f0f0f0; - margin-bottom: .5em; - } - legend { - font-weight: bold; - background-color: #f9f9f9; - border: 1px solid #a0a0a0; - border-width: 1px 2px 2px 1px; - } - fieldset table > tbody > tr > td { - width: 20%; - } - fieldset table > tbody > tr > td+td { - width: 80%; - } - - fieldset table > tbody > tr > td+td > input { - width: 98%; - } - --> - </style> -</head> -<body> -<h2>GeSHi Language File Generator Script</h2> -<p>To use this script, make sure that <strong>geshi.php</strong> is in the -parent directory or in your include_path, and that the language files are in a -subdirectory of GeSHi's directory called <strong>geshi/</strong>.</p> -<p>If not already done, select a language file below that will be used as -base for the language file to generate or create a blank one. Following this -you can do whatever you like to edit your language file. But note that not all -features are made available through this script.</p> - -<p>Checking GeSHi installation ... <?php -// Rudimentary checking of where GeSHi is. In a default install it will be in ../, but -// it could be in the current directory if the include_path is set. There's nowhere else -// we can reasonably guess. -if (is_readable('../geshi.php')) { - $path = '../'; -} elseif (is_readable('geshi.php')) { - $path = './'; -} else { - report_error(TYPE_ERROR, 'Could not find geshi.php - make sure it is in your include path!'); -} - -if(!$error_abort) { - require $path . 'geshi.php'; - - if(!class_exists('GeSHi')) { - report_error(TYPE_ERROR, 'The GeSHi class was not found, although it seemed we loaded the correct file!'); - } -} - -if(!$error_abort) { - if(!defined('GESHI_LANG_ROOT')) { - report_error(TYPE_ERROR, 'There\'s no information present on where to find the language files!'); - } elseif(!is_dir(GESHI_LANG_ROOT)) { - report_error(TYPE_ERROR, 'The path "'.GESHI_LANG_ROOT.'" given, does not ressemble a directory!'); - } elseif(!is_readable(GESHI_LANG_ROOT)) { - report_error(TYPE_ERROR, 'The path "'.GESHI_LANG_ROOT.'" is not readable to this script!'); - } -} - -if(!$error_abort) { - if (!($dir = @opendir(GESHI_LANG_ROOT))) { - report_error(TYPE_ERROR, 'Error requesting listing for available language files!'); - } - - $languages = array(); - - if(!$error_abort) { - while ($file = readdir($dir)) { - if (!$file || $file[0] == '.' || strpos($file, '.') === false) { - continue; - } - $lang = substr($file, 0, strpos($file, '.')); - $languages[] = $lang; - } - closedir($dir); - } - - $languages = array_unique($languages); - sort($languages); - - if(!count($languages)) { - report_error(TYPE_WARNING, 'Unable to locate any usable language files in "'.GESHI_LANG_ROOT.'"!'); - } -} - -output_error_cache(); - -// --- empty variables for values of $_POST - begin --- -$post_var_names = array('li', 'ai', 'ld'); - -$li = array( - 'file' => 'example', - 'name' => 'Example' - ); - -$ai = array( - 'name' => 'Benny Baumann', - 'email' => 'BenBE@geshi.org', - 'web' => 'http://qbnz.com/highlighter/' - ); - -$ld = array( - 'cmt' => array( - 'sl' => array( - 1 => array( - 'start' => '//', - 'style' => 'font-style: italic; color: #666666;' - ), - 2 => array( - 'start' => '#', - 'style' => 'font-style: italic; color: #666666;' - ) - ), - 'ml' => array( - 1 => array( - 'start' => '/*', - 'end' => '*/', - 'style' => 'font-style: italic; color: #666666;' - ), - 2 => array( - 'start' => '/**', - 'end' => '*/', - 'style' => 'font-style: italic; color: #006600;' - ) - ), - 'rxc' => array( - 1 => array( - 'rx' => '/Hello RegExp/', - 'style' => 'font-style: italic; color: #666666;' - ) - ) - ), - 'str' => array( - 'qm' => array( - 1 => array( - 'delim' => "'", - 'style' => 'color: #0000FF;' - ), - 2 => array( - 'delim' => """, - 'style' => 'color: #0000FF;' - ) - ), - 'ec' => array( - 'char' => '\\', - 'style' => 'font-weight: bold; color: #000080;' - ), - 'erx' => array( - 1 => array( - 'rx' => '/\{\\\\$\w+\}/', - 'style' => 'font-weight: bold; color: #008080;' - ), - 2 => array( - 'rx'=> '/\{\\\\$\w+\}/', - 'style' => 'font-weight: bold; color: #008080;' - ) - ) - ), - 'kw_case' => 'GESHI_CAPS_NO_CHANGE', - 'kw' => array( - 1 => array( - 'list' => '', - 'case' => '0', - 'style' => 'color: #0000FF; font-weight: bold;', - 'docs' => '' - ) - ), - 'sy' => array( - 0 => array( - 'list' => '', - 'style' => 'color: #0000FF; font-weight: bold;' - ) - ) - ); - -$kw_case_sel = array( - 'GESHI_CAPS_NO_CHANGE' => '', - 'GESHI_CAPS_UPPER' => '', - 'GESHI_CAPS_LOWER' => '' - ); - -$kw_cases_sel = array( - 1 => array( - 0 => '', - 1 => '' - ) - ); -// --- empty variables for values of $_POST - end --- - -echo "<pre>"; -//var_dump($languages); - -foreach($post_var_names as $varName) { // export wanted variables of $_POST array... - if(array_key_exists($varName, $_POST)) { - $$varName = htmlspecialchars_deep($_POST[$varName]); - } -} - -// determine the selected kw_case... -$kw_case_sel[$ld['kw_case']] = ' selected="selected"'; - -// determine the selected kw_cases... -for($i = 1; $i <= count($kw_cases_sel); $i += 1) { - $kw_cases_sel[$i][(int) $ld['kw'][$i]['case']] = ' selected="selected"'; -} - -$lang = validate_lang(); -var_dump($lang); -echo "</pre>"; - -?> - -<form action="?action=test" method="post"> - <fieldset> - <legend>Generic Information</legend> - - <table width="100%"> - <tr> - <td> - <label for="li[file]">Language File ID:</label> - </td> - <td> - <input type="text" name="li[file]" id="li[file]" value="<?=$li['file']; ?>" /> - </td> - </tr> - - <tr> - <td> - <label for="li[name]">Language Name:</label> - </td> - <td> - <input type="text" name="li[name]" id="li[name]" value="<?=$li['name']; ?>" /> - </td> - </tr> - - </table> - </fieldset> - - <fieldset> - <legend>Author</legend> - - <table width="100%"> - <tr> - <td> - <label for="ai[name]">Full Name:</label> - </td> - <td> - <input type="text" name="ai[name]" id="ai[name]" value="<?=$ai['name']; ?>" /> - </td> - </tr> - - <tr> - <td> - <label for="ai[email]">eMail address:</label> - </td> - <td> - <input type="text" name="ai[email]" id="ai[email]" value="<?=$ai['email']; ?>" /> - </td> - </tr> - - <tr> - <td> - <label for="ai[web]">Homepage:</label> - </td> - <td> - <input type="text" name="ai[web]" id="ai[web]" value="<?=$ai['web']; ?>" /> - </td> - </tr> - </table> - </fieldset> - - <fieldset> - <legend>Comments</legend> - - <fieldset> - <legend>Single Line</legend> - - <fieldset> - <legend>Comment Group 1</legend> - - <table width="100%"> - <tr> - <td> - <label for="ld[cmt][sl][1][start]">Comment Start:</label> - </td> - <td> - <input type="text" name="ld[cmt][sl][1][start]" id="ld[cmt][sl][1][start]" value="<?=$ld['cmt']['sl'][1]['start']; ?>" /> - </td> - </tr> - - <tr> - <td> - <label for="ld[cmt][sl][1][style]">Comment Style:</label> - </td> - <td> - <input type="text" name="ld[cmt][sl][1][style]" id="ld[cmt][sl][1][style]" value="<?=$ld['cmt']['sl'][1]['style']; ?>" /> - </td> - </tr> - </table> - </fieldset> - - <fieldset> - <legend>Comment Group 2</legend> - - <table width="100%"> - <tr> - <td> - <label for="ld[cmt][sl][2][start]">Comment Start:</label> - </td> - <td> - <input type="text" name="ld[cmt][sl][2][start]" id="ld[cmt][sl][2][start]" value="<?=$ld['cmt']['sl'][2]['start']; ?>" /> - </td> - </tr> - - <tr> - <td> - <label for="ld[cmt][sl][2][style]">Comment Style:</label> - </td> - <td> - <input type="text" name="ld[cmt][sl][2][style]" id="ld[cmt][sl][2][style]" value="<?=$ld['cmt']['sl'][2]['style']; ?>" /> - </td> - </tr> - </table> - </fieldset> - </fieldset> - - <fieldset> - <legend>Multiple Lines</legend> - - <fieldset> - <legend>Comment Group 1</legend> - - <table width="100%"> - <tr> - <td> - <label for="ld[cmt][ml][1][start]">Comment Start:</label> - </td> - <td> - <input type="text" name="ld[cmt][ml][1][start]" id="ld[cmt][ml][1][start]" value="<?=$ld['cmt']['ml'][1]['start']; ?>" /> - </td> - </tr> - - <tr> - <td> - <label for="ld[cmt][ml][1][end]">Comment End:</label> - </td> - <td> - <input type="text" name="ld[cmt][ml][1][end]" id="ld[cmt][ml][1][end]" value="<?=$ld['cmt']['ml'][1]['end']; ?>" /> - </td> - </tr> - - <tr> - <td> - <label for="ld[cmt][ml][1][style]">Comment Style:</label> - </td> - <td> - <input type="text" name="ld[cmt][ml][1][style]" id="ld[cmt][ml][1][style]" value="<?=$ld['cmt']['ml'][1]['style']; ?>" /> - </td> - </tr> - </table> - </fieldset> - - <fieldset> - <legend>Comment Group 2</legend> - - <table width="100%"> - <tr> - <td> - <label for="ld[cmt][ml][2][start]">Comment Start:</label> - </td> - <td> - <input type="text" name="ld[cmt][ml][2][start]" id="ld[cmt][ml][2][start]" value="<?=$ld['cmt']['ml'][2]['start']; ?>" /> - </td> - </tr> - - <tr> - <td> - <label for="ld[cmt][ml][2][end]">Comment End:</label> - </td> - <td> - <input type="text" name="ld[cmt][ml][2][end]" id="ld[cmt][ml][2][end]" value="<?=$ld['cmt']['ml'][2]['end']; ?>" /> - </td> - </tr> - - <tr> - <td> - <label for="ld[cmt][ml][2][style]">Comment Style:</label> - </td> - <td> - <input type="text" name="ld[cmt][ml][2][style]" id="ld[cmt][ml][2][style]" value="<?=$ld['cmt']['ml'][2]['style']; ?>" /> - </td> - </tr> - </table> - </fieldset> - </fieldset> - - <fieldset> - <legend>Regular Expressions</legend> - - <fieldset> - <legend>Comment Group 1</legend> - - <table width="100%"> - <tr> - <td> - <label for="ld[cmt][rxc][1][rx]">Comment RX:</label> - </td> - <td> - <input type="text" name="ld[cmt][rxc][1][rx]" id="ld[cmt][rxc][1][rx]" value="<?=$ld['cmt']['rxc'][1]['rx']; ?>" /> - </td> - </tr> - - <tr> - <td> - <label for="ld[cmt][rxc][1][style]">Comment Style:</label> - </td> - <td> - <input type="text" name="ld[cmt][rxc][1][style]" id="ld[cmt][rxc][1][style]" value="<?=$ld['cmt']['rxc'][1]['style']; ?>" /> - </td> - </tr> - </table> - </fieldset> - </fieldset> - </fieldset> - - <fieldset> - <legend>Strings</legend> - - <fieldset> - <legend>String \ Quotes (delimiters, parsed)</legend> - - <fieldset> - <legend>Quotemark Group 1</legend> - - <table width="100%"> - <tr> - <td> - <label for="ld[str][qm][1][delim]">String Delimiter:</label> - </td> - <td> - <input type="text" name="ld[str][qm][1][delim]" id="ld[str][qm][1][delim]" value="<?=$ld['str']['qm'][1]['delim']; ?>" /> - </td> - </tr> - - <tr> - <td> - <label for="ld[str][qm][1][style]">String Style:</label> - </td> - <td> - <input type="text" name="ld[str][qm][1][style]" id="ld[str][qm][1][style]" value="<?=$ld['str']['qm'][1]['style']; ?>" /> - </td> - </tr> - </table> - </fieldset> - <fieldset> - <legend>Quotemark Group 2</legend> - - <table width="100%"> - <tr> - <td> - <label for="ld[str][qm][1][delim]">String Delimiter:</label> - </td> - <td> - <input type="text" name="ld[str][qm][2][delim]" id="ld[str][qm][2][delim]" value="<?=$ld['str']['qm'][2]['delim']; ?>" /> - </td> - </tr> - - <tr> - <td> - <label for="ld[str][qm][1][style]">String Style:</label> - </td> - <td> - <input type="text" name="ld[str][qm][2][style]" id="ld[str][qm][2][style]" value="<?=$ld['str']['qm'][2]['style']; ?>" /> - </td> - </tr> - </table> - </fieldset> - - - </fieldset> - - <fieldset> - <legend>Escape Sequences</legend> - - <fieldset> - <legend>Generic Escape Char</legend> - - <table width="100%"> - <tr> - <td> - <label for="ld[str][ec][char]">Escape Char:</label> - </td> - <td> - <input type="text" name="ld[str][ec][char]" id="ld[str][ec][char]" value="<?=$ld['str']['ec']['char']; ?>" /> - </td> - </tr> - - <tr> - <td> - <label for="ld[str][ec][style]">Escape Char Style:</label> - </td> - <td> - <input type="text" name="ld[str][ec][style]" id="ld[str][ec][style]" value="<?=$ld['str']['ec']['style']; ?>" /> - </td> - </tr> - </table> - </fieldset> - - <fieldset> - <legend>Escape Regexp Group 1</legend> - - <table width="100%"> - <tr> - <td> - <label for="ld[str][erx][1][rx]">Escape Regexp:</label> - </td> - <td> - <input type="text" name="ld[str][erx][1][rx]" id="ld[str][erx][1][rx]" value="<?=$ld['str']['erx'][1]['rx']; ?>" /> - </td> - </tr> - - <tr> - <td> - <label for="ld[str][erx][1][style]">Escape Style:</label> - </td> - <td> - <input type="text" name="ld[str][erx][1][style]" id="ld[str][erx][1][style]" value="<?=$ld['str']['erx'][1]['style']; ?>" /> - </td> - </tr> - </table> - </fieldset> - - <fieldset> - <legend>Escape Regexp Group 2</legend> - - <table width="100%"> - <tr> - <td> - <label for="ld[str][erx][2][rx]">Escape Regexp:</label> - </td> - <td> - <input type="text" name="ld[str][erx][2][rx]" id="ld[str][erx][2][rx]" value="<?=$ld['str']['erx'][2]['rx']; ?>" /> - </td> - </tr> - - <tr> - <td> - <label for="ld[str][erx][2][style]">Escape Style:</label> - </td> - <td> - <input type="text" name="ld[str][erx][2][style]" id="ld[str][erx][2][style]" value="<?=$ld['str']['erx'][2]['style']; ?>" /> - </td> - </tr> - </table> - </fieldset> - </fieldset> - </fieldset> - - <fieldset> - <legend>Keywords</legend> - - <fieldset> - <legend>Case of Keywords</legend> - - <table width="100%"> - <tr> - <td> - <label for="ld[kw_case]">Handling of keywords case:</label> - </td> - <td> - <select name=ld[kw_case]" id="ld[kw_case]"> - <option value="GESHI_CAPS_NO_CHANGE"<?=$kw_case_sel['GESHI_CAPS_NO_CHANGE']; ?>>Don’t change the case of any keyword</option> - <option value="GESHI_CAPS_UPPER"<?=$kw_case_sel['GESHI_CAPS_UPPER']; ?>>Convert the case of all keywords to upper case</option> - <option value="GESHI_CAPS_LOWER"<?=$kw_case_sel['GESHI_CAPS_LOWER']; ?>>Convert the case of all keywords to lower case</option> - </select> - </td> - </tr> - </table> - </fieldset> - - <fieldset> - <legend>Keyword Group 1</legend> - - <table width="100%"> - <tr> - <td> - <label for="ld[kw][1][list]">Keyword List:</label> - </td> - <td> - <textarea name="ld[kw][1][list]" id="ld[kw][1][list]" rows="10" cols="80"><?=$ld['kw'][1]['list']; ?></textarea> - </td> - </tr> - - <tr> - <td> - <label for="ld[kw][1][case]">Case Sensitive:</label> - </td> - <td> - <select name="ld[kw][1][case]" id="ld[kw][1][case]"> - <option value="0"<?=$kw_cases_sel[1][0]; ?>>No</option> - <option value="1"<?=$kw_cases_sel[1][1]; ?>>Yes</option> - </select> - </td> - </tr> - - <tr> - <td> - <label for="ld[kw][1][style]">Keyword Style:</label> - </td> - <td> - <input type="text" name="ld[kw][1][style]" id="ld[kw][1][style]" value="<?=$ld['kw'][1]['style']; ?>" /> - </td> - </tr> - - <tr> - <td> - <label for="ld[kw][1][docs]">Documentation URL:</label> - </td> - <td> - <input type="text" name="ld[kw][1][docs]" id="ld[kw][1][docs]" value="<?=$ld['kw'][1]['docs']; ?>" /> - </td> - </tr> - </table> - </fieldset> - - </fieldset> - - - <fieldset> - <legend>Symbols</legend> - - <fieldset> - <legend>Symbols Group 1</legend> - - <table width="100%"> - <tr> - <td> - <label for="ld[sy][0][list]">Symbols List:</label> - </td> - <td> - <textarea name="ld[sy][0][list]" id="ld[sy][0][list]" rows="10" cols="80"><?=$ld['sy'][0]['list']; ?></textarea> - </td> - </tr> - - <tr> - <td> - <label for="ld[sy][0][style]">Symbols Style:</label> - </td> - <td> - <input type="text" name="ld[sy][0][style]" id="ld[sy][0][style]" value="<?=$ld['sy'][0]['style']; ?>" /> - </td> - </tr> - </table> - </fieldset> - - </fieldset> - - - <div id="langfile"> - <fieldset> - <legend>Language File Source</legend> -<?php -$G = new GeSHi('', 'php'); -$langfile_source = gen_langfile($lang); -$G->set_source($langfile_source); -echo $G->parse_code(); -unset($G); -?> - </fieldset> - </div> - - <input type="submit" name="btn" value="Send!" /> -</form> - -<p>Operation completed in <?php -$time_end = explode(' ', microtime()); -$time_diff = $time_end[0] + $time_end[1] - $time_start[0] - $time_start[1]; - -echo sprintf("%.2f", $time_diff); -?> seconds.</p> - -<div id="footer">GeSHi © 2004-2007 Nigel McNie, 2007-2009 Benny Baumann, released under the GNU GPL</div> -</body> -</html> -<?php - -function str_to_phpstring($str, $doublequote = false){ - if($doublequote) { - return '"' . strtr($str, - array( - "\"" => "\\\"", - "\\" => "\\\\", - "\0" => "\\0", - "\n" => "\\n", - "\r" => "\\r", - "\t" => "\\t", - "\$" => "\\\$" - ) - ) . '"'; - } else { - return "'" . strtr($str, - array( - "'" => "\\'", - "\\" => "\\\\" - ) - ) . "'"; - } -} - -function validate_lang(){ - $ai = array( - 'name' => 'Benny Baumann', - 'email' => 'BenBE@geshi.org', - 'web' => 'http://qbnz.com/highlighter/' - ); - - $li = array( - 'file' => 'example', - 'desc' => 'Example' - ); - - if(isset($_POST['ld'])) { - $ld = $_POST['ld']; - } else { - $ld = array( - 'cmt' => array( - 'sl' => array( - 1 => array( - 'start' => '//', - 'style' => 'test' - ) - ), - 'ml' => array( - 1 => array( - 'start' => '/*', - 'end' => '*/', - 'style' => 'font-style: italic; color: #666666;' - ) - ), - 'rxc' => array( - 1 => array( - 'rx' => '/Hello/', - 'style' => 'color: #00000' - ) - ) - ), - 'str' => array( - 'qm' => array(), - 'ec' => array( - 'char' => '' - ), - 'erx' => array() - ), - 'kw' => array(), - 'kw_case' => 'GESHI_CAPS_NO_CHANGE', - 'sy' => array() - ); - } - - return array('ai' => $ai, 'li' => $li, 'ld' => $ld); -} - -function gen_langfile($lang){ - $langfile = $lang['li']['file']; - $langdesc = $lang['li']['desc']; - - $langauthor_name = $lang['ai']['name']; - $langauthor_email = $lang['ai']['email']; - $langauthor_web = $lang['ai']['web']; - - $langversion = GESHI_VERSION; - - $langdate = date('Y/m/d'); - $langyear = date('Y'); - - $i = ' '; - $i = array('', $i, $i.$i, $i.$i.$i); - - $src = <<<GESHI_LANGFILE_HEAD -<?php -/************************************************************************************* - * {$langfile}.php - * -------- - * Author: {$langauthor_name} ({$langauthor_email}) - * Copyright: (c) {$langyear} {$langauthor_name} ({$langauthor_web}) - * Release Version: {$langversion} - * Date Started: {$langdate} - * - * {$langdesc} language file for GeSHi. - * - * CHANGES - * ------- - * {$langdate} ({$langversion}) - * - First Release - * - * TODO (updated {$langdate}) - * ------------------------- - * * Complete language file - * - ************************************************************************************* - * - * This file is part of GeSHi. - * - * GeSHi is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GeSHi is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GeSHi; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - ************************************************************************************/ - -\$language_data = array( - -GESHI_LANGFILE_HEAD; - - //Language Name - $src .= $i[1] . "'LANG_NAME' => ".str_to_phpstring($langdesc).",\n"; - - //Comments - $src .= $i[1] . "'COMMENT_SINGLE' => array(\n"; - foreach($lang['ld']['cmt']['sl'] as $idx_cmt_sl => $tmp_cmt_sl) { - $src .= $i[2] . ((int)$idx_cmt_sl). " => ". str_to_phpstring($tmp_cmt_sl['start']) . ",\n"; - } - $src .= $i[2] . "),\n"; - $src .= $i[1] . "'COMMENT_MULTI' => array(\n"; - foreach($lang['ld']['cmt']['ml'] as $tmp_cmt_ml) { - $src .= $i[2] . str_to_phpstring($tmp_cmt_ml['start']). " => ". str_to_phpstring($tmp_cmt_ml['end']) . ",\n"; - } - $src .= $i[2] . "),\n"; - $src .= $i[1] . "'COMMENT_REGEXP' => array(\n"; - foreach($lang['ld']['cmt']['rxc'] as $idx_cmt_rxc => $tmp_cmt_rxc) { - $src .= $i[2] . ((int)$idx_cmt_rxc). " => ". str_to_phpstring($tmp_cmt_rxc['rx']) . ",\n"; - } - $src .= $i[2] . "),\n"; - - //Case Keywords - $src .= $i[1] . "'CASE_KEYWORDS' => " . $lang['ld']['kw_case'] . ",\n"; - - //Quotes \ Strings - $src .= $i[1] . "'QUOTEMARKS' => array(\n"; - foreach($lang['ld']['str']['qm'] as $idx_str_qm => $tmp_str_qm) { - $src .= $i[2] . ((int)$idx_str_qm). " => ". str_to_phpstring($tmp_str_qm['delim']) . ",\n"; - } - $src .= $i[2] . "),\n"; - $src .= $i[1] . "'ESCAPE_CHAR' => " . str_to_phpstring($lang['ld']['str']['ec']['char']) . ",\n"; - $src .= $i[1] . "'ESCAPE_REGEXP' => array(\n"; - foreach($lang['ld']['str']['erx'] as $idx_str_erx => $tmp_str_erx) { - $src .= $i[2] . ((int)$idx_str_erx). " => ". str_to_phpstring($tmp_str_erx['rx']) . ",\n"; - } - $src .= $i[2] . "),\n"; - - //HardQuotes - $src .= $i[1] . "'HARDQUOTE' => array(\n"; - $src .= $i[2] . "),\n"; - $src .= $i[1] . "'HARDESCAPE' => array(\n"; - $src .= $i[2] . "),\n"; - $src .= $i[1] . "'HARDCHAR' => '',\n"; - - //Numbers - $src .= $i[1] . "'NUMBERS' =>\n"; - $src .= $i[2] . "GESHI_NUMBER_INT_BASIC | GESHI_NUMBER_OCT_PREFIX | GESHI_NUMBER_HEX_PREFIX |\n"; - $src .= $i[2] . "GESHI_NUMBER_FLT_SCI_ZERO,\n"; - - //Keywords - $src .= $i[1] . "'KEYWRODS' => array(\n"; - foreach($lang['ld']['kw'] as $idx_kw => $tmp_kw) { - $src .= $i[2] . ((int)$idx_kw) . " => array(\n"; - if(!is_array($tmp_kw['list'])) { - $tmp_kw['list'] = explode("\n", $tmp_kw['list']); - } - $tmp_kw['list'] = array_map('trim', $tmp_kw['list']); - sort($tmp_kw['list']); - $kw_esc = array_map('str_to_phpstring', $tmp_kw['list']); - $kw_nl = true; - $kw_pos = 0; - foreach($kw_esc as $kw_data) { - if((strlen($kw_data) + $kw_pos > 79) && $kw_pos > strlen($i[3])) { - $src .= "\n"; - $kw_nl = true; - $kw_pos = 0; - } - if($kw_nl) { - $src .= $i[3]; - $kw_pos += strlen($i[3]); - $kw_nl = false; - } - $src .= $kw_data . ', '; - $kw_pos += strlen($kw_data) + 2; - } - $src .= "\n"; - $src .= $i[3] . "),\n"; - } - $src .= $i[2] . "),\n"; - - //Case Sensitivity - $src .= $i[1] . "'CASE_SENSITIVE' => array(\n"; - foreach($lang['ld']['kw'] as $idx_kw => $tmp_kw) { - $src .= $i[2] . ((int)$idx_kw) . " => " . ($tmp_kw['case'] ? 'true' : 'false') . ",\n"; - } - $src .= $i[2] . "),\n"; - - //Symbols - $src .= $i[1] . "'SYMBOLS' => array(\n"; - foreach($lang['ld']['sy'] as $idx_kw => $tmp_kw) { - $src .= $i[2] . ((int)$idx_kw) . " => array(\n"; - $tmp_kw['list'] = (array)$tmp_kw['list']; - sort($tmp_kw['list']); - $kw_esc = array_map('str_to_phpstring', $tmp_kw['list']); - $kw_nl = true; - $kw_pos = strlen($i[3]); - foreach($kw_esc as $kw_data) { - if((strlen($kw_data) + $kw_pos > 79) && $kw_pos > strlen($i[3])) { - $src .= "\n"; - $kw_nl = true; - $kw_pos = 0; - } - if($kw_nl) { - $src .= $i[3]; - $kw_pos += strlen($i[3]); - $kw_nl = false; - } - $src .= $kw_data . ', '; - $kw_pos += strlen($kw_data) + 2; - } - $src .= "\n"; - $src .= $i[3] . "),\n"; - } - $src .= $i[2] . "),\n"; - - //Styles \ CSS - $src .= $i[1] . "'STYLES' => array(\n"; - $src .= $i[2] . "'KEYWRODS' => array(\n"; - foreach($lang['ld']['kw'] as $idx_kw => $tmp_kw) { - $src .= $i[3] . ((int)$idx_kw) . " => " . str_to_phpstring($tmp_kw['style']) . ",\n"; - } - $src .= $i[3] . "),\n"; - $src .= $i[2] . "'COMMENTS' => array(\n"; - foreach($lang['ld']['cmt']['sl'] as $idx_cmt_sl => $tmp_cmt_sl) { - $src .= $i[3] . ((int)$idx_cmt_sl) . " => " . str_to_phpstring($tmp_cmt_sl['style']) . ",\n"; - } - foreach($lang['ld']['cmt']['rxc'] as $idx_cmt_rxc => $tmp_cmt_rxc) { - $src .= $i[3] . ((int)$idx_cmt_rxc) . " => " . str_to_phpstring($tmp_cmt_rxc['style']) . ",\n"; - } - $src .= $i[3] . "'MULTI' => " . str_to_phpstring($lang['ld']['cmt']['ml'][1]['style']) . "\n"; - $src .= $i[3] . "),\n"; - $src .= $i[2] . "'ESCAPE_CHAR' => array(\n"; - foreach($lang['ld']['str']['erx'] as $idx_str_erx => $tmp_str_erx) { - $src .= $i[3] . ((int)$idx_str_erx). " => ". str_to_phpstring($tmp_str_erx['style']) . ",\n"; - } - // 'HARD' => 'color: #000099; font-weight: bold;' - $src .= $i[3] . "),\n"; - $src .= $i[2] . "'BRACKETS' => array(\n"; - $src .= $i[3] . "),\n"; - $src .= $i[2] . "'STRINGS' => array(\n"; - foreach($lang['ld']['str']['qm'] as $idx_str_qm => $tmp_str_qm) { - $src .= $i[3] . ((int)$idx_str_qm). " => ". str_to_phpstring($tmp_str_qm['style']) . ",\n"; - } - // 'HARD' => 'color: #0000ff;' - $src .= $i[3] . "),\n"; - $src .= $i[2] . "'NUMBERS' => array(\n"; - $src .= $i[3] . "),\n"; - $src .= $i[2] . "'METHODS' => array(\n"; - $src .= $i[3] . "),\n"; - $src .= $i[2] . "'SYMBOLS' => array(\n"; - foreach($lang['ld']['sy'] as $idx_kw => $tmp_kw) { - $src .= $i[3] . ((int)$idx_kw) . " => " . str_to_phpstring($tmp_kw['style']) . ",\n"; - } - $src .= $i[3] . "),\n"; - $src .= $i[2] . "'REGEXPS' => array(\n"; - $src .= $i[3] . "),\n"; - $src .= $i[2] . "'SCRIPT' => array(\n"; - $src .= $i[3] . "),\n"; - $src .= $i[2] . "),\n"; - - //Keyword Documentation - $src .= $i[1] . "'URLS' => array(\n"; - foreach($lang['ld']['kw'] as $idx_kw => $tmp_kw) { - $src .= $i[2] . ((int)$idx_kw) . " => " . str_to_phpstring($tmp_kw['docs']) . ",\n"; - } - $src .= $i[2] . "),\n"; - $src .= $i[1] . "'OOLANG' => false,\n"; - $src .= $i[1] . "'OBJECT_SPLITTERS' => array(\n"; - $src .= $i[2] . "),\n"; - $src .= $i[1] . "'REGEXPS' => array(\n"; - $src .= $i[2] . "),\n"; - $src .= $i[1] . "'STRICT_MODE_APPLIES' => GESHI_MAYBE,\n"; - $src .= $i[1] . "'SCRIPT_DELIMITERS' => array(\n"; - $src .= $i[2] . "),\n"; - $src .= $i[1] . "'HIGHLIGHT_STRICT_BLOCK' => array(\n"; - $src .= $i[2] . "),\n"; - $src .= $i[1] . "'TAB_WIDTH' => 4\n"; - - $src .= <<<GESHI_LANGFILE_FOOTER -); -GESHI_LANGFILE_FOOTER; - - //Reduce source ... - $src = preg_replace('/array\(\s*\)/s', 'array()', $src); - $src = preg_replace('/\,(\s*\))/s', '\1', $src); - $src = preg_replace('/\s+$/m', '', $src); - - return $src; -} diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 010c471c..75ed529e 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -75,7 +75,7 @@ $wgConfigRegistry = array( * MediaWiki version number * @since 1.2 */ -$wgVersion = '1.25.1'; +$wgVersion = '1.25.2'; /** * Name of the site. It must be changed in LocalSettings.php diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index 240cb97b..45cd7ea5 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -3342,7 +3342,7 @@ function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1, // Removing leading zeros works around broken base detection code in // some PHP versions (see <https://bugs.php.net/bug.php?id=50175> and // <https://bugs.php.net/bug.php?id=55398>). - $result = gmp_strval( gmp_init( ltrim( $input, '0' ), $sourceBase ), $destBase ); + $result = gmp_strval( gmp_init( ltrim( $input, '0' ) ?: '0', $sourceBase ), $destBase ); } elseif ( extension_loaded( 'bcmath' ) && ( $engine == 'auto' || $engine == 'bcmath' ) ) { $decimal = '0'; foreach ( str_split( strtolower( $input ) ) as $char ) { diff --git a/includes/Setup.php b/includes/Setup.php index dd8fbf8a..b3bf0fca 100644 --- a/includes/Setup.php +++ b/includes/Setup.php @@ -232,9 +232,7 @@ if ( $wgUseInstantCommons ) { $wgForeignFileRepos[] = array( 'class' => 'ForeignAPIRepo', 'name' => 'wikimediacommons', - 'apibase' => WebRequest::detectProtocol() === 'https' ? - 'https://commons.wikimedia.org/w/api.php' : - 'http://commons.wikimedia.org/w/api.php', + 'apibase' => 'https://commons.wikimedia.org/w/api.php', 'hashLevels' => 2, 'fetchDescription' => true, 'descriptionCacheExpiry' => 43200, diff --git a/includes/User.php b/includes/User.php index 3cd69fdc..8ea491ce 100644 --- a/includes/User.php +++ b/includes/User.php @@ -2204,6 +2204,8 @@ class User implements IDBAccessObject { * page. Ignored if null or !$val. */ public function setNewtalk( $val, $curRev = null ) { + global $wgMemc; + if ( wfReadOnly() ) { return; } @@ -2218,7 +2220,6 @@ class User implements IDBAccessObject { $field = 'user_id'; $id = $this->getId(); } - global $wgMemc; if ( $val ) { $changed = $this->updateNewtalk( $field, $id, $curRev ); @@ -2270,37 +2271,13 @@ class User implements IDBAccessObject { } /** - * Immediately touch the user data cache for this account. - * Updates user_touched field, and removes account data from memcached - * for reload on the next hit. + * Immediately touch the user data cache for this account + * + * Calls touch() and removes account data from memcached */ public function invalidateCache() { - if ( wfReadOnly() ) { - return; - } - $this->load(); - if ( $this->mId ) { - $this->mTouched = $this->newTouchedTimestamp(); - - $dbw = wfGetDB( DB_MASTER ); - $userid = $this->mId; - $touched = $this->mTouched; - $method = __METHOD__; - $dbw->onTransactionIdle( function () use ( $dbw, $userid, $touched, $method ) { - // Prevent contention slams by checking user_touched first - $encTouched = $dbw->addQuotes( $dbw->timestamp( $touched ) ); - $needsPurge = $dbw->selectField( 'user', '1', - array( 'user_id' => $userid, 'user_touched < ' . $encTouched ) ); - if ( $needsPurge ) { - $dbw->update( 'user', - array( 'user_touched' => $dbw->timestamp( $touched ) ), - array( 'user_id' => $userid, 'user_touched < ' . $encTouched ), - $method - ); - } - } ); - $this->clearSharedCache(); - } + $this->touch(); + $this->clearSharedCache(); } /** diff --git a/includes/api/ApiBase.php b/includes/api/ApiBase.php index 5a1eb995..6c33da57 100644 --- a/includes/api/ApiBase.php +++ b/includes/api/ApiBase.php @@ -1192,7 +1192,7 @@ abstract class ApiBase extends ContextSource { $this->dieUsage( 'Specified user does not exist', 'bad_wlowner' ); } $token = $user->getOption( 'watchlisttoken' ); - if ( $token == '' || $token != $params['token'] ) { + if ( $token == '' || !hash_equals( $token, $params['token'] ) ) { $this->dieUsage( 'Incorrect watchlist token provided -- please set a correct token in Special:Preferences', 'bad_wltoken' diff --git a/includes/api/ApiOpenSearch.php b/includes/api/ApiOpenSearch.php index a93b7cc6..0adb464d 100644 --- a/includes/api/ApiOpenSearch.php +++ b/includes/api/ApiOpenSearch.php @@ -384,13 +384,25 @@ class ApiOpenSearchFormatJson extends ApiFormatJson { public function execute() { if ( !$this->getResult()->getResultData( 'error' ) ) { - $warnings = $this->getResult()->removeValue( 'warnings', null ); + $result = $this->getResult(); + + // Ignore warnings or treat as errors, as requested + $warnings = $result->removeValue( 'warnings', null ); if ( $this->warningsAsError && $warnings ) { $this->dieUsage( 'Warnings cannot be represented in OpenSearch JSON format', 'warnings', 0, array( 'warnings' => $warnings ) ); } + + // Ignore any other unexpected keys (e.g. from $wgDebugToolbar) + $remove = array_keys( array_diff_key( + $result->getResultData(), + array( 0 => 'search', 1 => 'terms', 2 => 'descriptions', 3 => 'urls' ) + ) ); + foreach ( $remove as $key ) { + $result->removeValue( $key, null ); + } } parent::execute(); diff --git a/includes/api/ApiQueryImageInfo.php b/includes/api/ApiQueryImageInfo.php index 94b4bbdb..095e5dda 100644 --- a/includes/api/ApiQueryImageInfo.php +++ b/includes/api/ApiQueryImageInfo.php @@ -592,7 +592,10 @@ class ApiQueryImageInfo extends ApiQueryBase { $retval = array(); if ( is_array( $metadata ) ) { foreach ( $metadata as $key => $value ) { - $r = array( 'name' => $key ); + $r = array( + 'name' => $key, + ApiResult::META_BC_BOOLS => array( 'value' ), + ); if ( is_array( $value ) ) { $r['value'] = self::processMetaData( $value, $result ); } else { diff --git a/includes/exception/MWExceptionHandler.php b/includes/exception/MWExceptionHandler.php index c50b6c8c..a58705f6 100644 --- a/includes/exception/MWExceptionHandler.php +++ b/includes/exception/MWExceptionHandler.php @@ -486,6 +486,8 @@ TXT; if ( $json !== false ) { wfDebugLog( 'exception-json', $json, 'private' ); } + + Hooks::run( 'LogException', array( $e, false ) ); } } @@ -501,7 +503,8 @@ TXT; // The set_error_handler callback is independent from error_reporting. // Filter out unwanted errors manually (e.g. when wfSuppressWarnings is active). - if ( ( error_reporting() & $e->getSeverity() ) !== 0 ) { + $suppressed = ( error_reporting() & $e->getSeverity() ) === 0; + if ( !$suppressed ) { $log = self::getLogMessage( $e ); if ( $wgLogExceptionBacktrace ) { wfDebugLog( $channel, $log . "\n" . $e->getTraceAsString() ); @@ -515,5 +518,7 @@ TXT; if ( $json !== false ) { wfDebugLog( "$channel-json", $json, 'private' ); } + + Hooks::run( 'LogException', array( $e, $suppressed ) ); } } diff --git a/includes/filerepo/ForeignAPIRepo.php b/includes/filerepo/ForeignAPIRepo.php index 7ead968f..3c031921 100644 --- a/includes/filerepo/ForeignAPIRepo.php +++ b/includes/filerepo/ForeignAPIRepo.php @@ -521,6 +521,7 @@ class ForeignAPIRepo extends FileRepo { if ( $status->isOK() ) { return $req->getContent(); } else { + wfDebug( "ForeignAPIRepo: ERROR on GET: " . $status->getWikiText() ); return false; } } diff --git a/includes/installer/DatabaseUpdater.php b/includes/installer/DatabaseUpdater.php index 702f850c..70707901 100644 --- a/includes/installer/DatabaseUpdater.php +++ b/includes/installer/DatabaseUpdater.php @@ -145,15 +145,26 @@ abstract class DatabaseUpdater { return; // already loaded } $vars = Installer::getExistingLocalSettings(); - if ( !$vars ) { - return; // no LocalSettings found + + $registry = ExtensionRegistry::getInstance(); + $queue = $registry->getQueue(); + // Don't accidentally load extensions in the future + $registry->clearQueue(); + + // This will automatically add "AutoloadClasses" to $wgAutoloadClasses + $data = $registry->readFromQueue( $queue ); + $hooks = array( 'wgHooks' => array( 'LoadExtensionSchemaUpdates' => array() ) ); + if ( isset( $data['globals']['wgHooks']['LoadExtensionSchemaUpdates'] ) ) { + $hooks = $data['globals']['wgHooks']['LoadExtensionSchemaUpdates']; } - if ( !isset( $vars['wgHooks'] ) || !isset( $vars['wgHooks']['LoadExtensionSchemaUpdates'] ) ) { - return; + if ( $vars && isset( $vars['wgHooks']['LoadExtensionSchemaUpdates'] ) ) { + $hooks = array_merge_recursive( $hooks, $vars['wgHooks']['LoadExtensionSchemaUpdates'] ); } global $wgHooks, $wgAutoloadClasses; - $wgHooks['LoadExtensionSchemaUpdates'] = $vars['wgHooks']['LoadExtensionSchemaUpdates']; - $wgAutoloadClasses = $wgAutoloadClasses + $vars['wgAutoloadClasses']; + $wgHooks['LoadExtensionSchemaUpdates'] = $hooks; + if ( $vars && isset( $vars['wgAutoloadClasses'] ) ) { + $wgAutoloadClasses += $vars['wgAutoloadClasses']; + } } /** diff --git a/includes/registration/ExtensionProcessor.php b/includes/registration/ExtensionProcessor.php index 7f738661..bb8fb329 100644 --- a/includes/registration/ExtensionProcessor.php +++ b/includes/registration/ExtensionProcessor.php @@ -81,6 +81,7 @@ class ExtensionProcessor implements Processor { 'config', 'ParserTestFiles', 'AutoloadClasses', + 'manifest_version', ); /** diff --git a/includes/registration/ExtensionRegistry.php b/includes/registration/ExtensionRegistry.php index 2558f7e2..4e690aa8 100644 --- a/includes/registration/ExtensionRegistry.php +++ b/includes/registration/ExtensionRegistry.php @@ -109,6 +109,24 @@ class ExtensionRegistry { } /** + * Get the current load queue. Not intended to be used + * outside of the installer. + * + * @return array + */ + public function getQueue() { + return $this->queued; + } + + /** + * Clear the current load queue. Not intended to be used + * outside of the installer. + */ + public function clearQueue() { + $this->queued = array(); + } + + /** * Process a queue of extensions and return their extracted data * * @param array $queue keys are filenames, values are ignored @@ -143,7 +161,7 @@ class ExtensionRegistry { protected function exportExtractedData( array $info ) { foreach ( $info['globals'] as $key => $val ) { - if ( !isset( $GLOBALS[$key] ) || !$GLOBALS[$key] ) { + if ( !isset( $GLOBALS[$key] ) || ( is_array( $GLOBALS[$key] ) && !$GLOBALS[$key] ) ) { $GLOBALS[$key] = $val; } elseif ( $key === 'wgHooks' || $key === 'wgExtensionCredits' ) { // Special case $wgHooks and $wgExtensionCredits, which require a recursive merge. diff --git a/includes/specials/SpecialDeletedContributions.php b/includes/specials/SpecialDeletedContributions.php index 9e4bbbe5..fb85942d 100644 --- a/includes/specials/SpecialDeletedContributions.php +++ b/includes/specials/SpecialDeletedContributions.php @@ -479,7 +479,7 @@ class DeletedContributionsPage extends SpecialPage { if ( ( $id !== null ) || ( $id === null && IP::isIPAddress( $nt->getText() ) ) ) { # Block / Change block / Unblock links if ( $this->getUser()->isAllowed( 'block' ) ) { - if ( $userObj->isBlocked() ) { + if ( $userObj->isBlocked() && $userObj->getBlock()->getType() !== Block::TYPE_AUTO ) { $tools[] = Linker::linkKnown( # Change block link SpecialPage::getTitleFor( 'Block', $nt->getDBkey() ), $this->msg( 'change-blocklink' )->escaped() diff --git a/includes/specials/SpecialVersion.php b/includes/specials/SpecialVersion.php index c1a95939..9a1c5e5d 100644 --- a/includes/specials/SpecialVersion.php +++ b/includes/specials/SpecialVersion.php @@ -265,8 +265,8 @@ class SpecialVersion extends SpecialPage { $version = $wgVersion . ' ' . wfMessage( 'version-svn-revision', - isset( $info['directory-rev'] ) ? $info['directory-rev'] : '', - $info['checkout-rev'] + isset( $svnInfo['directory-rev'] ) ? $svnInfo['directory-rev'] : '', + isset( $svnInfo['checkout-rev'] ) ? $svnInfo['checkout-rev'] : '' )->text(); } diff --git a/languages/i18n/af.json b/languages/i18n/af.json index e9547e93..5957bda7 100644 --- a/languages/i18n/af.json +++ b/languages/i18n/af.json @@ -1450,7 +1450,7 @@ "nmembers": "$1 {{PLURAL:$1|lid|lede}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|lid|lede}}", "nrevisions": "$1 {{PLURAL:$1|weergawe|weergawes}}", - "nviews": "$1 {{PLURAL:$1|keer|kere}} aangevra", + "nimagelinks": "Gebruik op {{PLURAL:$1|een bladsy|$1 bladsye}}", "ntransclusions": "gebruik op {{PLURAL:$1|een bladsy|$1 bladsye}}", "specialpage-empty": "Die verslag lewer geen resultate nie.", diff --git a/languages/i18n/am.json b/languages/i18n/am.json index 0a96eef7..38dbe775 100644 --- a/languages/i18n/am.json +++ b/languages/i18n/am.json @@ -1058,7 +1058,7 @@ "nlinks": "$1 መያያዣዎች", "nmembers": "$1 {{PLURAL:$1|መጣጥፍ|መጣጥፎች}}", "nrevisions": "$1 ለውጦች", - "nviews": "$1 {{PLURAL:$1|ዕይታ|ዕይታዎች}}", + "nimagelinks": "በ$1 {{PLURAL:$1|ገጽ|ገጾች}} ላይ ይጠቀማል።", "ntransclusions": "በ$1 {{PLURAL:$1|ገጽ|ገጾች}} ይጠቀማል።", "specialpage-empty": "(ይህ ገጽ ባዶ ነው።)", diff --git a/languages/i18n/an.json b/languages/i18n/an.json index 56586417..828bd49a 100644 --- a/languages/i18n/an.json +++ b/languages/i18n/an.json @@ -1256,7 +1256,7 @@ "nlinks": "$1 {{PLURAL:$1|vinclo|vinclos}}", "nmembers": "$1 {{PLURAL:$1|miembro|miembros}}", "nrevisions": "$1 {{PLURAL:$1|versión|versions}}", - "nviews": "$1 {{PLURAL:$1|vesita|vesitas}}", + "nimagelinks": "S'emplega en $1 {{PLURAL:$1|pachina|pachinas}}", "ntransclusions": "s'emplega en $1 {{PLURAL:$1|pachina|pachinas}}", "specialpage-empty": "Ista pachina ye bueda.", diff --git a/languages/i18n/ar.json b/languages/i18n/ar.json index 0cb3df83..aaf21537 100644 --- a/languages/i18n/ar.json +++ b/languages/i18n/ar.json @@ -1548,7 +1548,7 @@ "nmembers": "{{PLURAL:$1|لا أعضاء|عضو واحد|عضوان|$1 أعضاء|$1 عضوا|$1 عضو}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|عضو|أعضاء}}", "nrevisions": "{{PLURAL:$1|لا مراجعات|مراجعة واحدة|مراجعتان|$1 مراجعات|$1 مراجعة}}", - "nviews": "{{PLURAL:$1|مشاهدة واحدة|مشاهدتان|$1 مشاهدات|$1 مشاهدة}}", + "nimagelinks": "مستخدم في {{PLURAL:$1||صفحة واحدة|صفحتين|$1 صفحات|$1 صفحة}}", "ntransclusions": "مستخدم في {{PLURAL:$1||صفحة واحدة|صفحتين|$1 صفحات|$1 صفحة}}", "specialpage-empty": "لا توجد نتائج لهذا التقرير.", diff --git a/languages/i18n/arc.json b/languages/i18n/arc.json index befb4b2c..86cbb3c9 100644 --- a/languages/i18n/arc.json +++ b/languages/i18n/arc.json @@ -783,7 +783,7 @@ "nlinks": "$1 {{PLURAL:$1|ܐܣܘܪܐ|ܐܣܘܪ̈ܐ}}", "nmembers": "$1 {{PLURAL:$1|ܗܕܡܐ|ܗܕ̈ܡܐ}}", "nrevisions": "$1 {{PLURAL:$1|ܬܢܝܬܐ|ܬܢܝܬ̈ܐ }}", - "nviews": "$1 {{PLURAL:$1|ܚܘܘܝܐ|ܚܘܘܝ̈ܐ}}", + "specialpage-empty": "ܠܝܬ ܦܠܛ̈ܐ ܒܬܫܪܪܐ ܗܢܐ.", "lonelypages": "ܦܐܬܬ̈ܐ ܝܬܡܬ̈ܐ", "uncategorizedpages": "ܦܐܬܬ̈ܐ ܠܐ ܣܕܝܪ̈ܬܐ", diff --git a/languages/i18n/arn.json b/languages/i18n/arn.json index 5e55cf65..f610d505 100644 --- a/languages/i18n/arn.json +++ b/languages/i18n/arn.json @@ -450,7 +450,7 @@ "withoutinterwiki-submit": "Pegelpe", "nbytes": "$1 {{PLURAL:$1 byte}}", "nmembers": "$1 {{PLURAL:$1|koneltulu}}", - "nviews": "$1 {{PLURAL:$1|pen|pen}}", + "prefixindex": "Kom wülngiñ engu wüne konkülelu nemül", "shortpages": "Pichi pakina", "usercreated": "{{GENDER:$3|Dewmangey}} $1, $2 mew", diff --git a/languages/i18n/ary.json b/languages/i18n/ary.json index 79e12cc3..9c96f9f0 100644 --- a/languages/i18n/ary.json +++ b/languages/i18n/ary.json @@ -1062,7 +1062,7 @@ "nlinks": "$1 {{PLURAL:$1|l-wṣla|dl-wṣlaṫ}}", "nmembers": "$1 {{PLURAL:$1|Ĝoḍw|Aĝḍa'}}", "nrevisions": "$1 {{PLURAL:$1|l-ṃoṛajaĝa|dl-ṃoṛajaĝaṫ}}", - "nviews": "$1 {{PLURAL:$1|l-ṃoċahada|dl-ṃoċahadaṫ}}", + "nimagelinks": "mosṫĥmal f-$1 {{PLURAL:$1|ṣ-ṣfḫa|dṣ-ṣfaḫi}}", "ntransclusions": "mosṫĥmal f-$1 {{PLURAL:$1|ṣ-ṣfḫa|dṣ-ṣfaḫi}}", "lonelypages": "sfahi itima", diff --git a/languages/i18n/arz.json b/languages/i18n/arz.json index adf0eed6..8d64b4e3 100644 --- a/languages/i18n/arz.json +++ b/languages/i18n/arz.json @@ -1168,7 +1168,7 @@ "nlinks": "{{PLURAL:$1|وصله واحده|وصلتين|$1 وصلات|$1 وصله}}", "nmembers": "$1 {{PLURAL:$1|عضو|اعضاء}}", "nrevisions": "{{PLURAL:$1|تعديل وحيد|تعديلين|$1 تعديلات|$1 تعديل|$1}}", - "nviews": "{{PLURAL:$1|مشاهدة واحدة|مشاهدتين|$1 مشاهدات|$1 مشاهدة}}", + "specialpage-empty": "مافيش نتايج للتقرير دا.", "lonelypages": "صفحات يتيمه", "lonelypagestext": "الصفحات دى ماعندهاش لينكات أو تضمينات من الصفحات التانية فى {{SITENAME}}.", diff --git a/languages/i18n/as.json b/languages/i18n/as.json index 6d86b3fb..04906b4c 100644 --- a/languages/i18n/as.json +++ b/languages/i18n/as.json @@ -1472,7 +1472,7 @@ "nmembers": "{{PLURAL:|$1 টা প্ৰবন্ধ বা উপশ্ৰেণী|$1 টা প্ৰবন্ধ বা উপশ্ৰেণী}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|জন সদস্য}}", "nrevisions": "$1টা {{PLURAL:$1|সংশোধন|সংশোধন}}", - "nviews": "$1 {{PLURAL:$1|টা দৰ্শন|টা দৰ্শন}}", + "nimagelinks": "$1 {{PLURAL:$1|টা পৃষ্ঠাত}} ব্যৱহৃত", "ntransclusions": "$1 {{PLURAL:$1|টা পৃষ্ঠাত}} ব্যৱহৃত", "specialpage-empty": "এই বিৱৰণৰ কোনো ফলাফল নাই ।", diff --git a/languages/i18n/ast.json b/languages/i18n/ast.json index 1b0c0899..fdc43d69 100644 --- a/languages/i18n/ast.json +++ b/languages/i18n/ast.json @@ -1509,7 +1509,7 @@ "nmembers": "$1 {{PLURAL:$1|miembru|miembros}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|miembru|miembros}}", "nrevisions": "$1 {{PLURAL:$1|revisión|revisiones}}", - "nviews": "$1 {{PLURAL:$1|vista|vistes}}", + "nimagelinks": "Usao en $1 {{PLURAL:$1|páxina|páxines}}", "ntransclusions": "usao en $1 {{PLURAL:$1|páxina|páxines}}", "specialpage-empty": "Nun hai resultaos nestos momentos.", diff --git a/languages/i18n/avk.json b/languages/i18n/avk.json index 40914c00..a9f3704b 100644 --- a/languages/i18n/avk.json +++ b/languages/i18n/avk.json @@ -930,7 +930,7 @@ "nlinks": "$1 {{PLURAL:$1|gluyasiki|gluyasiki}}", "nmembers": "$1 {{PLURAL:$1|bewik}}", "nrevisions": "$1 betara", - "nviews": "$1 rupera", + "specialpage-empty": "Mek trasiks tori bat munsteks.", "lonelypages": "Avuwikaf bueem", "lonelypagestext": "Batu bu tid gluyasikiiskafu male aru bu koe {{SITENAME}}.", diff --git a/languages/i18n/awa.json b/languages/i18n/awa.json index 218fa2e3..a6d0561d 100644 --- a/languages/i18n/awa.json +++ b/languages/i18n/awa.json @@ -1472,7 +1472,7 @@ "nmembers": "$1 {{PLURAL:$1|सदस्य}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|सदस्य}}", "nrevisions": "$1 {{PLURAL:$1|अवतरण}}", - "nviews": "{{PLURAL:$1|एक|$1}} दाइ देखि गा है", + "nimagelinks": "$1 {{PLURAL:$1|पन्ना|पन्नन्}} पे प्रयुक्त", "ntransclusions": "$1 {{PLURAL:$1|पन्ना|पन्नन}} पे प्रयुक्त", "specialpage-empty": "इ ब्यौरा कय खर्तीन कवनो परिणाम नाई है।", diff --git a/languages/i18n/az.json b/languages/i18n/az.json index dcc2dbc8..42b4f260 100644 --- a/languages/i18n/az.json +++ b/languages/i18n/az.json @@ -1240,7 +1240,7 @@ "nlinks": "$1 {{PLURAL:$1|keçid|keçidlər}}", "nmembers": "$1 {{PLURAL:$1|üzv|üzv}}", "nrevisions": "$1 dəyişiklik", - "nviews": "$1 baxış", + "nimagelinks": "$1 səhifədə istifadə olunmur", "ntransclusions": "$1 səhifədə istifadə olunur", "specialpage-empty": "Bu səhifə boşdur.", diff --git a/languages/i18n/azb.json b/languages/i18n/azb.json index 40a7b4cd..e0b28142 100644 --- a/languages/i18n/azb.json +++ b/languages/i18n/azb.json @@ -1440,7 +1440,7 @@ "nmembers": "{{PLURAL:$1|بیر|$1}} عوضو", "nmemberschanged": "$1 → $2 {{PLURAL:$2|عۆضو}}", "nrevisions": "{{PLURAL:$1|بیر|$1}} نوسخه", - "nviews": "{{PLURAL:$1|بیر|$1}} گؤرونوش", + "nimagelinks": "$1 ده{{PLURAL:$1|صحیفهده}}ایستیفاده اولونمور", "ntransclusions": "$1 ده{{PLURAL:$1|صحیفهده}}ایستیفاده اولونور", "specialpage-empty": "بو صحیفه بوشدور", diff --git a/languages/i18n/ba.json b/languages/i18n/ba.json index a7482099..fb4a2fd2 100644 --- a/languages/i18n/ba.json +++ b/languages/i18n/ba.json @@ -1411,7 +1411,7 @@ "nlinks": "$1 {{PLURAL:$1|һылтанма}}", "nmembers": "$1 {{PLURAL:$1|объект}}", "nrevisions": "$1 {{PLURAL:$1|1=өлгө|өлгө}}", - "nviews": "$1 {{PLURAL:$1|ҡарап сығыу}}", + "nimagelinks": "$1 {{PLURAL:$1|биттә}} ҡулланыла", "ntransclusions": "$1 {{PLURAL:$1|биттә}} ҡулланыла", "specialpage-empty": "Был һорау өсөн һөҙөмтәләр юҡ.", diff --git a/languages/i18n/bar.json b/languages/i18n/bar.json index 8bfc90e8..0145e17b 100644 --- a/languages/i18n/bar.json +++ b/languages/i18n/bar.json @@ -717,7 +717,7 @@ "nlinks": "{{PLURAL:$1|a Link|$1 Links}}", "nmembers": "{{PLURAL:$1|1 Eindrog|$1 Eindreg}}", "nrevisions": "{{PLURAL:$1|oah Beorwatung|$1 Beorwatungen}}", - "nviews": "{{PLURAL:$1|1 Åbfråg|$1 Åbfrång}}", + "uncategorizedpages": "Néd kategorisirde Seiten", "uncategorizedcategories": "Néd kategorisirde Kategorien", "uncategorizedimages": "Néd kategorisirde Daatein", diff --git a/languages/i18n/bcc.json b/languages/i18n/bcc.json index 9f056214..ab3e2121 100644 --- a/languages/i18n/bcc.json +++ b/languages/i18n/bcc.json @@ -1480,7 +1480,7 @@ "nmembers": "$1 {{PLURAL:$1|member|اعضا}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2| عضو|عضو}}", "nrevisions": "$1 {{PLURAL:$1|بازبینی|بازبینی ان}}", - "nviews": "$1 {{PLURAL:$1|دیستن|دیستن}}", + "nimagelinks": "$1 × $2, $3 {{PLURAL:$3|صفحه|صفحات}}", "ntransclusions": "بی $1 {{PLURAL:$1|تاکدیم|تاکدیم}} استپاده بوته", "specialpage-empty": "په ای گزارش هچ نتیجه ای نیست ان.", diff --git a/languages/i18n/bcl.json b/languages/i18n/bcl.json index e5a69d91..2f8d17e0 100644 --- a/languages/i18n/bcl.json +++ b/languages/i18n/bcl.json @@ -1446,7 +1446,7 @@ "nmembers": "$1 {{PLURAL:$1|miyembro|mga miyembro}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|miyembro|mga miyembro}}", "nrevisions": "$1 {{PLURAL:$1|pagpakarhay|mga pagpakarhay}}", - "nviews": "$1 {{PLURAL:$1|hiling|mga hiling}}", + "nimagelinks": "Ginamit sa $1 {{PLURAL:$1|pahina|mga pahina}}", "ntransclusions": "ginamit sa $1 {{PLURAL:$1|pahina|mga pahina}}", "specialpage-empty": "Mayong mga resulta para sa report na ini.", diff --git a/languages/i18n/be-tarask.json b/languages/i18n/be-tarask.json index b3418a17..d4ce1646 100644 --- a/languages/i18n/be-tarask.json +++ b/languages/i18n/be-tarask.json @@ -1514,7 +1514,7 @@ "nmembers": "$1 {{PLURAL:$1|элемэнт|элемэнты|элемэнтаў}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|элемэнт|элемэнты|элемэнтаў}}", "nrevisions": "$1 {{PLURAL:$1|вэрсія|вэрсіі|вэрсіяў}}", - "nviews": "$1 {{PLURAL:$1|прагляд|прагляды|праглядаў}}", + "nimagelinks": "Выкарыстоўваецца на $1 {{PLURAL:$1|старонцы|старонках|старонках}}", "ntransclusions": "выкарыстоўваецца на $1 {{PLURAL:$1|старонцы|старонках|старонках}}", "specialpage-empty": "Гэтая старонка — пустая.", diff --git a/languages/i18n/be.json b/languages/i18n/be.json index 836a20c6..2c6b6dd0 100644 --- a/languages/i18n/be.json +++ b/languages/i18n/be.json @@ -1494,7 +1494,7 @@ "nmembers": "$1 {{PLURAL:$1|складнік|складнікі|складнікаў}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|складнік|складнікі|складнік}}", "nrevisions": "$1 {{PLURAL:$1|версія|версіі|версій}}", - "nviews": "$1 {{PLURAL:$1|паказ|паказаў}}", + "nimagelinks": "Выкарыстоўваецца на $1 {{PLURAL:$1|старонцы|старонках|старонках}}", "ntransclusions": "выкарыстоўваецца на $1 {{PLURAL:$1|старонцы|старонках|старонках}}", "specialpage-empty": "Няма вынікаў для гэтай справаздачы.", diff --git a/languages/i18n/bg.json b/languages/i18n/bg.json index b51ddbfd..2b45b487 100644 --- a/languages/i18n/bg.json +++ b/languages/i18n/bg.json @@ -1439,7 +1439,7 @@ "nlinks": "$1 {{PLURAL:$1|препратка|препратки}}", "nmembers": "$1 {{PLURAL:$1|член|члена}}", "nrevisions": "$1 {{PLURAL:$1|версия|версии}}", - "nviews": "$1 {{PLURAL:$1|преглед|прегледа}}", + "nimagelinks": "Използва се в $1 {{PLURAL:$1|страница|страници}}", "ntransclusions": "използва се в $1 {{PLURAL:$1|страница|страници}}", "specialpage-empty": "Страницата е празна.", diff --git a/languages/i18n/bgn.json b/languages/i18n/bgn.json index e473177f..ff527bda 100644 --- a/languages/i18n/bgn.json +++ b/languages/i18n/bgn.json @@ -1349,7 +1349,7 @@ "nmembers": "$1 {{PLURAL:$1|عضو|عضو}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2| عضو|عضو}}", "nrevisions": "$1 {{PLURAL:$1|نخسه|نخسه}}", - "nviews": "$1 {{PLURAL:$1|دیست|دیست}}", + "nimagelinks": "استفاده بوته بی $1 {{PLURAL:$1|تاکدیم|تاکدیم}} ئی تا", "ntransclusions": "استفاده بوته بی $1 {{PLURAL:$1|تاکدیم|تاکدیم}} ئی تا", "specialpage-empty": "نتیجه په راپور ئا موجود نه اینت.", diff --git a/languages/i18n/bjn.json b/languages/i18n/bjn.json index cffaf52a..d9efb1a0 100644 --- a/languages/i18n/bjn.json +++ b/languages/i18n/bjn.json @@ -1268,7 +1268,7 @@ "nlinks": "$1 {{PLURAL:$1|tautan|tautan}}", "nmembers": "$1 {{PLURAL:$1|angguta|angguta}}", "nrevisions": "$1 {{PLURAL:$1|ralatan|raralatan}}", - "nviews": "dilihat $1 {{PLURAL:$1|kali|kali}}", + "nimagelinks": "Diguna'akan pada $1 {{PLURAL:$1|tungkaran|tutungkaran}}", "ntransclusions": "dipuruk pada $1 {{PLURAL:$1|tungkaran|tutungkaran}}", "specialpage-empty": "Kadada kulihan gasan lapuran ngini.", diff --git a/languages/i18n/bn.json b/languages/i18n/bn.json index 5e079d3d..1abbc357 100644 --- a/languages/i18n/bn.json +++ b/languages/i18n/bn.json @@ -1514,7 +1514,7 @@ "nmembers": "$1টি {{PLURAL:$1|সদস্য}}", "nmemberschanged": "$1 জন → $2 জন {{PLURAL:$2|সদস্য}}", "nrevisions": "$1 {{PLURAL:$1|সংশোধন|সংশোধনসমূহ}}", - "nviews": "$1 {{PLURAL:$1|বার দেখা হয়েছে|বার দেখা হয়েছে}}", + "nimagelinks": "$1 {{PLURAL:$1|টি পাতায়| টি পাতায়}} ব্যবহৃত", "ntransclusions": "$1 {{PLURAL:$1|টি পাতায়| টি পাতায়}} ব্যবহৃত", "specialpage-empty": "এই রিপোর্টের জন্য কোন ফলাফল নেই।", diff --git a/languages/i18n/br.json b/languages/i18n/br.json index 569dbef4..971b1927 100644 --- a/languages/i18n/br.json +++ b/languages/i18n/br.json @@ -1474,7 +1474,7 @@ "nmembers": "$1 {{PLURAL:$1|elfenn|elfenn}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|ezel}}", "nrevisions": "$1 {{PLURAL:$1|stumm|stumm}}", - "nviews": "$1 {{PLURAL:$1|selladenn|selladenn}}", + "nimagelinks": "Implijet e $1 {{PLURAL:$1|pajenn|pajenn}}", "ntransclusions": "implijet e $1 {{PLURAL:$1|pajenn|pajenn}}", "specialpage-empty": "Goullo eo ar bajenn-mañ.", diff --git a/languages/i18n/bs.json b/languages/i18n/bs.json index 086f06a5..ae36d785 100644 --- a/languages/i18n/bs.json +++ b/languages/i18n/bs.json @@ -1473,7 +1473,7 @@ "nlinks": "$1 {{PLURAL:$1|veza|veze}}", "nmembers": "$1 {{PLURAL:$1|član|članova}}", "nrevisions": "$1 {{PLURAL:$1|revizija|revizije|revizija}}", - "nviews": "$1 {{PLURAL:$1|pregled|pregleda}}", + "nimagelinks": "Koristi se na $1 {{PLURAL:$1|stranici|stranice|stranica}}", "ntransclusions": "koristi se na $1 {{PLURAL:$1|stranici|stranice|stranica}}", "specialpage-empty": "Nepostoje rezultati za ovaj izvještaj.", diff --git a/languages/i18n/ca.json b/languages/i18n/ca.json index 0d5f6fb2..5c3ddf9b 100644 --- a/languages/i18n/ca.json +++ b/languages/i18n/ca.json @@ -1563,7 +1563,7 @@ "nmembers": "$1 {{PLURAL:$1|element|elements}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|element|elements}}", "nrevisions": "$1 {{PLURAL:$1|revisió|revisions}}", - "nviews": "$1 {{PLURAL:$1|visita|visites}}", + "nimagelinks": "S'utilitza en {{PLURAL:$1|una pàgina|$1 pàgines}}", "ntransclusions": "utilitzada en {{PLURAL:$1|una pàgina|$1 pàgines}}", "specialpage-empty": "Aquesta pàgina és buida.", diff --git a/languages/i18n/ce.json b/languages/i18n/ce.json index fa759e2d..907e03dd 100644 --- a/languages/i18n/ce.json +++ b/languages/i18n/ce.json @@ -1383,7 +1383,7 @@ "nmembers": "$1 {{PLURAL:$1|хӀума|хӀумнаш}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|хӀума|хӀумнаш}}", "nrevisions": "$1 {{PLURAL:$1|верси|версеш}}", - "nviews": "$1 {{PLURAL:$1|хьажар}}", + "nimagelinks": "Лелош ю $1 {{PLURAL:$1|агӀонгахь|агӀонашкахь}}", "ntransclusions": "лелош ю $1 {{PLURAL:$1|агӀонгахь|агӀонашкахь}}", "specialpage-empty": "Дехаро хӀумма ца елла.", diff --git a/languages/i18n/ckb.json b/languages/i18n/ckb.json index 2eecb5c0..6702eb5e 100644 --- a/languages/i18n/ckb.json +++ b/languages/i18n/ckb.json @@ -1324,7 +1324,7 @@ "nlinks": "$1 {{PLURAL:$1|بەستەر|بەستەر}}", "nmembers": "$1 {{PLURAL:$1|ئەندام|ئەندام}}", "nrevisions": "$1 {{PLURAL:$1|پیاچوونەوە|پیاچوونەوە}}", - "nviews": "$1 جار {{PLURAL:$1|بینراو|بینراو}}", + "specialpage-empty": "ئەنجامێک بۆ ئەم ڕاپۆرتە نییە.", "lonelypages": "پەڕە ھەتیوەکان", "lonelypagestext": "پەڕەکانی خوارەوە لە پەڕەکانی تری {{SITENAME}}ەوە لینکیان بۆ نەدراوە و نەھێنراونەتە نێو ھیچ پەڕەیەکی تر.", diff --git a/languages/i18n/crh-cyrl.json b/languages/i18n/crh-cyrl.json index c8828d11..ae4f71c6 100644 --- a/languages/i18n/crh-cyrl.json +++ b/languages/i18n/crh-cyrl.json @@ -934,7 +934,7 @@ "nlinks": "{{PLURAL:$1|1=1 багъланты|$1 багъланты}}", "nmembers": "{{PLURAL:$1|1=1 аза|$1 аза}}", "nrevisions": "{{PLURAL:$1|1=1 версия|$1 версия}}", - "nviews": "{{PLURAL:$1|1=1 корюнюв|$1 корюнюв}}", + "specialpage-empty": "Бу соратма ичюн ич нетидже ёкъ.", "lonelypages": "Озюне ич багъланты олмагъан саифелер", "lonelypagestext": "Ашагъыдаки саифелерге {{SITENAME}} сайтындаки дигер саифелерден багъланты берильмеген, ондан да гъайры мезкюр саифелер дигер саиферлрге кирсетильмеген.", diff --git a/languages/i18n/crh-latn.json b/languages/i18n/crh-latn.json index 47e30ddf..f03d193e 100644 --- a/languages/i18n/crh-latn.json +++ b/languages/i18n/crh-latn.json @@ -934,7 +934,7 @@ "nlinks": "{{PLURAL:$1|1 bağlantı|$1 bağlantı}}", "nmembers": "{{PLURAL:$1|1 aza|$1 aza}}", "nrevisions": "{{PLURAL:$1|1 versiya|$1 versiya}}", - "nviews": "{{PLURAL:$1|1 körünüv|$1 körünüv}}", + "specialpage-empty": "Bu soratma içün iç netice yoq.", "lonelypages": "Özüne iç bağlantı olmağan saifeler", "lonelypagestext": "Aşağıdaki saifelerge {{SITENAME}} saytındaki diger saifelerden bağlantı berilmegen, ondan da ğayrı mezkür saifeler diger saiferlrge kirsetilmegen.", diff --git a/languages/i18n/cs.json b/languages/i18n/cs.json index 1fbc5b05..6a749a7c 100644 --- a/languages/i18n/cs.json +++ b/languages/i18n/cs.json @@ -1531,7 +1531,7 @@ "nmembers": "$1 {{PLURAL:$1|položka|položky|položek}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|položka|položky|položek}}", "nrevisions": "$1 {{PLURAL:$1|revize|revize|revizí}}", - "nviews": "$1 {{PLURAL:$1|návšteva|návštevy|návštev}}", + "nimagelinks": "Použit na $1 {{PLURAL:$1|stránce|stránkách}}", "ntransclusions": "použita na $1 {{PLURAL:$1|stránce|stránkách}}", "specialpage-empty": "Tomuto požadavku neodpovídají žádné záznamy.", diff --git a/languages/i18n/cv.json b/languages/i18n/cv.json index 5a78f748..a6cce665 100644 --- a/languages/i18n/cv.json +++ b/languages/i18n/cv.json @@ -644,7 +644,7 @@ "nbytes": "$1 {{PLURAL:$1|байт|байтсем}}", "ncategories": "$1 {{PLURAL:$1|категори|категорисем}}", "nlinks": "$1 {{PLURAL:$1|1=каçă|каçă}}", - "nviews": "$1 {{PLURAL:$1|пăхни|пăхнисем}}", + "specialpage-empty": "Ку страница пушă", "lonelypages": "Тăлăх страницăсем", "uncategorizedpages": "Каталогсăр страницăсем", diff --git a/languages/i18n/cy.json b/languages/i18n/cy.json index d4c32c84..6d0f23fd 100644 --- a/languages/i18n/cy.json +++ b/languages/i18n/cy.json @@ -1493,7 +1493,7 @@ "nmembers": "$1 {{PLURAL:$1|aelod|aelod|aelod|aelod|aelod|aelod}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|aelodau|aelod|aelodau}}", "nrevisions": "$1 {{PLURAL:$1|diwygiad|diwygiad|ddiwygiad|diwygiad|diwygiad|diwygiad}}", - "nviews": "$1 {{PLURAL:$1|ymweliad|ymweliad|ymweliad|ymweliad|ymweliad|ymweliad}}", + "nimagelinks": "Defnyddir ar {{PLURAL:$1||$1 dudalen|$1 dudalen|$1 tudalen|$1 thudalen|$1 tudalen}}", "ntransclusions": "defnyddir ar {{PLURAL:$1||$1 dudalen|$1 dudalen|$1 tudalen|$1 thudalen|$1 tudalen}}", "specialpage-empty": "Ni chafwyd canlyniadau i'w hadrodd.", diff --git a/languages/i18n/da.json b/languages/i18n/da.json index 6f3ab077..95a2fba9 100644 --- a/languages/i18n/da.json +++ b/languages/i18n/da.json @@ -1517,7 +1517,7 @@ "nmembers": "$1 {{PLURAL:$1|medlem|medlemmer}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|medlem|medlemmer}}", "nrevisions": "{{PLURAL:$1|1 ændring|$1 ændringer}}", - "nviews": "{{PLURAL:$1|1 visning|$1 visninger}}", + "nimagelinks": "Brugt på $1 {{PLURAL:$1|side|sider}}", "ntransclusions": "brugt på $1 {{PLURAL:$1|side|sider}}", "specialpage-empty": "Der er ingen resultater at vise.", diff --git a/languages/i18n/de.json b/languages/i18n/de.json index 98a8f550..24d12191 100644 --- a/languages/i18n/de.json +++ b/languages/i18n/de.json @@ -1583,7 +1583,7 @@ "nmembers": "{{PLURAL:$1|1 Eintrag|$1 Einträge}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|Mitglied|Mitglieder}}", "nrevisions": "{{PLURAL:$1|1 Bearbeitung|$1 Bearbeitungen}}", - "nviews": "{{PLURAL:$1|1 Abfrage|$1 Abfragen}}", + "nimagelinks": "Verwendet auf {{PLURAL:$1|einer Seite|$1 Seiten}}", "ntransclusions": "verwendet auf {{PLURAL:$1|einer Seite|$1 Seiten}}", "specialpage-empty": "Es sind aktuell keine zutreffenden Einträge vorhanden.", diff --git a/languages/i18n/diq.json b/languages/i18n/diq.json index a497dec3..e737bfc5 100644 --- a/languages/i18n/diq.json +++ b/languages/i18n/diq.json @@ -1473,7 +1473,7 @@ "nmembers": "$1 {{PLURAL:$1|eza|ezayan}}", "nmemberschanged": "$1 → $2 {{PLURAL:$1|eza|ezayan}}", "nrevisions": "$1 {{PLURAL:$1|vurnayış|vurnayışi}}", - "nviews": "$1 {{PLURAL:$1|vênayış|vênayışi}}", + "nimagelinks": "$1 {{PLURAL:$1|pele de|pelan de}} gureyeno", "ntransclusions": "$1 {{PLURAL:$1|pele de|pelan de}} gureyeno", "specialpage-empty": "Seba na rapore netice çıniyo.", diff --git a/languages/i18n/dsb.json b/languages/i18n/dsb.json index 295db5a4..7faac859 100644 --- a/languages/i18n/dsb.json +++ b/languages/i18n/dsb.json @@ -1472,7 +1472,7 @@ "nmembers": "$1 {{PLURAL:$1|zapis|zapisa|zapise}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|cłon|cłonka|cłonki|cłonkow}}", "nrevisions": "$1 {{PLURAL:$1|wobźěłanje|wobźěłani|wobźěłanja}}", - "nviews": "$1 {{PLURAL:$1|wótpšašanje|wótpšašani|wótpšašanja}}", + "nimagelinks": "Wužywa se na $1 {{PLURAL:$1|boku|bokoma|bokach|bokach}}", "ntransclusions": "wužywa se na $1 {{PLURAL:$1|boku|bokoma|bokach|bokach}}", "specialpage-empty": "Toś ten bok njewopśimjejo tuchylu žedne zapise.", diff --git a/languages/i18n/el.json b/languages/i18n/el.json index 78c64a38..d52848a6 100644 --- a/languages/i18n/el.json +++ b/languages/i18n/el.json @@ -1509,7 +1509,7 @@ "nmembers": "$1 {{PLURAL:$1|μέλος|μέλη}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|μέλος|μέλη}}", "nrevisions": "$1 {{PLURAL:$1|αναθεώρηση|αναθεωρήσεις}}", - "nviews": "$1 {{PLURAL:$1|επίσκεψη|επισκέψεις}}", + "nimagelinks": "Χρησιμοποιείται σε $1 {{PLURAL:$1|σελίδα|σελίδες}}", "ntransclusions": "χρησιμοποιείται σε $1 {{PLURAL:$1|σελίδα|σελίδες}}", "specialpage-empty": "Αυτή η σελίδα είναι κενή.", diff --git a/languages/i18n/en.json b/languages/i18n/en.json index a23c6b61..8de23acd 100644 --- a/languages/i18n/en.json +++ b/languages/i18n/en.json @@ -1602,7 +1602,7 @@ "nmembers": "$1 {{PLURAL:$1|member|members}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|member|members}}", "nrevisions": "$1 {{PLURAL:$1|revision|revisions}}", - "nviews": "$1 {{PLURAL:$1|view|views}}", + "nimagelinks": "Used on $1 {{PLURAL:$1|page|pages}}", "ntransclusions": "used on $1 {{PLURAL:$1|page|pages}}", "specialpage-empty": "There are no results for this report.", diff --git a/languages/i18n/eo.json b/languages/i18n/eo.json index 47032182..047af135 100644 --- a/languages/i18n/eo.json +++ b/languages/i18n/eo.json @@ -1532,7 +1532,7 @@ "nmembers": "{{PLURAL:$1|unu membro|$1 membroj}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|membro|membroj}}", "nrevisions": "$1 {{PLURAL:$1|versio|versioj}}", - "nviews": "{{PLURAL:$1|unufoje|$1 fojojn}}", + "nimagelinks": "Uzita en $1 {{PLURAL:$1|paĝo|paĝoj}}", "ntransclusions": "uzita en $1 {{PLURAL:$1|paĝo|paĝoj}}", "specialpage-empty": "Ne estas rezultoj por ĉi tiu raporto.", diff --git a/languages/i18n/es.json b/languages/i18n/es.json index 4f386393..330ffe13 100644 --- a/languages/i18n/es.json +++ b/languages/i18n/es.json @@ -1624,7 +1624,7 @@ "nmembers": "$1 {{PLURAL:$1|artículo|artículos}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|miembro|miembros}}", "nrevisions": "$1 {{PLURAL:$1|revisión|revisiones}}", - "nviews": "$1 {{PLURAL:$1|vista|vistas}}", + "nimagelinks": "Usado en {{PLURAL:$1|una página|$1 páginas}}", "ntransclusions": "usado en {{PLURAL:$1|una página|$1 páginas}}", "specialpage-empty": "Esta página está vacía.", diff --git a/languages/i18n/et.json b/languages/i18n/et.json index b0afd78c..dffdcfe8 100644 --- a/languages/i18n/et.json +++ b/languages/i18n/et.json @@ -1523,7 +1523,7 @@ "nmembers": "$1 {{PLURAL:$1|liige|liiget}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|liige|liiget}}", "nrevisions": "$1 {{PLURAL:$1|redaktsioon|redaktsiooni}}", - "nviews": "$1 {{PLURAL:$1|külastus|külastust}}", + "nimagelinks": "Kasutuses {{PLURAL:$1|ühel leheküljel|$1 leheküljel}}", "ntransclusions": "kasutuses {{PLURAL:$1|ühel leheküljel|$1 leheküljel}}", "specialpage-empty": "Vasteid ei leidu.", diff --git a/languages/i18n/eu.json b/languages/i18n/eu.json index 3bd40854..27a82579 100644 --- a/languages/i18n/eu.json +++ b/languages/i18n/eu.json @@ -1429,7 +1429,7 @@ "nmembers": "{{PLURAL:$1|partaide 1|$1 partaide}}", "nmemberschanged": "$1 → {{PLURAL:$2|kide $2|$2 kide}}", "nrevisions": "{{PLURAL:$1|berrikuspen 1|$1 berrikuspen}}", - "nviews": "{{PLURAL:$1|ikusketa 1|$1 ikusketa}}", + "nimagelinks": "{{PLURAL:$1|Orrialde batean erabilia|$1 orrialdetan erabilia}}", "ntransclusions": "{{PLURAL:$1|orrialde batean erabilia|$1 orrialdetan erabilia}}", "specialpage-empty": "Ez dago emaitzarik bilaketa honetarako.", diff --git a/languages/i18n/ext.json b/languages/i18n/ext.json index 427c0231..605d0f43 100644 --- a/languages/i18n/ext.json +++ b/languages/i18n/ext.json @@ -905,7 +905,7 @@ "nlinks": "$1 {{PLURAL:$1|atihu|atihus}}", "nmembers": "$1 {{PLURAL:$1|miembru|miembrus}}", "nrevisions": "$1 {{PLURAL:$1|revisión|revisionis}}", - "nviews": "$1 {{PLURAL:$1|vesita|vesitas}}", + "specialpage-empty": "Esta páhina está vacia.", "lonelypages": "Páhinas güérfanas", "lonelypagestext": "Las siguientis páginas nu están atijás (dendi otras páginas) ena {{SITENAME}}.", diff --git a/languages/i18n/fa.json b/languages/i18n/fa.json index 4ad8846f..e13f19e2 100644 --- a/languages/i18n/fa.json +++ b/languages/i18n/fa.json @@ -1551,7 +1551,7 @@ "nmembers": "$1 {{PLURAL:$1|عضو|عضو}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2| عضو|عضو}}", "nrevisions": "$1 {{PLURAL:$1|نسخه|نسخه}}", - "nviews": "$1 {{PLURAL:$1|بازدید|بازدید}}", + "nimagelinks": "مورد استفاده در $1 {{PLURAL:$1|صفحه|صفحه}}", "ntransclusions": "در $1 {{PLURAL:$1|صفحه|صفحه}} استفاده شدهاست", "specialpage-empty": "نتیجهای برای این گزارش وجود ندارد.", diff --git a/languages/i18n/fi.json b/languages/i18n/fi.json index 16ecd3eb..7e1babac 100644 --- a/languages/i18n/fi.json +++ b/languages/i18n/fi.json @@ -1547,7 +1547,7 @@ "nmembers": "$1 {{PLURAL:$1|jäsen|jäsentä}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|jäsen|jäsentä}}", "nrevisions": "$1 {{PLURAL:$1|muutos|muutosta}}", - "nviews": "$1 {{PLURAL:$1|lataus|latausta}}", + "nimagelinks": "Käytössä $1 {{PLURAL:$1|sivulla}}", "ntransclusions": "käytössä $1 {{PLURAL:$1|sivulla}}", "specialpage-empty": "Tämä sivu on tyhjä.", diff --git a/languages/i18n/fo.json b/languages/i18n/fo.json index 0bf854a6..e16a4b97 100644 --- a/languages/i18n/fo.json +++ b/languages/i18n/fo.json @@ -1391,7 +1391,7 @@ "nlinks": "$1 {{PLURAL:$1|slóð|slóðir}}", "nmembers": "$1 {{PLURAL:$1|limur|limir}}", "nrevisions": "$1 {{PLURAL:$1|versjón|versjónir}}", - "nviews": "$1 {{PLURAL:$1|skoðan|skoðanir}}", + "nimagelinks": "Brúkt á $1 {{PLURAL:$1|síðu|síðum}}", "ntransclusions": "brúkt á $1 {{PLURAL:$1|síðu|síðum}}", "specialpage-empty": "Tað eru ongi úrslit fyri hesa rapportina.", diff --git a/languages/i18n/fr.json b/languages/i18n/fr.json index 36c91e64..ca8e5bdd 100644 --- a/languages/i18n/fr.json +++ b/languages/i18n/fr.json @@ -1626,7 +1626,7 @@ "nmembers": "$1 membre{{PLURAL:$1||s}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|membre|membres}}", "nrevisions": "$1 version{{PLURAL:$1||s}}", - "nviews": "$1 consultation{{PLURAL:$1||s}}", + "nimagelinks": "Utilisé sur $1 {{PLURAL:$1|page|pages}}", "ntransclusions": "Utilisé sur $1 {{PLURAL:$1|page|pages}}", "specialpage-empty": "Il n'y a aucun résultat à afficher.", diff --git a/languages/i18n/frp.json b/languages/i18n/frp.json index 8c196ebc..d6154632 100644 --- a/languages/i18n/frp.json +++ b/languages/i18n/frp.json @@ -1355,7 +1355,7 @@ "nlinks": "$1 lim{{PLURAL:$1||s}}", "nmembers": "$1 membro{{PLURAL:$1||s}}", "nrevisions": "$1 vèrsion{{PLURAL:$1||s}}", - "nviews": "$1 vu{{PLURAL:$1|a|es}}", + "nimagelinks": "Empleyê dessus $1 pâge{{PLURAL:$1||s}}", "ntransclusions": "empleyê dessus $1 pâge{{PLURAL:$1||s}}", "specialpage-empty": "Y at gins de rèsultat a fâre vêre.", diff --git a/languages/i18n/frr.json b/languages/i18n/frr.json index 8c6c7775..0b4479f6 100644 --- a/languages/i18n/frr.json +++ b/languages/i18n/frr.json @@ -1505,7 +1505,7 @@ "nmembers": "{{PLURAL:$1|1 iindrach|$1 iindracher}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|lasmoot|lasmooten}}", "nrevisions": "$1 {{PLURAL:$1|feranrang|feranrangen}}", - "nviews": "$1 {{PLURAL:$1|klik|kliks}}", + "nimagelinks": "Brükt üüb $1 {{PLURAL:$1|sidj|sidjen}}", "ntransclusions": "brükt üüb $1 {{PLURAL:$1|sidj|sidjen}}", "specialpage-empty": "Diar san tu tidj nian iindracher.", diff --git a/languages/i18n/fur.json b/languages/i18n/fur.json index e4f8d1d4..c6b5a673 100644 --- a/languages/i18n/fur.json +++ b/languages/i18n/fur.json @@ -768,7 +768,7 @@ "nlinks": "$1 {{PLURAL:$1|leam|leams}}", "nmembers": "$1 {{PLURAL:$1|element|elements}}", "nrevisions": "$1 {{PLURAL:$1|revision|revisions}}", - "nviews": "$1 {{PLURAL:$1|viodude|viodudis}}", + "nimagelinks": "Doprât $1 {{PLURAL:$1|intune pagjine|in $1 pagjinis}}", "lonelypages": "Pagjinis solitaris", "lonelypagestext": "Lis pagjinis ca sot no àn leams di altris pagjinis di {{SITENAME}} e no son includudis in altris pagjinis.", diff --git a/languages/i18n/fy.json b/languages/i18n/fy.json index abcda04c..9160d59a 100644 --- a/languages/i18n/fy.json +++ b/languages/i18n/fy.json @@ -1115,7 +1115,7 @@ "nlinks": "$1 {{PLURAL:$1|keppeling|keppelings}}", "nmembers": "$1 {{PLURAL:$1|lid|lea}}", "nrevisions": "$1 {{PLURAL:$1|ferzje|ferzjes}}", - "nviews": "{{PLURAL:$1|1 kear|$1 kear}} sjoen", + "specialpage-empty": "Gjin resultaten foar dit rapport.", "lonelypages": "Lossteande siden", "lonelypagestext": "Nei de ûndersteande siden wurdt út {{SITENAME}} wei net ferwiisd.\nDe siden binne ek net as sjabloan opnommen.", diff --git a/languages/i18n/ga.json b/languages/i18n/ga.json index b50d4bc6..74c637c3 100644 --- a/languages/i18n/ga.json +++ b/languages/i18n/ga.json @@ -800,7 +800,7 @@ "nlinks": "{{PLURAL:$1|nasc amháin|$1 naisc}}", "nmembers": "{{PLURAL:$1|ball amháin|$1 baill}}", "nrevisions": "{{PLURAL:$1|Leagan amháin|$1 leagain}}", - "nviews": "{{PLURAL:$1|radharc amháin|$1 radhairc}}", + "lonelypages": "Leathanaigh aonair", "uncategorizedpages": "Leathanaigh gan chatagóir", "uncategorizedcategories": "Catagóirí gan chatagórú", diff --git a/languages/i18n/gan-hans.json b/languages/i18n/gan-hans.json index 80eff46e..f86d3bfa 100644 --- a/languages/i18n/gan-hans.json +++ b/languages/i18n/gan-hans.json @@ -840,7 +840,7 @@ "nlinks": "$1只链接", "nmembers": "$1只成员", "nrevisions": "$1只改动", - "nviews": "$1回浏览", + "specialpage-empty": "个只报告𠮶结果系空𠮶。", "lonelypages": "孤立𠮶页面", "lonelypagestext": "底下页面冇链接到{{SITENAME}}个别𠮶页面。", diff --git a/languages/i18n/gan-hant.json b/languages/i18n/gan-hant.json index 2837d291..b7db3f55 100644 --- a/languages/i18n/gan-hant.json +++ b/languages/i18n/gan-hant.json @@ -836,7 +836,7 @@ "nlinks": "$1隻連結", "nmembers": "$1隻成員", "nrevisions": "$1隻改動", - "nviews": "$1回瀏覽", + "specialpage-empty": "箇隻報告嗰結果係空嗰。", "lonelypages": "孤立嗰頁面", "lonelypagestext": "底下頁面冇連結到{{SITENAME}}箇別嗰頁面。", diff --git a/languages/i18n/gd.json b/languages/i18n/gd.json index 3969199b..b99d1c06 100644 --- a/languages/i18n/gd.json +++ b/languages/i18n/gd.json @@ -1525,7 +1525,7 @@ "nmembers": "$1 {{PLURAL:$1|bhall|bhall|buill|ball}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|bhall|bhall|buill|ball}}", "nrevisions": "$1 {{PLURAL:$1|mhùthadh|mhùthadh|mùthaidhean|mùthadh}}", - "nviews": "$1 {{PLURAL:$1|sealladh|shealladh|seallaidhean|sealladh}}", + "nimagelinks": "'Ga chleachdadh air $1 {{PLURAL:$1|duilleag|dhuilleag|duilleagan|duilleag}}", "ntransclusions": "'ga chleachdadh air $1 {{PLURAL:$1|duilleag|dhuilleag|duilleagan|duilleag}}", "specialpage-empty": "Chan eil toradh ann airson na h-aithris seo.", diff --git a/languages/i18n/gl.json b/languages/i18n/gl.json index c3a46e80..055e9ffa 100644 --- a/languages/i18n/gl.json +++ b/languages/i18n/gl.json @@ -1521,7 +1521,7 @@ "nmembers": "$1 {{PLURAL:$1|páxina|páxinas}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|membro|membros}}", "nrevisions": "$1 {{PLURAL:$1|revisión|revisións}}", - "nviews": "vista {{PLURAL:$1|unha vez|$1 veces}}", + "nimagelinks": "Empregada {{PLURAL:$1|nunha páxina|en $1 páxinas}}", "ntransclusions": "empregado en $1 {{PLURAL:$1|páxina|páxinas}}", "specialpage-empty": "Non hai resultados para o que solicitou.", diff --git a/languages/i18n/gn.json b/languages/i18n/gn.json index b9e8b508..d032b530 100644 --- a/languages/i18n/gn.json +++ b/languages/i18n/gn.json @@ -250,7 +250,7 @@ "nlinks": "$1 joaju", "nmembers": "$1 kuatiahai", "nrevisions": "$1 revisiones", - "nviews": "$1 vistas", + "lonelypages": "Kuatiarogue ityre'ỹva", "uncategorizedpages": "Kuatiarogue oñemohenda'ỹva", "uncategorizedcategories": "Ñemohenda noñemohendáiva", diff --git a/languages/i18n/grc.json b/languages/i18n/grc.json index 4b99ef08..c4139439 100644 --- a/languages/i18n/grc.json +++ b/languages/i18n/grc.json @@ -1009,7 +1009,7 @@ "nlinks": "$1 {{PLURAL:$1|σύνδεσμος|σύνδεσμοι}}", "nmembers": "$1 {{PLURAL:$1|μέλος|μέλη}}", "nrevisions": "$1 {{PLURAL:$1|ἀναθεώρησις|ἀναθεωρήσεις}}", - "nviews": "$1 {{PLURAL:$1|βλέψις|βλέψεις}}", + "specialpage-empty": "Οὐδὲν ἀποτέλεσμα ἐν τῇδε τῇ ἀναφορᾷ.", "lonelypages": "Δέλτοι ὀρφαναί", "lonelypagestext": "Aἱ ἀκόλουθοι δέλτοι μὴ συνδεδεμέναι μετὰ δέλτων τινῶν ἢ μὴ ὑπερκλῃσμέναι εἰς ἑτέρας δέλτους τινὰς ἐν τῷ {{SITENAME}} εἰσίν.", diff --git a/languages/i18n/gsw.json b/languages/i18n/gsw.json index dd47af17..574236d5 100644 --- a/languages/i18n/gsw.json +++ b/languages/i18n/gsw.json @@ -1442,7 +1442,7 @@ "nlinks": "$1 {{PLURAL:$1|Link|Links}}", "nmembers": "$1 {{PLURAL:$1|Syte|Sytene}}", "nrevisions": "$1 {{PLURAL:$1|Revision|Revisione}}", - "nviews": "$1 {{PLURAL:$1|Betrachtig|Betrachtige}}", + "nimagelinks": "Brucht uf $1 {{PLURAL:$1|Syte|Syte}}", "ntransclusions": "brucht uf $1 {{PLURAL:$1|Syte|Syte}}", "specialpage-empty": "In dr Syte het s no kei aktuälli Yytreg.", diff --git a/languages/i18n/gu.json b/languages/i18n/gu.json index 681e60da..05924017 100644 --- a/languages/i18n/gu.json +++ b/languages/i18n/gu.json @@ -1419,7 +1419,7 @@ "nlinks": "$1 {{PLURAL:$1|કડી|કડીઓ}}", "nmembers": "$1 {{PLURAL:$1|સદસ્ય|સદસ્યો}}", "nrevisions": "$1 {{PLURAL:$1|પુનરાવર્તન|પુનરાવર્તનો}}", - "nviews": "$1 {{PLURAL:$1|દેખાવ|દેખાવો}}", + "nimagelinks": "$1 {{PLURAL:$1|પાના|પાનાઓ}} પર વપરાયો", "ntransclusions": "$1 {{PLURAL:$1|પાના|પાનાઓ}} પર વપરાયો", "specialpage-empty": "આ પાનું ખાલી છે.", diff --git a/languages/i18n/hak.json b/languages/i18n/hak.json index 36ec2d75..a53f79b3 100644 --- a/languages/i18n/hak.json +++ b/languages/i18n/hak.json @@ -916,7 +916,7 @@ "nlinks": "$1隻鏈接", "nmembers": "$1隻成員", "nrevisions": "$1隻修訂版本", - "nviews": "$1次瀏覽", + "specialpage-empty": "本報告無結果。", "lonelypages": "孤立頁面", "lonelypagestext": "Yî-ha vùn-chông mò-yû lièn-kiet liá-ke wiki chûng ke khì-thâ vùn-chông.", diff --git a/languages/i18n/he.json b/languages/i18n/he.json index f49313d8..a0b4f801 100644 --- a/languages/i18n/he.json +++ b/languages/i18n/he.json @@ -1532,7 +1532,7 @@ "nmembers": "{{PLURAL:$1|דף אחד|$1 דפים}}", "nmemberschanged": "$1 ← {{PLURAL:$2|חבר אחד|$2 חברים}}", "nrevisions": "{{PLURAL:$1|גרסה אחת|$1 גרסאות}}", - "nviews": "{{PLURAL:$1|צפייה אחת|$1 צפיות}}", + "nimagelinks": "בשימוש {{PLURAL:$1|בדף אחד|ב־$1 דפים}}", "ntransclusions": "בשימוש {{PLURAL:$1|בדף אחד|ב־$1 דפים}}", "specialpage-empty": "אין תוצאות.", diff --git a/languages/i18n/hi.json b/languages/i18n/hi.json index b0ed3d21..7b91c1ae 100644 --- a/languages/i18n/hi.json +++ b/languages/i18n/hi.json @@ -1558,7 +1558,7 @@ "nmembers": "$1 {{PLURAL:$1|सदस्य}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|सदस्य}}", "nrevisions": "$1 {{PLURAL:$1|अवतरण}}", - "nviews": "{{PLURAL:$1|एक|$1}} बार देखा गया है", + "nimagelinks": "$1 {{PLURAL:$1|पृष्ठ|पृष्ठों}} पर प्रयुक्त", "ntransclusions": "$1 {{PLURAL:$1|पृष्ठ|पृष्ठों}} पर प्रयुक्त", "specialpage-empty": "इस ब्यौरे के लिये कोई परिणाम नहीं हैं।", diff --git a/languages/i18n/hif-latn.json b/languages/i18n/hif-latn.json index 4e3590d8..40b81a6a 100644 --- a/languages/i18n/hif-latn.json +++ b/languages/i18n/hif-latn.json @@ -1506,7 +1506,7 @@ "nmembers": "$1 {{PLURAL:$1|sadasya|sadasya}}", "nmemberschanged": "$1 → $2{{PLURAL:$2|sadasya|sadasya}}", "nrevisions": "$1 {{PLURAL:$1|badlao|badlao}}", - "nviews": "$1 {{PLURAL:$1|dafe dekha gais hai|dafe dekha gais hai}}", + "nimagelinks": "$1 {{PLURAL:$1|panna|panna}} me kaam me lawa gais hae", "ntransclusions": "$1 {{PLURAL:$1|panna|panna}} me kaam me lawa gais hae", "specialpage-empty": "Ii report khatir koi results nai hai.", diff --git a/languages/i18n/hr.json b/languages/i18n/hr.json index fc7aa3a4..a672e1bd 100644 --- a/languages/i18n/hr.json +++ b/languages/i18n/hr.json @@ -1479,7 +1479,7 @@ "nlinks": "$1 {{PLURAL:$1|poveznica|poveznice|poveznica}}", "nmembers": "$1 {{PLURAL:$1|član|članova}}", "nrevisions": "$1 {{PLURAL:$1|inačica|inačice|inačica}}", - "nviews": "$1 {{PLURAL:$1|put pogledano|puta pogledano|puta pogledano}}", + "nimagelinks": "Koristi se na $1 {{PLURAL:$1|stranici|stranice|stranica}}", "ntransclusions": "koristi se na $1 {{PLURAL:$1|stranici|stranice|stranica}}", "specialpage-empty": "Nema rezultata za traženi izvještaj.", diff --git a/languages/i18n/hrx.json b/languages/i18n/hrx.json index 301fa9ce..9e34ff32 100644 --- a/languages/i18n/hrx.json +++ b/languages/i18n/hrx.json @@ -1450,7 +1450,7 @@ "nmembers": "{{PLURAL:$1|1 Eintrooch|$1 Einträche}}", "nmemberschanged": "$1 → {{PLURAL:$2|En Mitglied|$2 Mitglieder}}", "nrevisions": "{{PLURAL:$1|1 Beoorbeitung|$1 Beoorbeitunge}}", - "nviews": "{{PLURAL:$1|1 Abfroch|$1 Abfroche}}", + "nimagelinks": "Verwendt uff {{PLURAL:$1|en Seit|$1 Seite}}", "ntransclusions": "Verwendt uff {{PLURAL:$1|en Seit|$1 Seite}}", "specialpage-empty": "Do sind aktuell ken zutreffende Einträche voarhand.", diff --git a/languages/i18n/hsb.json b/languages/i18n/hsb.json index ea835c9c..a37367d1 100644 --- a/languages/i18n/hsb.json +++ b/languages/i18n/hsb.json @@ -1489,7 +1489,7 @@ "nmembers": "{{PLURAL:$1|$1 čłon|$1 čłonaj|$1 čłony|$1 čłonow}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|čłon|čłonaj|čłonojo|čłonow}}", "nrevisions": "$1 {{PLURAL:$1|wobdźěłanje|wobdźěłani|wobdźěłanja|wobdźěłanjow}}", - "nviews": "$1 {{PLURAL:$1|jedyn wopyt|wopytaj|wopyty|wopytow}}", + "nimagelinks": "Wužiwa so na $1 {{PLURAL:$1|stronje|stronomaj|stronach|stronach}}", "ntransclusions": "wužiwa so na $1 {{PLURAL:$1|stronje|stronomaj|stronach|stronach}}", "specialpage-empty": "Tuchwilu žane zapiski.", diff --git a/languages/i18n/hu.json b/languages/i18n/hu.json index 5611b473..569a61c6 100644 --- a/languages/i18n/hu.json +++ b/languages/i18n/hu.json @@ -1510,7 +1510,7 @@ "nmembers": "{{PLURAL:$1|egy|$1}} elem", "nmemberschanged": "$1 → $2 tag", "nrevisions": "{{PLURAL:$1|egy|$1}} változat", - "nviews": "{{PLURAL:$1|egy|$1}} megtekintés", + "nimagelinks": "{{PLURAL:$1|Egy|$1}} lapon van használva", "ntransclusions": "{{PLURAL:$1|egy|$1}} lapon van használva", "specialpage-empty": "Ez az oldal üres.", diff --git a/languages/i18n/hy.json b/languages/i18n/hy.json index d5d575fd..2ab37ebb 100644 --- a/languages/i18n/hy.json +++ b/languages/i18n/hy.json @@ -1102,7 +1102,7 @@ "nlinks": "$1 {{PLURAL:$1|հղում|հղումներ}}", "nmembers": "$1 {{PLURAL:$1|անդամ|անդամ}}", "nrevisions": "$1 {{PLURAL:$1|տարբերակ|տարբերակներ}}", - "nviews": "$1 {{PLURAL:$1|դիտում|դիտումներ}}", + "nimagelinks": "օգտագործվում է $1 {{PLURAL:$1|էջ|էջեր}}", "ntransclusions": "օգտագործվում է $1 {{PLURAL:$1|էջ|էջեր}}", "specialpage-empty": "Հայցումը արդյունքներ չվերադարձրեց։", diff --git a/languages/i18n/ia.json b/languages/i18n/ia.json index 3f6eb714..780ecd17 100644 --- a/languages/i18n/ia.json +++ b/languages/i18n/ia.json @@ -1511,7 +1511,7 @@ "nmembers": "$1 {{PLURAL:$1|membro|membros}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|membro|membros}}", "nrevisions": "$1 {{PLURAL:$1|version|versiones}}", - "nviews": "$1 {{PLURAL:$1|visita|visitas}}", + "nimagelinks": "Usate in $1 {{PLURAL:$1|pagina|paginas}}", "ntransclusions": "usate in $1 {{PLURAL:$1|pagina|paginas}}", "specialpage-empty": "Il non ha resultatos pro iste reporto.", diff --git a/languages/i18n/id.json b/languages/i18n/id.json index 0e46d5e1..2894598f 100644 --- a/languages/i18n/id.json +++ b/languages/i18n/id.json @@ -1543,7 +1543,7 @@ "nmembers": "$1 {{PLURAL:$1|isi}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|anggota|anggota}}", "nrevisions": "$1 {{PLURAL:$1|revisi|revisi}}", - "nviews": "dilihat $1 {{PLURAL:$1|kali|kali}}", + "nimagelinks": "Digunakan pada $1 {{PLURAL:$1|halaman|halaman}}", "ntransclusions": "digunakan pada $1 {{PLURAL:$1|halaman|halaman}}", "specialpage-empty": "Tak ada yang perlu dilaporkan.", diff --git a/languages/i18n/ig.json b/languages/i18n/ig.json index 9b4dfcc3..ea6cc6a9 100644 --- a/languages/i18n/ig.json +++ b/languages/i18n/ig.json @@ -730,7 +730,7 @@ "nlinks": "{{PLURAL:$1|jikodo|jikodo}} $1", "nmembers": "{{PLURAL:$1|ọ'bànifé|Ndi n'bànifé}} $1", "nrevisions": "{{PLURAL:$1|orübà|orübà}} $1", - "nviews": "{{PLURAL:$1|he lèrè nke|he lèrè nke}} $1", + "lonelypages": "Ihü nke ogbènyè", "wantedpages": "Ihü há chọrọ", "prefixindex": "Ihü nílé jírí mkpụrụ édémédé nke mbu", diff --git a/languages/i18n/ilo.json b/languages/i18n/ilo.json index 5fc0be21..b1c8e4ca 100644 --- a/languages/i18n/ilo.json +++ b/languages/i18n/ilo.json @@ -1487,7 +1487,7 @@ "nmembers": "$1 a {{PLURAL:$1|kameng|kamkameng}}", "nmemberschanged": "$1 → $2 a {{PLURAL:$2|kameng|kamkameng}}", "nrevisions": "$1 {{PLURAL:$1|a rebison|kadagiti rebision}}", - "nviews": "$1 {{PLURAL:$1|a panangkita|kadagiti panangkita}}", + "nimagelinks": "Inusar iti $1 a {{PLURAL:$1|panid|pampanid}}", "ntransclusions": "inusar iti $1 a {{PLURAL:$1|panid|pampanid}}", "specialpage-empty": "Awan dagiti nagbanagan daytoy a reporta.", diff --git a/languages/i18n/io.json b/languages/i18n/io.json index afc328c8..1a9a39a0 100644 --- a/languages/i18n/io.json +++ b/languages/i18n/io.json @@ -661,7 +661,7 @@ "ncategories": "$1 {{PLURAL:$1|kategorio|kategorii}}", "nlinks": "$1 {{PLURAL:$1|ligilo|ligili}}", "nmembers": "$1 {{PLURAL:$1|membro|membri}}", - "nviews": "$1 {{PLURAL:$1|vizito|viziti}}", + "lonelypages": "Pagini sen ligili", "uncategorizedpages": "Nekategorizita pagini", "uncategorizedcategories": "Nekategorizita kategorii", diff --git a/languages/i18n/is.json b/languages/i18n/is.json index df335037..2a66a7b2 100644 --- a/languages/i18n/is.json +++ b/languages/i18n/is.json @@ -1439,7 +1439,7 @@ "nlinks": "$1 {{PLURAL:$1|tengill|tenglar}}", "nmembers": "$1 {{PLURAL:$1|meðlimur|meðlimir}}", "nrevisions": "$1 {{PLURAL:$1|breyting|breytingar}}", - "nviews": "$1 {{PLURAL:$1|fletting|flettingar}}", + "nimagelinks": "Ítengd á $1 {{PLURAL:$1|síðu|síðum}}", "ntransclusions": "Ítengd á $1 {{PLURAL:$1|síðu|síðum}}", "specialpage-empty": "Þessi síða er tóm.", diff --git a/languages/i18n/it.json b/languages/i18n/it.json index 6f7ad23c..23146c77 100644 --- a/languages/i18n/it.json +++ b/languages/i18n/it.json @@ -1585,7 +1585,7 @@ "nmembers": "$1 {{PLURAL:$1|elemento|elementi}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|elemento|elementi}}", "nrevisions": "$1 {{PLURAL:$1|versione|versioni}}", - "nviews": "$1 {{PLURAL:$1|visita|visite}}", + "nimagelinks": "Utilizzato su $1 {{PLURAL:$1|pagina|pagine}}", "ntransclusions": "usato in $1 {{PLURAL:$1|pagina|pagine}}", "specialpage-empty": "Questa pagina speciale è attualmente vuota.", diff --git a/languages/i18n/ja.json b/languages/i18n/ja.json index bee8a3ba..a98e682a 100644 --- a/languages/i18n/ja.json +++ b/languages/i18n/ja.json @@ -1577,7 +1577,7 @@ "nmembers": "$1項目", "nmemberschanged": "$1 → $2 {{PLURAL:$2|項目}}", "nrevisions": "$1版", - "nviews": "$1回の閲覧", + "nimagelinks": "$1 {{PLURAL:$1|ページ}}で使用", "ntransclusions": "$1 {{PLURAL:$1|ページ}}で使用", "specialpage-empty": "該当するものはありません。", diff --git a/languages/i18n/jv.json b/languages/i18n/jv.json index ffd855f9..08711ce2 100644 --- a/languages/i18n/jv.json +++ b/languages/i18n/jv.json @@ -1419,7 +1419,7 @@ "nmembers": "$1 {{PLURAL:$1|anggota|anggota}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|anggota|anggota}}", "nrevisions": "$1 {{PLURAL:$1|revisi|revisi}}", - "nviews": "Wis kaping $1 {{PLURAL:$1|dituduhaké|dituduhaké}}", + "nimagelinks": "Kanggo nèng {{PLURAL:$1|kaca|kaca}}", "ntransclusions": "kanggo nèng $1 {{PLURAL:$1|kaca|kaca}}", "specialpage-empty": "Ora ana sing perlu dilaporaké.", diff --git a/languages/i18n/ka.json b/languages/i18n/ka.json index 06e58639..06790ecc 100644 --- a/languages/i18n/ka.json +++ b/languages/i18n/ka.json @@ -1474,7 +1474,7 @@ "nmembers": "$1 წევრი", "nmemberschanged": "$1 → $2 {{PLURAL:$2|წევრი|წევრი}}", "nrevisions": "$1 რედაქტირება", - "nviews": "$1 ჩვენება", + "nimagelinks": "გამოიყენება $1 {{PLURAL:$1|გვერდზე}}", "ntransclusions": "გამოიყენება $1 {{PLURAL:$1|გვერდზე}}", "specialpage-empty": "ეს გვერდი ცარიელია.", diff --git a/languages/i18n/kaa.json b/languages/i18n/kaa.json index 805de26b..7ace457e 100644 --- a/languages/i18n/kaa.json +++ b/languages/i18n/kaa.json @@ -843,7 +843,7 @@ "nlinks": "{{PLURAL:$1|1 siltew|$1 siltew}}", "nmembers": "{{PLURAL:$1|1 ag'za|$1 ag'zalar}}", "nrevisions": "{{PLURAL:$1|1 nusqa|$1 nusqa}}", - "nviews": "{{PLURAL:$1|1 ma'rte|$1 ma'rte}} ko'rip shıg'ılg'an", + "specialpage-empty": "Bul sorawg'a hesh qanday na'tiyje joq.", "lonelypages": "Hesh betten siltelmegen betler", "lonelypagestext": "To'mendegi betlerge {{SITENAME}} proektindegi basqa betler siltemeydi.", diff --git a/languages/i18n/kab.json b/languages/i18n/kab.json index c92e9e14..a4660b4c 100644 --- a/languages/i18n/kab.json +++ b/languages/i18n/kab.json @@ -1422,7 +1422,7 @@ "nmembers": "$1 {{PLURAL:$1|amaslad|imasladen}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|amaslad|imasladen}}", "nrevisions": "$1 {{PLURAL:$1|tasiwelt|tisiwal}}", - "nviews": "$1 {{PLURAL:$1|timeẓriwt|tuẓrin}}", + "nimagelinks": "Yetseqdec ɣef $1 {{PLURAL:$1|asebter|isebtar}}", "ntransclusions": "yetseqdec ɣef $1 {{PLURAL:$1|asebter|isebtar}}", "specialpage-empty": "Asebter-agi d ilem.", diff --git a/languages/i18n/kiu.json b/languages/i18n/kiu.json index 50f65721..19b048cc 100644 --- a/languages/i18n/kiu.json +++ b/languages/i18n/kiu.json @@ -759,7 +759,7 @@ "nlinks": "$1 {{PLURAL:$1|gire|girey}}", "nmembers": "$1 {{PLURAL:$1|eza|ezay}}", "nrevisions": "$1 {{PLURAL:$1|çım-ra-viarnais|çım-ra-viarnaişi}}", - "nviews": "$1 {{PLURAL:$1|vênais|vênaişi}}", + "uncategorizedpages": "Pelê ke kategorize nêbiyê", "prefixindex": "Peli pêro be verbend", "shortpages": "Pelê kılmi", diff --git a/languages/i18n/kk-arab.json b/languages/i18n/kk-arab.json index a54f8315..51edd0f0 100644 --- a/languages/i18n/kk-arab.json +++ b/languages/i18n/kk-arab.json @@ -844,7 +844,7 @@ "nlinks": "$1 سىلتەمە", "nmembers": "$1 مۇشە", "nrevisions": "$1 تۇزەتۋ", - "nviews": "$1 رەت قارالعان", + "specialpage-empty": "بۇل باياناتقا ەش ناتىيجە جوق.", "lonelypages": "ەش بەتتەن سىلتەلمەگەن بەتتەر", "lonelypagestext": "كەلەسى بەتتەرگە {{SITENAME}} جوباسىنداعى باسقا بەتتەر سىلتەمەيدى.", diff --git a/languages/i18n/kk-cyrl.json b/languages/i18n/kk-cyrl.json index 1753182f..b76b3d67 100644 --- a/languages/i18n/kk-cyrl.json +++ b/languages/i18n/kk-cyrl.json @@ -1346,7 +1346,7 @@ "nmembers": "$1 {{PLURAL:$1|мүше|мүше}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|мүше|мүше}}", "nrevisions": "$1 {{PLURAL:$1|түзету|түзету}}", - "nviews": "$1 {{PLURAL:$1|қаралу|қаралу}}", + "nimagelinks": "$1 {{PLURAL:$1|бетте|бетте}} қолданылады", "ntransclusions": "$1 {{PLURAL:$1|бетте|бетте}} қолданылады", "specialpage-empty": "Бұл сұраныс бойынша нәтиже жоқ.", diff --git a/languages/i18n/kk-latn.json b/languages/i18n/kk-latn.json index 7e62a685..5fd6803b 100644 --- a/languages/i18n/kk-latn.json +++ b/languages/i18n/kk-latn.json @@ -845,7 +845,7 @@ "nlinks": "$1 silteme", "nmembers": "$1 müşe", "nrevisions": "$1 tüzetw", - "nviews": "$1 ret qaralğan", + "specialpage-empty": "Bul bayanatqa eş nätïje joq.", "lonelypages": "Eş betten siltelmegen better", "lonelypagestext": "Kelesi betterge {{SITENAME}} jobasındağı basqa better siltemeýdi.", diff --git a/languages/i18n/km.json b/languages/i18n/km.json index bbea687f..8a528efd 100644 --- a/languages/i18n/km.json +++ b/languages/i18n/km.json @@ -1362,7 +1362,7 @@ "nlinks": "$1 {{PLURAL:$1|តំណភ្ជាប់|តំណភ្ជាប់}}", "nmembers": "$1{{PLURAL:$1|សមាជិក|សមាជិក}}", "nrevisions": "$1 {{PLURAL:$1|កំណែប្រែ}}", - "nviews": "$1 {{PLURAL:$1|ការចូលមើល}}", + "nimagelinks": "ត្រូវបានប្រើនៅលើទំព័រចំនួន $1។", "ntransclusions": "ត្រូវបានប្រើនៅលើទំព័រចំនួន $1", "specialpage-empty": "គ្មានលទ្ធផលសម្រាប់របាយណ៍នេះទេ។", diff --git a/languages/i18n/kn.json b/languages/i18n/kn.json index cbd155a1..cf40be39 100644 --- a/languages/i18n/kn.json +++ b/languages/i18n/kn.json @@ -1118,7 +1118,7 @@ "nlinks": "$1 {{PLURAL:$1|ಸಂಪರ್ಕ|ಸಂಪರ್ಕಗಳು}}", "nmembers": "$1 {{PLURAL:$1|ಸದಸ್ಯ|ಸದಸ್ಯರು}}", "nrevisions": "$1 {{PLURAL:$1|ಬದಲಾವಣೆ|ಬದಲಾವಣೆಗಳು}}", - "nviews": "$1 {{PLURAL:$1|ನೋಟ|ನೋಟಗಳು}}", + "lonelypages": "ಒಬ್ಬಂಟಿ ಪುಟಗಳು", "lonelypagestext": "ಈ ಕೆಳಗಿನ ಪುಟಗಳು {{SITENAME}} ಅಲ್ಲಿರುವ ಇತರ ಯಾವ ಪುಟದಿಂದಲೂ ಕೊಂಡಿಯನ್ನು ಹೊಂದಿಲ್ಲ.", "uncategorizedpages": "ಅವರ್ಗೀಕೃತ ಪುಟಗಳು", diff --git a/languages/i18n/ko.json b/languages/i18n/ko.json index 7c18c028..974930ba 100644 --- a/languages/i18n/ko.json +++ b/languages/i18n/ko.json @@ -1546,7 +1546,7 @@ "nmembers": "{{PLURAL:$1|문서}} $1개", "nmemberschanged": "$1 → $2{{PLURAL:$2|개}}", "nrevisions": "{{PLURAL:$1|판}} $1개", - "nviews": "$1번 {{PLURAL:$1|읽음}}", + "nimagelinks": "{{PLURAL:$1|문서}} $1개에서 사용됨", "ntransclusions": "{{PLURAL:$1|문서}} $1개에서 사용됨", "specialpage-empty": "명령에 대한 결과가 없습니다.", diff --git a/languages/i18n/krc.json b/languages/i18n/krc.json index 2c3b40cb..d95388e7 100644 --- a/languages/i18n/krc.json +++ b/languages/i18n/krc.json @@ -1371,7 +1371,7 @@ "nmembers": "$1 {{PLURAL:$1|объект}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|объект}}", "nrevisions": "$1 {{PLURAL:$1|версия}}", - "nviews": "$1 {{PLURAL:$1|къарау}}", + "nimagelinks": "$1 {{PLURAL:$1|бетде}} хайырланады", "ntransclusions": "$1 {{PLURAL:$1|бетде}} хайырланады", "specialpage-empty": "Сорма эсеб келтирмеди.", diff --git a/languages/i18n/ksh.json b/languages/i18n/ksh.json index 2a37b9ca..36d6ad67 100644 --- a/languages/i18n/ksh.json +++ b/languages/i18n/ksh.json @@ -1518,7 +1518,7 @@ "nmembers": "met {{PLURAL:$1|ein Sigg|$1 Sigge}} dren", "nmemberschanged": "met $1 → {{PLURAL:$2|eine Sigg|$2 Sigge|keine Sigg}}", "nrevisions": "{{PLURAL:$1|Ein Änderung|$1 Änderunge|Keij Änderung}}", - "nviews": "{{PLURAL:$1|Eine Avrof|$1 Avrofe|Keine Avrof}}", + "nimagelinks": "Weed op {{PLURAL:$1|eine Sigg|$1 Sigge|keine Sigg}} jebruch", "ntransclusions": "weed op {{PLURAL:$1|eine Sigg|$1 Sigge|keine Sigg}} jebruch", "specialpage-empty": "Heh en dä Leß es nix dren.", diff --git a/languages/i18n/ku-latn.json b/languages/i18n/ku-latn.json index 799d6907..de3d84c9 100644 --- a/languages/i18n/ku-latn.json +++ b/languages/i18n/ku-latn.json @@ -951,7 +951,7 @@ "nlinks": "$1 {{PLURAL:$1|girêdan|girêdan}}", "nmembers": "$1 {{PLURAL:$1|endam|endam}}", "nrevisions": "$1 {{PLURAL:$1|guherandin|guherandin}}", - "nviews": "$1 {{PLURAL:$1|dîtin|dîtin}}", + "lonelypages": "Rûpelên sêwî", "uncategorizedpages": "Rûpelên bêkategorî", "uncategorizedcategories": "Kategoriyên bê kategorî", diff --git a/languages/i18n/la.json b/languages/i18n/la.json index 77734a28..4d99473f 100644 --- a/languages/i18n/la.json +++ b/languages/i18n/la.json @@ -993,7 +993,7 @@ "nlinks": "$1 {{PLURAL:$1|nexus|nexus}}", "nmembers": "$1 {{PLURAL:$1|inest|insunt}}", "nrevisions": "$1 {{PLURAL:$1|emendatio|emendationes}}", - "nviews": "$1 {{PLURAL:$1|visa|visae}}", + "lonelypages": "Paginae non annexae", "uncategorizedpages": "Paginae sine categoriis", "uncategorizedcategories": "Categoriae sine categoriis", diff --git a/languages/i18n/lb.json b/languages/i18n/lb.json index 4319ac34..e641fe04 100644 --- a/languages/i18n/lb.json +++ b/languages/i18n/lb.json @@ -1496,7 +1496,7 @@ "nmembers": "$1 {{PLURAL:$1|Member|Memberen}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|Member|Memberen}}", "nrevisions": "$1 {{PLURAL:$1|Versioun|Versiounen}}", - "nviews": "$1 {{PLURAL:$1|Offro|Offroen}}", + "nimagelinks": "Benotzt op {{PLURAL:$1|enger Säit|$1 Säiten}}", "ntransclusions": "benotzt op {{PLURAL:$1|enger Säit|$1 Säiten}}", "specialpage-empty": "Dës Säit ass eidel.", diff --git a/languages/i18n/li.json b/languages/i18n/li.json index b0795462..fe4c3e7c 100644 --- a/languages/i18n/li.json +++ b/languages/i18n/li.json @@ -1281,7 +1281,7 @@ "nlinks": "$1 {{PLURAL:$1|verwiezing|verwiezinge}}", "nmembers": "$1 {{PLURAL:$1|lid|lede}}", "nrevisions": "$1 {{PLURAL:$1|herzening|herzeninge}}", - "nviews": "{{PLURAL:$1|eine kieër|$1 kieër}} bekeke", + "nimagelinks": "Gebroek op $1 {{PLURAL:$1|pagina|pagina's}}", "ntransclusions": "Gebroek op $1 {{PLURAL:$1|pagina|pagina's}}", "specialpage-empty": "Deze pagina is laeg.", diff --git a/languages/i18n/lmo.json b/languages/i18n/lmo.json index 264bb818..4bd1b7d0 100644 --- a/languages/i18n/lmo.json +++ b/languages/i18n/lmo.json @@ -1016,7 +1016,7 @@ "nmembers": "$1 {{PLURAL:$1|element|element}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|elemènt|elemèncc}}", "nrevisions": "$1 {{PLURAL:$1|reviziù}}", - "nviews": "$1 {{PLURAL:$1|vìzita|vìzite}}", + "nimagelinks": "Dopràt sö $1 {{PLURAL:$1|pàgina|pàgine}}", "ntransclusions": "dopràt sö $1 {{PLURAL:$1|pàgina|pàgine}}", "specialpage-empty": "Chèsta pàgina speciàl al momènt l'è öda.", diff --git a/languages/i18n/loz.json b/languages/i18n/loz.json index f511adcc..b6ec3db9 100644 --- a/languages/i18n/loz.json +++ b/languages/i18n/loz.json @@ -468,7 +468,7 @@ "nlinks": "$1 {{PLURAL:$1|ling'ki|ling'ki}}", "nmembers": "$1 {{PLURAL:$1|peta|petani}}", "nrevisions": "$1 {{PLURAL:$1|hloli|hlolina}}", - "nviews": "$1 {{PLURAL:$1|kamukile|kamukile}}", + "specialpage-empty": "Kamukile ni sa bundau.", "lonelypages": "Petulo coni ling'ki di a", "lonelypagestext": "Petulo kamukile ni sa con ling'ki di xeti petulo di {{SITENAME}}.", diff --git a/languages/i18n/lrc.json b/languages/i18n/lrc.json index f2f4dcbb..297f6a24 100644 --- a/languages/i18n/lrc.json +++ b/languages/i18n/lrc.json @@ -1519,7 +1519,7 @@ "nmembers": "$1 {{PLURAL:$1|اندوم|اندوميا}}", "nmemberschanged": "$1 → $2 {{جمی:$2|اندوم|اندومیا}}", "nrevisions": "$1 {{جمس:$1|وانئری|وانئریا}}", - "nviews": "$1 {{جمی:$1|دیئن|دیئنیا}}", + "nimagelinks": "$1 {{جمی:$1|بلگه|بلگيا}} استفاده بیه", "ntransclusions": "$1 {{جمی:$1|بلگه|بلگيا}} استفاده بیه", "specialpage-empty": "نتیجه ای د ای گزارشت نئ.", diff --git a/languages/i18n/lt.json b/languages/i18n/lt.json index a392ca13..5310625c 100644 --- a/languages/i18n/lt.json +++ b/languages/i18n/lt.json @@ -1491,7 +1491,7 @@ "nmembers": "$1 {{PLURAL:$1|narys|nariai|narių}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|narys|nariai|narių}}", "nrevisions": "$1 {{PLURAL:$1|keitimas|keitimai|keitimų}}", - "nviews": "$1 {{PLURAL:$1|parodymas|parodymai|parodymų}}", + "nimagelinks": "Naudojama $1 {{PLURAL:$1|puslapyje|puslapiuose|puslapių}}", "ntransclusions": "naudojama $1 {{PLURAL:$1|puslapyje|puslapiuose|puslapių}}", "specialpage-empty": "Šiai ataskaitai nėra rezultatų.", diff --git a/languages/i18n/lus.json b/languages/i18n/lus.json index 88cae64b..b064f8f3 100644 --- a/languages/i18n/lus.json +++ b/languages/i18n/lus.json @@ -964,7 +964,7 @@ "nlinks": "$1 {{PLURAL:$1||}} Zawmna $1", "nmembers": "A chhungah {{PLURAL:$1||$1}} a awm.", "nrevisions": "siamṭhatna $1 {{PLURAL:$1||}}", - "nviews": "vawi $1 {{PLURAL:$1||}} ràwn a ni tawh.", + "nimagelinks": "Phêk $1-ah {{PLURAL:$1||}} hman a ni.", "ntransclusions": "phêk $1-ah {{PLURAL:$1||}} hman a ni.", "specialpage-empty": "Thuhawn a awm lo tlat.", diff --git a/languages/i18n/lv.json b/languages/i18n/lv.json index cafbea42..68026570 100644 --- a/languages/i18n/lv.json +++ b/languages/i18n/lv.json @@ -1288,7 +1288,7 @@ "nlinks": "$1 {{PLURAL:$1|saites|saite|saites}}", "nmembers": "$1 {{PLURAL:$1|lapas|lapa|lapas}}", "nrevisions": "$1 {{PLURAL:$1|versijas|versija|versijas}}", - "nviews": "skatīta $1 {{PLURAL:$1|reizes|reizi|reizes}}", + "nimagelinks": "Izmantots $1 {{PLURAL:$1|lapās|lapā|lapās}}", "ntransclusions": "izmantots $1 {{PLURAL:$1|lapās|lapā|lapās}}", "specialpage-empty": "Šim ziņojumam nav rezultātu.", diff --git a/languages/i18n/lzh.json b/languages/i18n/lzh.json index 674c343a..90dbcba5 100644 --- a/languages/i18n/lzh.json +++ b/languages/i18n/lzh.json @@ -1268,7 +1268,7 @@ "nlinks": "$1鏈", "nmembers": "$1戶", "nrevisions": "$1審", - "nviews": "$1閱", + "nimagelinks": "用以頁有$1", "ntransclusions": "用以頁有$1", "lonelypages": "孤寡", diff --git a/languages/i18n/mai.json b/languages/i18n/mai.json index ffa712d1..7062debf 100644 --- a/languages/i18n/mai.json +++ b/languages/i18n/mai.json @@ -1459,7 +1459,7 @@ "nmembers": "$1 {{PLURAL:$1|सदस्य|सदस्य सभ}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|प्रयोक्ता|प्रयोक्ता सभ}}", "nrevisions": "$1{{PLURAL:$1|संशोधन|संशोधन सभ}}", - "nviews": "$1 {{PLURAL:$1|दृश्य|दृश्य सभ}}", + "nimagelinks": "$1पर प्रयुक्त {{PLURAL:$1|पन्ना|पन्ना सभ}}", "ntransclusions": "$1पर प्रयुक्त {{PLURAL:$1|पन्ना|पन्ना सभ}}", "specialpage-empty": "ऐ पन्ना लेल कोनो परिणाम नै अछि।", diff --git a/languages/i18n/map-bms.json b/languages/i18n/map-bms.json index f7cf1c6a..27f57cb0 100644 --- a/languages/i18n/map-bms.json +++ b/languages/i18n/map-bms.json @@ -1057,7 +1057,7 @@ "nlinks": "$1 {{PLURAL:$1|pranala|pranala}}", "nmembers": "$1 {{PLURAL:$1|isi|isi}}", "nrevisions": "$1 {{PLURAL:$1|revisi|revisi}}", - "nviews": "Wis ping $1 {{PLURAL:$1|dideleng|dideleng}}", + "nimagelinks": "Digunakna nang $1 {{PLURAL:$1|kaca|kaca}}", "ntransclusions": "digunakna nang $1 {{PLURAL:$1|kaca|kaca}}", "specialpage-empty": "Ora ana sing perlu dilaporna.", diff --git a/languages/i18n/mdf.json b/languages/i18n/mdf.json index 46f6d38d..2b110f21 100644 --- a/languages/i18n/mdf.json +++ b/languages/i18n/mdf.json @@ -1064,7 +1064,7 @@ "nlinks": "$1 {{PLURAL:$1|сюлмафкс|сюлмафкст}}", "nmembers": "$1 {{PLURAL:$1|сувси|сувсихть}}", "nrevisions": "$1 {{PLURAL:$1|верзие|верзиет}}", - "nviews": "$1 {{PLURAL:$1|няфтема|няфтемат}}", + "specialpage-empty": "Тя информациень коряс мезеге изь мув.", "lonelypages": "Уроз лопат", "lonelypagestext": "Ся лопатне афи сюлмафт афи сотфт иля лопатнень мархта {{SITENAME}}са.", diff --git a/languages/i18n/mg.json b/languages/i18n/mg.json index 8f39d3dd..1ca75cf2 100644 --- a/languages/i18n/mg.json +++ b/languages/i18n/mg.json @@ -1466,7 +1466,7 @@ "nlinks": "{{PLURAL:$1|rohy|rohy}} $1", "nmembers": "{{PLURAL:$1|mpikambana|mpikambana}} $1", "nrevisions": "{{PLURAL:$1|fanovana|fanovana}} $1", - "nviews": "{{PLURAL:}}Tsidika $1", + "nimagelinks": "Ampiasain'ny pejy miisa{{PLURAL:}} $1", "ntransclusions": "Ampiasaina eo amin'ny pejy miisa $1 {{PLURAL:}}", "specialpage-empty": "Tsy misy valiny ho aseho.", diff --git a/languages/i18n/mhr.json b/languages/i18n/mhr.json index 3f38f594..9909073a 100644 --- a/languages/i18n/mhr.json +++ b/languages/i18n/mhr.json @@ -529,7 +529,7 @@ "withoutinterwiki-submit": "ончыкташ", "nbytes": "$1 {{PLURAL:$1|1=байт|байт}}", "nmembers": "$1 {{PLURAL:$1|1=лаштык|лаштык-влак}}", - "nviews": "$1 {{PLURAL:$1|1=ончымо|ончымо-влак}}", + "lonelypages": "Тулык лаштык-влак", "wantedcategories": "Ыштыман категорий-влак", "wantedpages": "Ыштышаш лаштык-влак", diff --git a/languages/i18n/min.json b/languages/i18n/min.json index e63929fc..51fd0f61 100644 --- a/languages/i18n/min.json +++ b/languages/i18n/min.json @@ -1107,7 +1107,7 @@ "nlinks": "$1 {{PLURAL:$1|pautan}}", "nmembers": "$1 {{PLURAL:$1|anggota}}", "nrevisions": "$1 {{PLURAL:$1|revisi}}", - "nviews": "dilihek $1 {{PLURAL:$1|kali}}", + "nimagelinks": "Digunoan pado $1 {{PLURAL:$1|laman}}", "ntransclusions": "digunoan pado $1 {{PLURAL:$1|laman}}", "specialpage-empty": "Indak ado nan paralu dilaporan.", diff --git a/languages/i18n/mk.json b/languages/i18n/mk.json index de8663b4..d85efb68 100644 --- a/languages/i18n/mk.json +++ b/languages/i18n/mk.json @@ -1528,7 +1528,7 @@ "nmembers": "$1 {{PLURAL:$1|член|членови}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|член|членови}}", "nrevisions": "$1 {{PLURAL:$1|измена|измени}}", - "nviews": "$1 {{PLURAL:$1|преглед|прегледи}}", + "nimagelinks": "Се користи на $1 {{PLURAL:$1|страница|страници}}", "ntransclusions": "се користи на $1 {{PLURAL:$1|страница|страници}}", "specialpage-empty": "Нема резултати од пребарувањето на овој извештај.", diff --git a/languages/i18n/ml.json b/languages/i18n/ml.json index 1c560f3e..07e9028c 100644 --- a/languages/i18n/ml.json +++ b/languages/i18n/ml.json @@ -1520,7 +1520,7 @@ "nmembers": "{{PLURAL:$1|ഒരു അംഗം|$1 അംഗങ്ങൾ}}", "nmemberschanged": "$1 → {{PLURAL:$2|ഒരു അംഗം|$2 അംഗങ്ങൾ}}", "nrevisions": "{{PLURAL:$1|ഒരു പതിപ്പ്|$1 പതിപ്പുകൾ}}", - "nviews": "{{PLURAL:$1|ഒരു സന്ദർശനം|$1 സന്ദർശനങ്ങൾ}}", + "nimagelinks": "{{PLURAL:$1|ഒരു താളിൽ|$1 താളുകളിൽ}} ഉപയോഗിച്ചിരിക്കുന്നു", "ntransclusions": "{{PLURAL:$1|ഒരു താളിൽ|$1 താളുകളിൽ}} ഉപയോഗിച്ചിരിക്കുന്നു", "specialpage-empty": "ഈ താൾ ശൂന്യമാണ്.", diff --git a/languages/i18n/mn.json b/languages/i18n/mn.json index 7fe9c722..718dbc90 100644 --- a/languages/i18n/mn.json +++ b/languages/i18n/mn.json @@ -1344,7 +1344,7 @@ "nlinks": "$1 линк", "nmembers": "$1 гишүүн", "nrevisions": "$1 засвар", - "nviews": "$1 удаа үзсэн", + "nimagelinks": "$1 {{PLURAL:$1|хуудсанд|хуудсанд}} ашигласан", "specialpage-empty": "Энэ мэдүүлэгт үр дүн гарсангүй.", "lonelypages": "Өнчин хуудсууд", diff --git a/languages/i18n/mr.json b/languages/i18n/mr.json index ead4fefd..d1c2d651 100644 --- a/languages/i18n/mr.json +++ b/languages/i18n/mr.json @@ -1472,7 +1472,7 @@ "nmembers": "$1 {{PLURAL:$1|सदस्य}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|सदस्य}}", "nrevisions": "$1 {{PLURAL:$1|आवर्तन|आवर्तने}}", - "nviews": "$1 {{PLURAL:$1|दृषीपथ|दृषीपथ}}", + "nimagelinks": "$1{{PLURAL:$1|पानावर|पानांवर}}", "ntransclusions": "$1{{PLURAL:$1|पानावर|पानांवर}} वापर", "specialpage-empty": "या अहवालाकरिता(रिपोर्ट)कोणताही निकाल नाही.", diff --git a/languages/i18n/ms.json b/languages/i18n/ms.json index 14b518c4..3fb3c942 100644 --- a/languages/i18n/ms.json +++ b/languages/i18n/ms.json @@ -1522,7 +1522,7 @@ "nmembers": "$1 ahli", "nmemberschanged": "$1 → $2 {{PLURAL:$2|ahli}}", "nrevisions": "$1 semakan", - "nviews": "Dilihat $1 kali", + "nimagelinks": "Digunakan pada {{PLURAL:$1|sebuah|$1 buah}} laman", "ntransclusions": "digunakan pada {{PLURAL:$1|sebuah|$1 buah}} laman", "specialpage-empty": "Tiada keputusan bagi laporan ini.", diff --git a/languages/i18n/mt.json b/languages/i18n/mt.json index 3c55d64f..ca9ac704 100644 --- a/languages/i18n/mt.json +++ b/languages/i18n/mt.json @@ -1357,7 +1357,7 @@ "nlinks": "{{PLURAL:$1|link|$1 links}}", "nmembers": "$1 {{PLURAL:$1|membru|membri}}", "nrevisions": "{{PLURAL:$1|reviżjoni|$1 reviżjonijiet}}", - "nviews": "{{PLURAL:$1|visita|$1 visiti}}", + "nimagelinks": "Użat fuq $1 {{PLURAL:$1|paġna|paġni}}", "ntransclusions": "użat fuq $1 {{PLURAL:$1|paġna|paġni}}", "specialpage-empty": "Dan ir-rapport ma fih l-ebda riżultat.", diff --git a/languages/i18n/myv.json b/languages/i18n/myv.json index da14248b..d5576776 100644 --- a/languages/i18n/myv.json +++ b/languages/i18n/myv.json @@ -918,7 +918,7 @@ "nlinks": "$1 {{PLURAL:$1|невтевкс|невтевкснедэ|невтевкст}}", "nmembers": "куронь $1 {{PLURAL:$1|ломань|ломанть}}", "nrevisions": "$1 {{PLURAL:$1|1=лиякстомтома|лиякстомтомат}}", - "nviews": "$1 {{PLURAL:$1|1=ванома потмо|ванома потмот}}", + "lonelypages": "Лопаурозкэть", "uncategorizedpages": "Категориявтомо лопат", "uncategorizedcategories": "Категориявтомо категорият", diff --git a/languages/i18n/nap.json b/languages/i18n/nap.json index e7922b4a..24b0a5fc 100644 --- a/languages/i18n/nap.json +++ b/languages/i18n/nap.json @@ -1508,7 +1508,7 @@ "nmembers": "$1 {{PLURAL:$1|elemento|elemente}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|membro|membre}}", "nrevisions": "$1 {{PLURAL:$1|verzione|verziune}}", - "nviews": "$1 {{PLURAL:$1|visita|visite}}", + "nimagelinks": "Ausate ncopp'a {{PLURAL:$1|na paggena|$1 paggene}}", "ntransclusions": "ausate ncopp'a {{PLURAL:$1|na paggena|$1 paggene}}", "specialpage-empty": "Nun ce stanno risultate pe' stu report.", diff --git a/languages/i18n/nb.json b/languages/i18n/nb.json index 9d2d63f5..6fdcffb1 100644 --- a/languages/i18n/nb.json +++ b/languages/i18n/nb.json @@ -1543,7 +1543,7 @@ "nmembers": "$1 {{PLURAL:$1|medlem|medlemmer}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|medlem|medlemmer}}", "nrevisions": "$1 {{PLURAL:$1|revisjon|revisjoner}}", - "nviews": "$1 {{PLURAL:$1|visning|visninger}}", + "nimagelinks": "Brukt på $1 {{PLURAL:$1|side|sider}}", "ntransclusions": "brukt på $1 {{PLURAL:$1|side|sider}}", "specialpage-empty": "Denne siden er tom.", diff --git a/languages/i18n/nds-nl.json b/languages/i18n/nds-nl.json index f54cc789..33cfb10e 100644 --- a/languages/i18n/nds-nl.json +++ b/languages/i18n/nds-nl.json @@ -1450,7 +1450,7 @@ "nlinks": "$1 {{PLURAL:$1|verwiezing|verwiezingen}}", "nmembers": "$1 {{PLURAL:$1|onderwarp|onderwarpen}}", "nrevisions": "$1 {{PLURAL:$1|versie|versies}}", - "nviews": "{{PLURAL:$1|1 keer|$1 keer}} bekeken", + "nimagelinks": "Wörden op {{PLURAL:$1|één zied|$1 ziejen}} gebruukt", "ntransclusions": "wörden op {{PLURAL:$1|één zied|$1 ziejen}} gebruukt", "specialpage-empty": "Disse zied is leeg.", diff --git a/languages/i18n/nds.json b/languages/i18n/nds.json index f8301c32..2e1c61e8 100644 --- a/languages/i18n/nds.json +++ b/languages/i18n/nds.json @@ -1111,7 +1111,7 @@ "nlinks": "$1 {{PLURAL:$1|Verwies|Verwiesen}}", "nmembers": "$1 {{PLURAL:$1|Maat|Maten}}", "nrevisions": "{{PLURAL:$1|1 Version|$1 Versionen}}", - "nviews": "$1 {{PLURAL:$1|Affraag|Affragen}}", + "specialpage-empty": "Disse Siet is leddig.", "lonelypages": "Weetsieden", "lonelypagestext": "Op disse Sieden wiest kene annern Sieden vun {{SITENAME}} un se sünd ok narms inbunnen.", diff --git a/languages/i18n/ne.json b/languages/i18n/ne.json index 6e78ef2a..3dd2d9fd 100644 --- a/languages/i18n/ne.json +++ b/languages/i18n/ne.json @@ -1335,7 +1335,7 @@ "nlinks": "$1 {{PLURAL:$1|लिंक|लिंकहरु}}", "nmembers": "$1 {{PLURAL:$1|सदस्य|सदस्यहरू}}", "nrevisions": "$1 {{PLURAL:$1|पुनरावलोकन|पुनरावलोकनहरु}}", - "nviews": "$1 {{PLURAL:$1|अवलोकन|अवलोकनहरु}}", + "nimagelinks": "$1 {{PLURAL:$1|पृष्ठ|पृष्ठहरु}}माथि प्रयोग गरिएको", "ntransclusions": "$1 {{PLURAL:$1पृष्ठमा प्रयोग गरिएको|पृष्ठहरुमा प्रयोग गरिएका}}", "specialpage-empty": "यो पृष्ठ खाली छ।", diff --git a/languages/i18n/nl.json b/languages/i18n/nl.json index 8cd91784..e47671af 100644 --- a/languages/i18n/nl.json +++ b/languages/i18n/nl.json @@ -1564,7 +1564,7 @@ "nmembers": "$1 {{PLURAL:$1|item|items}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|lid|leden}}", "nrevisions": "$1 {{PLURAL:$1|versie|versies}}", - "nviews": "{{PLURAL:$1|1 keer|$1 keer}} bekeken", + "nimagelinks": "Gebruikt op {{PLURAL:$1|één pagina|$1 pagina's}}", "ntransclusions": "gebruikt op {{PLURAL:$1|één pagina|$1 pagina's}}", "specialpage-empty": "Er zijn geen resultaten voor deze rapportage.", diff --git a/languages/i18n/nn.json b/languages/i18n/nn.json index b9aa6fb3..3830f69c 100644 --- a/languages/i18n/nn.json +++ b/languages/i18n/nn.json @@ -1436,7 +1436,7 @@ "nlinks": "{{PLURAL:$1|Éi lenkje|$1 lenkjer}}", "nmembers": "$1 {{PLURAL:$1|medlem|medlemmer}}", "nrevisions": "{{PLURAL:$1|Éin versjon|$1 versjonar}}", - "nviews": "{{PLURAL:$1|Éi vising|$1 visingar}}", + "nimagelinks": "Brukt på $1 {{PLURAL:$1|side|sider}}", "ntransclusions": "brukt på $1 {{PLURAL:$1|side|sider}}", "specialpage-empty": "Det er ingen resultat for denne rapporten.", diff --git a/languages/i18n/oc.json b/languages/i18n/oc.json index 4f1471ea..108226fe 100644 --- a/languages/i18n/oc.json +++ b/languages/i18n/oc.json @@ -1488,7 +1488,7 @@ "nmembers": "$1 {{PLURAL:$1|membre|membres}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|membre|membres}}", "nrevisions": "$1 {{PLURAL:$1|revision|revisions}}", - "nviews": "$1 {{PLURAL:$1|consultacion|consultacions}}", + "nimagelinks": "Utilizat sus $1 {{PLURAL:$1|pagina|paginas}}", "ntransclusions": "Utilizat sus $1 {{PLURAL:$1|pagina|paginas}}", "specialpage-empty": "Aquesta pagina es voida.", diff --git a/languages/i18n/or.json b/languages/i18n/or.json index a89a2292..c2fed792 100644 --- a/languages/i18n/or.json +++ b/languages/i18n/or.json @@ -1483,7 +1483,7 @@ "nmembers": "$1 {{PLURAL:$1|member|ସଭ୍ୟ}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|ସଭ୍ୟ|ସଭ୍ୟଗଣ}}", "nrevisions": "$1 ଗୋଟି {{PLURAL:$1|ସଂସ୍କରଣ|ସଂସ୍କରଣ}}", - "nviews": "$1 ଟି {{PLURAL:$1|ଦେଖଣା|ଦେଖଣା}}", + "nimagelinks": "$1 ଟି {{PLURAL:$1|ପୃଷ୍ଠା|ପୃଷ୍ଠା}}ରେ ବ୍ୟବହାର କରାଯାଇଅଛି", "ntransclusions": "$1ଟି {{PLURAL:$1|ପୃଷ୍ଠା|ପୃଷ୍ଠା}}ରେ ବ୍ୟବହାର କରାଯାଇଅଛି", "specialpage-empty": "ଏହି ଅନୁରୋଧ ପାଇଁ କିଛି ଫଳାଫଳ ମିଳିଲା ନାହିଁ ।", diff --git a/languages/i18n/os.json b/languages/i18n/os.json index 89ef183a..7faeb9fb 100644 --- a/languages/i18n/os.json +++ b/languages/i18n/os.json @@ -849,7 +849,7 @@ "nlinks": "$1 {{PLURAL:$1|æрвитæн|æрвитæны}}", "nmembers": "$1 {{PLURAL:$1|уæнг|уæнгы}}", "nrevisions": "$1 {{PLURAL:$1|фæлтæр|фæлтæры}}", - "nviews": "$1 {{PLURAL:$1|æркаст|æркасты}}", + "nimagelinks": "Архайд цæуы $1 {{PLURAL:$1|фарсы}}", "ntransclusions": "архайд цæуы $1 {{PLURAL:$1|фарсы}}", "lonelypages": "Сидзæр фæрстæ", diff --git a/languages/i18n/pa.json b/languages/i18n/pa.json index 1c96f7dc..dd5bfffa 100644 --- a/languages/i18n/pa.json +++ b/languages/i18n/pa.json @@ -1254,7 +1254,7 @@ "nlinks": "$1 {{PLURAL:$1|ਲਿੰਕ|ਲਿੰਕ}}", "nmembers": "$1 {{PLURAL:$1|ਮੈਂਬਰ|ਮੈਂਬਰਾਂ}}", "nrevisions": "$1 {{PLURAL:$1|ਰੀਵਿਜ਼ਨ|ਰੀਵਿਜ਼ਨਾਂ}}", - "nviews": "$1 {{PLURAL:$1|ਫੇਰੀ|ਫੇਰੀਆਂ}}", + "nimagelinks": "$1 {{PLURAL:$1|ਸਫ਼ੇ|ਸਫ਼ਿਆਂ}} ’ਤੇ ਵਰਤਿਆ ਹੋਇਆ", "ntransclusions": "$1 {{PLURAL:$1|ਸਫ਼ੇ|ਸਫ਼ਿਆਂ}} ’ਤੇ ਵਰਤਿਆ ਹੋਇਆ", "specialpage-empty": "ਇਸ ਰਿਪੋਟ ਦਾ ਕੋਈ ਨਤੀਜਾ ਨਹੀਂ ਹੈ।", diff --git a/languages/i18n/pam.json b/languages/i18n/pam.json index 81c2ba3d..21cbf0a7 100644 --- a/languages/i18n/pam.json +++ b/languages/i18n/pam.json @@ -867,7 +867,7 @@ "nlinks": "$1 {{PLURAL:$1|link|suglung}}", "nmembers": "$1 {{PLURAL:$1|kayanib}}", "nrevisions": "$1 {{PLURAL:$1|pamagbayu|pamagbayu}}", - "nviews": "$1 {{PLURAL:$1|linawe|linawe}}", + "specialpage-empty": "Alang linual/resulta king ulat (report) a ini.", "lonelypages": "Bulung a alang suglung (orphaned)", "lonelypagestext": "Alang suglung manibat kareng aliwang bulung ning {{SITENAME}} kareng makatuking bulung.", diff --git a/languages/i18n/pl.json b/languages/i18n/pl.json index 64a84f46..6880e5b8 100644 --- a/languages/i18n/pl.json +++ b/languages/i18n/pl.json @@ -1582,7 +1582,7 @@ "nmembers": "$1 {{PLURAL:$1|element|elementy|elementów}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|element|elementy|elementów}}", "nrevisions": "$1 {{PLURAL:$1|wersja|wersje|wersji}}", - "nviews": "odwiedzono $1 {{PLURAL:$1|raz|razy}}", + "nimagelinks": "Używane na $1 {{PLURAL:$1|stronie|stronach}}", "ntransclusions": "używany na $1 {{PLURAL:$1|stronie|stronach}}", "specialpage-empty": "Ta strona raportu jest pusta.", diff --git a/languages/i18n/pms.json b/languages/i18n/pms.json index 1878fe73..9cf308ef 100644 --- a/languages/i18n/pms.json +++ b/languages/i18n/pms.json @@ -1520,7 +1520,7 @@ "nmembers": "$1 {{PLURAL:$1|element|element}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|mèmber}}", "nrevisions": "{{PLURAL:$1|na revision|$1 revision}}", - "nviews": "{{PLURAL:$1|na consultassion|$1 consultassion}}", + "nimagelinks": "Dovrà dzora a $1 {{PLURAL:$1|pàgina|pàgine}}", "ntransclusions": "dovrà dzora a $1 {{PLURAL:$1|pàgina|pàgine}}", "specialpage-empty": "Pàgina veujda.", diff --git a/languages/i18n/pnb.json b/languages/i18n/pnb.json index f1252884..d1635fde 100644 --- a/languages/i18n/pnb.json +++ b/languages/i18n/pnb.json @@ -1237,7 +1237,7 @@ "nlinks": "$1 {{PLURAL:$1|link|جوڑ}}", "nmembers": "$1 {{PLURAL:$1|member|ممبران}}", "nrevisions": "$1 {{PLURAL:$1|ریوین|ریویناں}}", - "nviews": "$1 {{PLURAL:$1|وکھالہ|وکھالے}}", + "nimagelinks": "تے ورتیا $1 {{PLURAL:$1|صفہ|صفے}}", "ntransclusions": "$1 تے ورتے {{PLURAL:$1|صفہ|صفے}}", "specialpage-empty": "ایس رپورٹ دے کوئی نتیجے نئیں۔", diff --git a/languages/i18n/prg.json b/languages/i18n/prg.json index d0b33ead..3164fc1c 100644 --- a/languages/i18n/prg.json +++ b/languages/i18n/prg.json @@ -1006,7 +1006,7 @@ "nlinks": "$1 {{PLURAL:$1|autengīnsenis|autengīnsenei}}", "nmembers": "$1 {{PLURAL:$1|streīpstus|streīpstai}}", "nrevisions": "$1 {{PLURAL:$1|wersiōni|wersiōnis}}", - "nviews": "$1 {{PLURAL:$1|kāimalukisenis|kāimalukisenei}}", + "specialpage-empty": "Ni ast rezultātai per šin repōrtan.", "lonelypages": "Ainaseīlingis pāusai", "lonelypagestext": "Prēi zemmaisins pāusans ni autenginna niaīnan kittan pāusan anga tenēi ni autenginna prei niaīnan kittan pāusan en {{SITENAME}}.", diff --git a/languages/i18n/ps.json b/languages/i18n/ps.json index cade0ad8..c0eb9576 100644 --- a/languages/i18n/ps.json +++ b/languages/i18n/ps.json @@ -1124,7 +1124,7 @@ "nlinks": "$1 {{PLURAL:$1|تړنه|تړنې}}", "nmembers": "$1 {{PLURAL:$1|غړی|غړي}}", "nrevisions": "$1 {{PLURAL:$1|بڼه|بڼې}}", - "nviews": "$1 {{PLURAL:$1|کتنه|کتنې}}", + "nimagelinks": "په $1 {{PLURAL:$1|کارېدلی مخ|کارېدلي مخونه}}", "ntransclusions": "په $1 {{PLURAL:$1|مخ|مخونو}} کارېدلی", "specialpage-empty": "د دې راپور لپاره کومې پايلې نشته.", diff --git a/languages/i18n/pt-br.json b/languages/i18n/pt-br.json index 26634b19..c6a59caf 100644 --- a/languages/i18n/pt-br.json +++ b/languages/i18n/pt-br.json @@ -1578,7 +1578,7 @@ "nmembers": "$1 {{PLURAL:$1|membro|membros}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|membro|membros}}", "nrevisions": "$1 {{PLURAL:$1|revisão|revisões}}", - "nviews": "$1 {{PLURAL:$1|visita|visitas}}", + "nimagelinks": "Utilizada em $1 {{PLURAL:$1|página|páginas}}", "ntransclusions": "usada {{PLURAL:$1|numa página|em $1 páginas}}", "specialpage-empty": "Atualmente não há dados a serem exibidos nesta página.", diff --git a/languages/i18n/pt.json b/languages/i18n/pt.json index 3a0e736e..16c4b5c9 100644 --- a/languages/i18n/pt.json +++ b/languages/i18n/pt.json @@ -1564,7 +1564,7 @@ "nmembers": "$1 {{PLURAL:$1|membro|membros}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|membro|membros}}", "nrevisions": "$1 {{PLURAL:$1|edição|edições}}", - "nviews": "$1 {{PLURAL:$1|visita|visitas}}", + "nimagelinks": "Usada {{PLURAL:$1|numa página|em $1 páginas}}", "ntransclusions": "usada {{PLURAL:$1|numa página|em $1 páginas}}", "specialpage-empty": "Não existem dados para apresentar.", diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json index db301158..fef1ce51 100644 --- a/languages/i18n/qqq.json +++ b/languages/i18n/qqq.json @@ -1768,7 +1768,6 @@ "nmembers": "Appears in brackets after each category listed on the special page [[Special:WantedCategories]].\n\nParameters:\n* $1 - the number of members of the category\nSee also:\n* {{msg-mw|Nmemberschanged}}", "nmemberschanged": "Appears in brackets after each category listed on the special page [[Special:WantedCategories]] if the number of pages in the category has changed since the list was last refreshed.\n\nParameters:\n* $1 - the original number of members of the category\n* $2 - the current one\nSee also:\n* {{msg-mw|Nmembers}}", "nrevisions": "Used as link text in [[Special:FewestRevisions]].\n\nThe link points to the page history (action=history).\n\nParameters:\n* $1 - number of revisions", - "nviews": "This message is used on [[Special:PopularPages]] to say how many times each page has been viewed.\n\nPreceded by the page title, like: Page title ($1 views)\n\nParameters:\n* $1 - the number of views", "nimagelinks": "Used on [[Special:MostLinkedFiles]] to indicate how often a specific file is used.\n\nParameters:\n* $1 - number of pages\nSee also:\n* {{msg-mw|Ntransclusions}}", "ntransclusions": "Used on [[Special:MostTranscludedPages]] to indicate how often a template is in use.\n\nParameters:\n* $1 - number of pages\nSee also:\n* {{msg-mw|Nimagelinks}}", "specialpage-empty": "Used on a special page when there is no data. For example on [[Special:Unusedimages]] when all images are used.", diff --git a/languages/i18n/qu.json b/languages/i18n/qu.json index d91d0941..103aed86 100644 --- a/languages/i18n/qu.json +++ b/languages/i18n/qu.json @@ -1447,7 +1447,7 @@ "nmembers": "$1 {{PLURAL:$1|qillqa|qillqakuna}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|wankurisqa|wankurisqakuna}}", "nrevisions": "$1 {{PLURAL:$1|llamk'apusqa|llamk'apusqakuna}}", - "nviews": "$1 {{PLURAL:$1|rikuy|rikuykuna}}", + "nimagelinks": "$1 {{PLURAL:$1|p'anqapi|p'anqakunapi}} llamk'achisqa", "ntransclusions": "$1 {{PLURAL:$1|p'anqapi|p'anqakunapi}} llamk'achisqa", "specialpage-empty": "Kay p'anqaqa ch'usaqmi.", diff --git a/languages/i18n/rm.json b/languages/i18n/rm.json index a94802cb..4c0c1032 100644 --- a/languages/i18n/rm.json +++ b/languages/i18n/rm.json @@ -1339,7 +1339,7 @@ "nlinks": "$1 {{PLURAL:$1|colliaziun|colliaziuns}}", "nmembers": "$1 {{PLURAL:$1|commember|commembers}}", "nrevisions": "{{PLURAL:$1|Ina versiun|$1 versiuns}}", - "nviews": "Contemplà $1 {{PLURAL:$1|giada|giadas}}", + "nimagelinks": "Utilisà sin $1 {{PLURAL:$1|pagina|paginas}}", "ntransclusions": "utilisà sin $1 {{PLURAL:$1|pagina|paginas}}", "specialpage-empty": "Questa pagina cuntegna actualmain naginas endataziuns.", diff --git a/languages/i18n/ro.json b/languages/i18n/ro.json index a3e56eff..bdecc0a8 100644 --- a/languages/i18n/ro.json +++ b/languages/i18n/ro.json @@ -1528,7 +1528,7 @@ "nmembers": "$1 {{PLURAL:$1|membru|membri|de membri}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|membru|membri|de membri}}", "nrevisions": "{{PLURAL:$1|o versiune|$1 versiuni|$1 de versiuni}}", - "nviews": "{{PLURAL:$1|o accesare|$1 accesări|$1 de accesări}}", + "nimagelinks": "Utilizat pe $1 {{PLURAL:$1|pagină|pagini}}", "ntransclusions": "utilizat pe $1 {{PLURAL:$1|pagină|pagini}}", "specialpage-empty": "Această pagină este goală.", diff --git a/languages/i18n/roa-tara.json b/languages/i18n/roa-tara.json index 35f80491..47220c56 100644 --- a/languages/i18n/roa-tara.json +++ b/languages/i18n/roa-tara.json @@ -1438,7 +1438,7 @@ "nlinks": "$1 {{PLURAL:$1|collegamende|collegaminde}}", "nmembers": "$1 {{PLURAL:$1|membre|membre}}", "nrevisions": "$1 {{PLURAL:$1|revisione|revisiune}}", - "nviews": "$1 {{PLURAL:$1|visite|visite}}", + "nimagelinks": "Ausate sus a $1 {{PLURAL:$1|pàgene|pàggene}}", "ntransclusions": "ausate sus a $1 {{PLURAL:$1|pàgene|pàggene}}", "specialpage-empty": "Non ge stonne resultete pe stu report.", diff --git a/languages/i18n/ru.json b/languages/i18n/ru.json index 06b4b7ba..a3e8999a 100644 --- a/languages/i18n/ru.json +++ b/languages/i18n/ru.json @@ -1582,7 +1582,7 @@ "nmembers": "$1 {{PLURAL:$1|объект|объекта|объектов}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|объект|объекта|объектов}}", "nrevisions": "$1 {{PLURAL:$1|версия|версии|версий}}", - "nviews": "$1 {{PLURAL:$1|просмотр|просмотра|просмотров}}", + "nimagelinks": "Используется на $1 {{PLURAL:$1|странице|страницах}}", "ntransclusions": "используется на $1 {{PLURAL:$1|странице|страницах}}", "specialpage-empty": "Запрос не дал результатов.", diff --git a/languages/i18n/rue.json b/languages/i18n/rue.json index dfa980a7..d50e14fb 100644 --- a/languages/i18n/rue.json +++ b/languages/i18n/rue.json @@ -1426,7 +1426,7 @@ "nlinks": "$1 {{PLURAL:$1|одказ|одказы|одказів}}", "nmembers": "$1 {{PLURAL:$1|обєкт|обєкты|обєктів}}", "nrevisions": "$1 {{PLURAL:$1|ревізія|ревізії|ревізій}}", - "nviews": "$1 {{PLURAL:$1|навщіва|навщівы|навщів}}", + "nimagelinks": "Хоснованый ня $1 {{PLURAL:$1|сторінка|сторінкы|сторінках}}", "ntransclusions": "хоснованый ня $1 {{PLURAL:$1|сторінка|сторінкы|сторінках}}", "specialpage-empty": "Той пожадавцї не одповідають жадны записы.", diff --git a/languages/i18n/sa.json b/languages/i18n/sa.json index c3df68df..1bdf32dd 100644 --- a/languages/i18n/sa.json +++ b/languages/i18n/sa.json @@ -1482,7 +1482,7 @@ "nlinks": "$1 {{PLURAL:$1|अनुबन्धः|अनुबन्धाः}}", "nmembers": "$1 {{PLURAL:$1|योजकः|योजकाः}}", "nrevisions": "$1 {{PLURAL:$1|पुनरावृत्तिः}}", - "nviews": "$1 {{PLURAL:$1|अनुबन्धः|अनुबन्धाः}}", + "nimagelinks": "$1 {{PLURAL:$1|पुटम्|पुटानि}} प्रयुक्तानि ।", "ntransclusions": "$1 {{PLURAL:$1|पुटम्|पुटानि}} प्रयुक्तानि ।", "specialpage-empty": "अस्य वृत्तस्य परिणामः नास्ति ।", diff --git a/languages/i18n/sah.json b/languages/i18n/sah.json index ca59d025..27e1313e 100644 --- a/languages/i18n/sah.json +++ b/languages/i18n/sah.json @@ -1511,7 +1511,7 @@ "nmembers": "$1 {{PLURAL:$1|кыттааччы|кыттааччылаах}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|эбийиэк|эбийиэктээх}}", "nrevisions": "$1 {{PLURAL:$1|барыллаах|барыл баар}}", - "nviews": "$1 көрүүлээх", + "nimagelinks": "$1 {{PLURAL:$1|сирэйгэ|ахсааннаах сирэйгэ}} туттуллар", "ntransclusions": "$1 {{PLURAL:$1|сирэйгэ|ахсааннаах сирэйгэ}} туттуллар", "specialpage-empty": "Көрдөөн тугу да булбата.", diff --git a/languages/i18n/sc.json b/languages/i18n/sc.json index 4eb51675..faf25ac3 100644 --- a/languages/i18n/sc.json +++ b/languages/i18n/sc.json @@ -1003,7 +1003,7 @@ "nlinks": "$1 {{PLURAL:$1|ligòngiu|ligòngios}}", "nmembers": "$1 {{PLURAL:$1|cumponente|cumponentes}}", "nrevisions": "$1 {{PLURAL:$1|revisione|revisiones}}", - "nviews": "$1 {{PLURAL:$1|bisura|bisuras}}", + "lonelypages": "Pàginas burdas", "uncategorizedpages": "Pàginas chentza categoria", "uncategorizedcategories": "Categorias chentza categoria", diff --git a/languages/i18n/scn.json b/languages/i18n/scn.json index 39bcc39a..d2fec3fb 100644 --- a/languages/i18n/scn.json +++ b/languages/i18n/scn.json @@ -1501,7 +1501,7 @@ "nmembers": "$1 {{PLURAL:$1|membru|membra}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|membru|membra}}", "nrevisions": "$1 {{PLURAL:$1|rivisioni|rivisioni}}", - "nviews": "$1 {{PLURAL:$1|vìsita|vìsiti}}", + "nimagelinks": "Adupiratu nta $1 {{PLURAL:$1|pàggina|pàggini}}", "ntransclusions": "adupiratu nta $1 {{PLURAL:$1|pàggina|pàggini}}", "specialpage-empty": "Nun cci su' risultati pi' stu rennicuntu.", diff --git a/languages/i18n/sco.json b/languages/i18n/sco.json index 7fde9aba..eec362c8 100644 --- a/languages/i18n/sco.json +++ b/languages/i18n/sco.json @@ -1501,7 +1501,7 @@ "nmembers": "$1 {{PLURAL:$1|memmer|memmers}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|memmer|memmers}}", "nrevisions": "$1 {{PLURAL:$1|reveesion|reveesions}}", - "nviews": "$1 {{PLURAL:$1|luik|luiks}}", + "nimagelinks": "Uised oan $1 {{PLURAL:$1|page|pages}}", "ntransclusions": "uised oan $1 {{PLURAL:$1|page|pages}}", "specialpage-empty": "Thaur's naw ootcomes fer this report.", diff --git a/languages/i18n/sdc.json b/languages/i18n/sdc.json index f97f953f..cd51829f 100644 --- a/languages/i18n/sdc.json +++ b/languages/i18n/sdc.json @@ -838,7 +838,7 @@ "nlinks": "$1 {{PLURAL:$1|cullegamentu|cullegamenti}}", "nmembers": "$1 {{PLURAL:$1|erementu|erementi}}", "nrevisions": "$1 {{PLURAL:$1|ribisioni|ribisioni}}", - "nviews": "$1 {{PLURAL:$1|visita|visiti}}", + "specialpage-empty": "Chisthu rapporthu nò cunteni nisciun risulthaddu.", "lonelypages": "Pàgini òiffani", "lonelypagestext": "Li sighenti pàgini so chena cullegamenti chi prubenani d'althri pàgini di {{SITENAME}}.", diff --git a/languages/i18n/se.json b/languages/i18n/se.json index 22bb6212..47c3f6cc 100644 --- a/languages/i18n/se.json +++ b/languages/i18n/se.json @@ -626,7 +626,7 @@ "nlinks": "$1 {{PLURAL:$1|liŋka|liŋkka}}", "nmembers": "$1 {{PLURAL:$1|lahttu|lahtu}}", "nrevisions": "$1 {{PLURAL:$1|rievdádus|rievdádusa}}", - "nviews": "$1 {{PLURAL:$1|láden|ládema}}", + "specialpage-empty": "Dán siiddus ii leat teaksta.", "lonelypages": "Oarbbes siiddut", "lonelypagestext": "Čuovvovaš siidduide ii čujuhuvvo eará siidduin.", diff --git a/languages/i18n/sei.json b/languages/i18n/sei.json index d3a576f9..93ce1d28 100644 --- a/languages/i18n/sei.json +++ b/languages/i18n/sei.json @@ -600,7 +600,7 @@ "nlinks": "$1 {{PLURAL:$1|link|linkám}}", "nmembers": "$1 {{PLURAL:$1|diipolam|diipolám}}", "nrevisions": "$1 {{PLURAL:$1|revicion|revición}}", - "nviews": "$1 {{PLURAL:$1|cohuatl|cohuátl}}", + "prefixindex": "Indexde prefix", "shortpages": "Páhinám diibajlipám", "longpages": "Páhinám bajlipám", diff --git a/languages/i18n/ses.json b/languages/i18n/ses.json index 8ec5156c..2fe76d06 100644 --- a/languages/i18n/ses.json +++ b/languages/i18n/ses.json @@ -1500,7 +1500,7 @@ "nmembers": "{{PLURAL:$1|kondayze}} $1", "nmemberschanged": "{{PLURAL:$2|kondayze}} $1 → $2 \\", "nrevisions": "{{PLURAL:$1|filla}} $1", - "nviews": "{{PLURAL:$1|gunari}} $1 \\", + "nimagelinks": "Goyandi {{PLURAL:$1|moo}} ga", "ntransclusions": "goyandi {{PLURAL:$1|moo}} 1", "specialpage-empty": "Hunyan kulyaŋ ši bayrandiroo woo se.", diff --git a/languages/i18n/sgs.json b/languages/i18n/sgs.json index 3de17ab1..db6383de 100644 --- a/languages/i18n/sgs.json +++ b/languages/i18n/sgs.json @@ -939,7 +939,7 @@ "nlinks": "$1 {{PLURAL:$1|nūruoda|nūruodas|nūruodu}}", "nmembers": "$1 {{PLURAL:$1|narīs|narē|nariū}}", "nrevisions": "$1 {{PLURAL:$1|pakeitėms|pakeitėmā|pakeitėmu}}", - "nviews": "$1 {{PLURAL:$1|paruodīms|paruodīmā|paruodīmu}}", + "specialpage-empty": "Šėtā ataskaitā nie rezoltatu.", "lonelypages": "Vėinišė straipsnē", "lonelypagestext": "I šėtuos poslapius nier nūruodu ėš kėtū šėta pruojekta poslapiu.", diff --git a/languages/i18n/sh.json b/languages/i18n/sh.json index 23a59acc..4a461286 100644 --- a/languages/i18n/sh.json +++ b/languages/i18n/sh.json @@ -1453,7 +1453,7 @@ "nmembers": "$1 {{PLURAL:$1|član|članova}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|član|članova}}", "nrevisions": "$1 {{PLURAL:$1|revizija|revizije|revizija}}", - "nviews": "$1 {{PLURAL:$1|pregled|pregleda}}", + "nimagelinks": "Koristi se na $1 {{PLURAL:$1|stranici|stranice|stranica}}", "ntransclusions": "koristi se na $1 {{PLURAL:$1|stranici|stranice|stranica}}", "specialpage-empty": "Ne postoje rezultati za ovaj izvještaj.", diff --git a/languages/i18n/shi.json b/languages/i18n/shi.json index df7d659f..64a3ee4a 100644 --- a/languages/i18n/shi.json +++ b/languages/i18n/shi.json @@ -651,7 +651,7 @@ "nlinks": "$1 {{PLURAL:$1|azday|izdayn}}", "nmembers": "$1 {{PLURAL:$1|agmam|igmamn}}", "nrevisions": "$1 {{PLURAL:$1|asgadda|isgaddatn}}", - "nviews": "$1 {{PLURAL:$1|assag|issagn}}", + "specialpage-empty": "Ur illa mayttukfan i asaggu yad", "lonelypages": "Tasnatiwin tigigilin", "lonelypagestext": "Tisnawinad ur ur tuyzdaynt z ulla lant ɣ tisniwin yaḍnin ɣ {{SITENAME}}.", diff --git a/languages/i18n/si.json b/languages/i18n/si.json index ce40d751..a46239a0 100644 --- a/languages/i18n/si.json +++ b/languages/i18n/si.json @@ -1420,7 +1420,7 @@ "nlinks": "{{PLURAL:$1|එක් සබැඳියකි|සබැඳියන් $1 කි}}", "nmembers": "{{PLURAL:$1|එක් සාමාජිකයෙකි|සාමාජීකයන් $1 කි}}", "nrevisions": "{{PLURAL:$1|එක් සංශෝධනයකි|සංශෝධන $1 කි }}", - "nviews": " {{PLURAL:$1|නැරඹුම් එකකි|නැරඹුම් $1 කි}}", + "nimagelinks": "{{PLURAL:$1|පිටු|පිටු}} $1 ක භාවිතාකර ඇත", "ntransclusions": "{{PLURAL:$1|පිටු|පිටු}} $1 ක භාවිතාකර ඇත", "specialpage-empty": "මෙම වාර්තාවට ප්රතිඵල කිසිවක් නොමැත.", diff --git a/languages/i18n/sk.json b/languages/i18n/sk.json index b1eeec07..d6c943db 100644 --- a/languages/i18n/sk.json +++ b/languages/i18n/sk.json @@ -1476,7 +1476,7 @@ "nlinks": "$1 {{PLURAL:$1|odkaz|odkazy|odkazov}}", "nmembers": "$1 {{PLURAL:$1|člen|členovia|členov}}", "nrevisions": "$1 {{PLURAL:$1|revízia|revízie|revízií}}", - "nviews": "$1 {{PLURAL:$1|návšteva|návštevy|návštev}}", + "nimagelinks": "Použité na $1 {{PLURAL:$1|stránke|stránkach}}", "ntransclusions": "použité na $1 {{PLURAL:$1|stránke|stránkach}}", "specialpage-empty": "Táto správa neobsahuje žiadne položky.", diff --git a/languages/i18n/sl.json b/languages/i18n/sl.json index 38a5e5a1..e40e41c0 100644 --- a/languages/i18n/sl.json +++ b/languages/i18n/sl.json @@ -1513,7 +1513,7 @@ "nmembers": "$1 {{PLURAL:$1|element|elementa|elementi|elementov|elementov}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|element|elementa|elementi|elementov}}", "nrevisions": "$1 {{PLURAL:$1|redakcija|redakciji|redakcije|redakcij|redakcij}}", - "nviews": "$1 {{PLURAL:$1|ogled|ogleda|ogledi|ogledov|ogledov}}", + "nimagelinks": "Uporabljeno na $1 {{PLURAL:$1|strani|straneh}}", "ntransclusions": "uporabljeno na $1 {{PLURAL:$1|strani|straneh}}", "specialpage-empty": "Za to poročilo ni rezultatov.", diff --git a/languages/i18n/sli.json b/languages/i18n/sli.json index da013e86..9bc76d7e 100644 --- a/languages/i18n/sli.json +++ b/languages/i18n/sli.json @@ -913,7 +913,7 @@ "ncategories": "$1 {{PLURAL:$1|Kategorie|Kategoria}}", "nmembers": "{{PLURAL:$1|1 Eentrag|$1 Eenträge}}", "nrevisions": "{{PLURAL:$1|1 Beoarbeetung|$1 Beoarbeetunga}}", - "nviews": "{{PLURAL:$1|1 Obfroage|$1 Obfroaga}}", + "specialpage-empty": "De Seite enthält aktuell kenne Einträge.", "lonelypages": "Verwaiste Seyta", "lonelypagestext": "De folgenden Seyta waan ne eingebunden oder is werd ne uff se ei {{SITENAME}} verwiesa.", diff --git a/languages/i18n/sma.json b/languages/i18n/sma.json index 4d477e90..024b862e 100644 --- a/languages/i18n/sma.json +++ b/languages/i18n/sma.json @@ -374,7 +374,7 @@ "nlinks": "$1 {{PLURAL:$1|lïenghke|lïenghkeh}}", "nmembers": "$1 {{PLURAL:$1|lihtsege|lihtsegh}}", "nrevisions": "$1 {{PLURAL:$1|gïehtjedamme|gïehtjedammeh}}", - "nviews": "$1 {{PLURAL:$1|vuesehte|vuesehteh}}", + "lonelypages": "Eejhtegapth bielieh", "uncategorizedpages": "Ov-kategorije bielieh", "uncategorizedcategories": "Ov-kategorije kategorijeh", diff --git a/languages/i18n/sq.json b/languages/i18n/sq.json index fc870a20..85b68923 100644 --- a/languages/i18n/sq.json +++ b/languages/i18n/sq.json @@ -1376,7 +1376,7 @@ "nlinks": "$1 {{PLURAL:$1|lidhje|lidhje}}", "nmembers": "$1 {{PLURAL:$1|antar|antarë}}", "nrevisions": "$1 {{PLURAL:$1|version|versione}}", - "nviews": "$1 {{PLURAL:$1|shikim|shikime}}", + "nimagelinks": "Përdorur në $1 {{PLURAL:$1|faqe|faqe}}", "ntransclusions": "përdorur në $1 {{PLURAL:$1|faqe|faqe}}", "specialpage-empty": "Kjo faqe është boshe.", diff --git a/languages/i18n/sr-ec.json b/languages/i18n/sr-ec.json index bf05562b..a764e2a2 100644 --- a/languages/i18n/sr-ec.json +++ b/languages/i18n/sr-ec.json @@ -1518,7 +1518,7 @@ "nmembers": "$1 {{PLURAL:$1|члан|члана|чланова}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|члан|члана|чланова}}", "nrevisions": "$1 {{PLURAL:$1|измена|измене|измена}}", - "nviews": "$1 {{PLURAL:$1|преглед|прегледа|прегледа}}", + "nimagelinks": "Користи се на $1 {{PLURAL:$1|страници|странице|страница}}", "ntransclusions": "користи се на $1 {{PLURAL:$1|страници|странице|страница}}", "specialpage-empty": "Нема резултата за овај извештај.", diff --git a/languages/i18n/sr-el.json b/languages/i18n/sr-el.json index fd5bf80e..7d75b871 100644 --- a/languages/i18n/sr-el.json +++ b/languages/i18n/sr-el.json @@ -1508,7 +1508,7 @@ "nmembers": "$1 {{PLURAL:$1|član|člana|članova}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|član|člana|članova}}", "nrevisions": "$1 {{PLURAL:$1|izmena|izmene|izmena}}", - "nviews": "$1 {{PLURAL:$1|pregled|pregleda|pregleda}}", + "nimagelinks": "Koristi se na $1 {{PLURAL:$1|stranici|stranice|stranica}}", "ntransclusions": "koristi se na $1 {{PLURAL:$1|stranici|stranice|stranica}}", "specialpage-empty": "Nema rezultata za ovaj izveštaj.", diff --git a/languages/i18n/srn.json b/languages/i18n/srn.json index 82189049..f1c1ab65 100644 --- a/languages/i18n/srn.json +++ b/languages/i18n/srn.json @@ -556,7 +556,7 @@ "nlinks": "$1 {{PLURAL:$1|miti|miti}}", "nmembers": "$1 {{PLURAL:$1|memre|memre}}", "nrevisions": "$1 {{PLURAL:$1|si|si}}", - "nviews": "$1 {{PLURAL:$1|mansi|mansi}}", + "lonelypages": "Weisi papira", "lonelypagestext": "Na den ondroben peprewoysi sey fu u {{SITENAME}} no skaki.", "uncategorizedpages": "Papira sondro grupu", diff --git a/languages/i18n/stq.json b/languages/i18n/stq.json index 2e483ca1..b022f7d3 100644 --- a/languages/i18n/stq.json +++ b/languages/i18n/stq.json @@ -1203,7 +1203,7 @@ "nlinks": "{{PLURAL:$1|1 Ferbiendenge|$1 Ferbiendengen}}", "nmembers": "{{PLURAL:$1|1 Iendraach|$1 Iendraage}}", "nrevisions": "{{PLURAL:$1|1 Beoarbaideng|$1 Beoarbaidengen}}", - "nviews": "{{PLURAL:$1|1 Oufroage|$1 Oufroagen}}", + "nimagelinks": "Ferwoand ap $1 {{PLURAL:$1|Siede|Sieden}}", "ntransclusions": "ferwoand ap $1 {{PLURAL:$1|Siede|Sieden}}", "specialpage-empty": "Ju Siede änthaalt aktuell neen Iendraage.", diff --git a/languages/i18n/su.json b/languages/i18n/su.json index 01819be0..bd0bf7a9 100644 --- a/languages/i18n/su.json +++ b/languages/i18n/su.json @@ -1293,7 +1293,7 @@ "nmembers": "$1 {{PLURAL:$1|kontributor|kontributor}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|anggota|anggota}}", "nrevisions": "$1 {{PLURAL:$1|révisi|révisi}}", - "nviews": "$1 {{PLURAL:$1|témbongan|témbongan}}", + "nimagelinks": "Dipaké di $1 {{PLURAL:$1|kaca|kaca}}", "ntransclusions": "dipaké di $1 {{PLURAL:$1|kaca|kaca}}", "specialpage-empty": "Kaca ieu kosong.", diff --git a/languages/i18n/sv.json b/languages/i18n/sv.json index c74e6376..88998787 100644 --- a/languages/i18n/sv.json +++ b/languages/i18n/sv.json @@ -1569,7 +1569,7 @@ "nmembers": "$1 {{PLURAL:$1|medlem|medlemmar}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|medlem|medlemmar}}", "nrevisions": "$1 {{PLURAL:$1|version|versioner}}", - "nviews": "$1 {{PLURAL:$1|visning|visningar}}", + "nimagelinks": "Används på $1 {{PLURAL:$1|sida|sidor}}", "ntransclusions": "används på $1 {{PLURAL:$1|sida|sidor}}", "specialpage-empty": "Den här sidan är tom.", diff --git a/languages/i18n/sw.json b/languages/i18n/sw.json index 878be697..9fc287e3 100644 --- a/languages/i18n/sw.json +++ b/languages/i18n/sw.json @@ -1259,7 +1259,7 @@ "nlinks": "{{PLURAL:$1|kiungo|viungo}} $1", "nmembers": "{{PLURAL:$1|kitu|vitu}} $1", "nrevisions": "{{PLURAL:$1|pitio|mapitio}} $1", - "nviews": "{{PLURAL:$1|mtazamaji|mitazamaji}} $1", + "nimagelinks": "Inatumika katika {{PLURAL:$1|ukurasa moja tu|kurasa $1}}", "ntransclusions": "inatumika katika {{PLURAL:$1|ukurasa moja tu|kurasa $1}}", "specialpage-empty": "Hakuna matokeo katika taarifa hii.", diff --git a/languages/i18n/szl.json b/languages/i18n/szl.json index 16a5a19d..ba778d42 100644 --- a/languages/i18n/szl.json +++ b/languages/i18n/szl.json @@ -1192,7 +1192,7 @@ "nlinks": "$1 {{PLURAL:$1|link|linki|linkůw}}", "nmembers": "$1 {{PLURAL:$1|elyment|elymenty|elymentůw}}", "nrevisions": "$1 {{PLURAL:$1|wersja|wersje|wersjůw}}", - "nviews": "filowano $1 {{PLURAL:$1|roz|rozůw}}", + "specialpage-empty": "Ta zajta je pusto.", "lonelypages": "Poćepńynte zajty", "lonelypagestext": "Do zajtůw půńiżyj ńy adresuje żodno inkszo zajta we {{SITENAME}}.", diff --git a/languages/i18n/ta.json b/languages/i18n/ta.json index 97a26b99..625f69a2 100644 --- a/languages/i18n/ta.json +++ b/languages/i18n/ta.json @@ -1374,7 +1374,7 @@ "nlinks": "$1 {{PLURAL:$1|இணைப்பு|இணைப்புக்கள்}}", "nmembers": "$1 {{PLURAL:$1|உறுப்பினர்|உறுப்பினர்கள்}}", "nrevisions": "{{PLURAL:$1|ஒரு திருத்தம்|$1 திருத்தங்கள்}}", - "nviews": "{{PLURAL:$1|ஒரு பார்வை|$1 பார்வைகள்}}", + "nimagelinks": "$1 {{PLURAL:$!|பக்கத்தில்|பக்கங்களில்}} பயன்படுத்தப்பட்டது", "ntransclusions": "$1 {{PLURAL:$1|பக்கத்தில்|பக்கங்களில்}} பயன்படுத்தப்பட்டது", "specialpage-empty": "இந்தப் புகாருக்குகந்த முடிவுகள் எதுவுமில்லை.", diff --git a/languages/i18n/te.json b/languages/i18n/te.json index 9838a435..da45b84f 100644 --- a/languages/i18n/te.json +++ b/languages/i18n/te.json @@ -1486,7 +1486,7 @@ "nmembers": "$1 {{PLURAL:$1|సభ్యుడు|సభ్యులు}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|సభ్యుడు|సభ్యులు}}", "nrevisions": "{{PLURAL:$1|కూర్పు|$1 కూర్పులు}}", - "nviews": "$1 {{PLURAL:$1|సందర్శన|సందర్శనలు}}", + "nimagelinks": "$1 {{PLURAL:$1|పుట|పుటల}}లో ఉపయోగించారు", "ntransclusions": "$1 {{PLURAL:$1|పుట|పుటల}}లో ఉపయోగించారు", "specialpage-empty": "ఈ పేజీ ఖాళీగా ఉంది.", diff --git a/languages/i18n/tg-cyrl.json b/languages/i18n/tg-cyrl.json index 44b6978a..227b130e 100644 --- a/languages/i18n/tg-cyrl.json +++ b/languages/i18n/tg-cyrl.json @@ -1138,7 +1138,7 @@ "nlinks": "$1 {{PLURAL:$1|пайванд|пайвандҳо}}", "nmembers": "$1 {{PLURAL:$1|узв}}", "nrevisions": "$1 {{PLURAL:$1|вироиш|вироиш}}", - "nviews": "$1 {{PLURAL:$1|намоиш|намоишҳо}}", + "specialpage-empty": "Барои ин ҳисобот натиҷае вуҷуд надорад.", "lonelypages": "Саҳифаҳои ятим", "lonelypagestext": "Ба саҳифаҳои зерин дар дигар саҳифаи {{SITENAME}} пайванд дода нашудааст.", diff --git a/languages/i18n/tg-latn.json b/languages/i18n/tg-latn.json index c3dff497..f1acd0b7 100644 --- a/languages/i18n/tg-latn.json +++ b/languages/i18n/tg-latn.json @@ -845,7 +845,7 @@ "nlinks": "$1 {{PLURAL:$1|pajvand|pajvandho}}", "nmembers": "$1 {{PLURAL:$1|uzv}}", "nrevisions": "$1 {{PLURAL:$1|viroiş|viroiş}}", - "nviews": "$1 {{PLURAL:$1|namoiş|namoişho}}", + "specialpage-empty": "Baroi in hisobot natiçae vuçud nadorad.", "lonelypages": "Sahifahoi jatim", "uncategorizedpages": "Sahifahoe, ki ba jagon gurūh doxil nestand", diff --git a/languages/i18n/th.json b/languages/i18n/th.json index 33c7d5c5..75f69d26 100644 --- a/languages/i18n/th.json +++ b/languages/i18n/th.json @@ -1475,7 +1475,7 @@ "nmembers": "$1 หน้า", "nmemberschanged": "$1 → $2 สมาชิก", "nrevisions": "$1 รุ่นปรับปรุง", - "nviews": "$1 ครั้ง", + "nimagelinks": "ใช้ใน $1 {{PLURAL:$1|หน้า|หน้า}}", "ntransclusions": "ใช้ใน $1 {{PLURAL:$1|หน้า|หน้า}}", "specialpage-empty": "ไม่มีผลลัพธ์รายงานนี้", diff --git a/languages/i18n/tk.json b/languages/i18n/tk.json index ce14aea9..9e65fece 100644 --- a/languages/i18n/tk.json +++ b/languages/i18n/tk.json @@ -1154,7 +1154,7 @@ "nlinks": "$1 {{PLURAL:$1|çykgyt|çykgyt}}", "nmembers": "{{PLURAL:$1|agza|agzalar}}", "nrevisions": "{{PLURAL:$1|wersiýa|wersiýalar}}", - "nviews": "$1 {{PLURAL:$1|synlama|synlama}}", + "specialpage-empty": "Bu habarnama üçin hiç hili netije ýok.", "lonelypages": "Hossarsyz sahypalar", "lonelypagestext": "Aşakdaky sahypalara {{SITENAME}} saýtyndaky başga sahypalardan çykgyt berilmändir ýa-da olara atanaklaýyn girizilmändirler.", diff --git a/languages/i18n/tl.json b/languages/i18n/tl.json index 649f8e92..c041d5c7 100644 --- a/languages/i18n/tl.json +++ b/languages/i18n/tl.json @@ -1405,7 +1405,7 @@ "nlinks": "$1 {{PLURAL:$1|ugnay|mga ugnay}}", "nmembers": "$1 {{PLURAL:$1|kasapi|mga kasapi}}", "nrevisions": "$1 {{PLURAL:$1|pagbabago|mga pagbabago}}", - "nviews": "$1 {{PLURAL:$1|pagtingin|mga pagtingin}}", + "nimagelinks": "Ginamit sa $1 {{PLURAL:$1|pahina|mga pahina}}", "ntransclusions": "ginamit sa $1 {{PLURAL:$1|pahina|mga pahina}}", "specialpage-empty": "Walang resulta para sa ulat na ito.", diff --git a/languages/i18n/tr.json b/languages/i18n/tr.json index a910adf9..36e357ae 100644 --- a/languages/i18n/tr.json +++ b/languages/i18n/tr.json @@ -1564,7 +1564,7 @@ "nmembers": "{{PLURAL:$1|üye|üye}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|üye|üye}}", "nrevisions": "{{PLURAL:$1|değişiklik|değişiklikler}}", - "nviews": "$1 {{PLURAL:$1|görünüm|görünüm}}", + "nimagelinks": "$1 {{PLURAL:$1|sayfada|sayfada}} kullanılıyor", "ntransclusions": "$1 {{PLURAL:$1|sayfada|sayfada}} kullanılıyor", "specialpage-empty": "Bu rapor için hiç sonuç yok.", diff --git a/languages/i18n/tyv.json b/languages/i18n/tyv.json index 34f12ac4..4ff5748d 100644 --- a/languages/i18n/tyv.json +++ b/languages/i18n/tyv.json @@ -635,7 +635,7 @@ "nlinks": "$1 {{PLURAL:$1|холбаа}}", "nmembers": "$1 {{PLURAL:$1|кежигүн}}", "nrevisions": "$1 {{PLURAL:$1|үндүрери}}", - "nviews": "$1 {{PLURAL:$1|көрүш}}", + "specialpage-empty": "Бо илеткелдиң түңнели чок.", "lonelypages": "Чааскаан арыннар", "uncategorizedpages": "Бөлүк эвес арыннар", diff --git a/languages/i18n/tzm.json b/languages/i18n/tzm.json index 04f2eb21..bcaff68e 100644 --- a/languages/i18n/tzm.json +++ b/languages/i18n/tzm.json @@ -387,7 +387,7 @@ "withoutinterwiki-submit": "ⵥⵕ", "nbytes": "$1 {{PLURAL:$1|byte|bytes}}", "ncategories": "$1 {{PLURAL:$1|ⵜⴰⴳⴳⴰⵢⵜ|ⵜⴰⴳⴳⴰⵢⵉⵏ}}", - "nviews": "$1 {{PLURAL:$1|ⵥⵕ|ⵥⵕ ⴰⴽⴽ}}", + "longpages": "ⵜⴰⵙⵏⵉⵡⵉⵏ ⵎⵇⵇⴰⵔⵏⵜ", "newpages": "ⵜⵉⵙⵏⵉⵡⵉⵏ ⵜⵉⵎⴰⵢⵏⵓⵜⵉⵏ", "newpages-username": "ⴰⵙⵙⴰⵖ ⵓⵎⴷⴰⵏ:", diff --git a/languages/i18n/ug-arab.json b/languages/i18n/ug-arab.json index 2c73fb52..340ba587 100644 --- a/languages/i18n/ug-arab.json +++ b/languages/i18n/ug-arab.json @@ -1409,7 +1409,7 @@ "nlinks": "$1 {{PLURAL:$1|ئۇلانما|ئۇلانما}}", "nmembers": "$1 {{PLURAL:$1|ئەزا|ئەزا}}", "nrevisions": "$1 {{PLURAL:$1|تۈزىتىش|تۈزىتىش}}", - "nviews": "$1 {{PLURAL:$1|زىيارەت|زىيارەت}}", + "nimagelinks": "$1 {{PLURAL:$1|بەت|بەت}} تە ئىشلىتىلىدۇ", "ntransclusions": "$1 {{PLURAL:$1|بەت|بەت}} تە ئىشلىتىلدى", "specialpage-empty": "بۇ دوكلاتنىڭ نەتىجىسى يوق.", diff --git a/languages/i18n/uk.json b/languages/i18n/uk.json index 1d209d92..27f9e134 100644 --- a/languages/i18n/uk.json +++ b/languages/i18n/uk.json @@ -1573,7 +1573,7 @@ "nmembers": "$1 {{PLURAL:$1|об'єкт|об'єкти|об'єктів}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|член|члени|членів}}", "nrevisions": "$1 {{PLURAL:$1|версія|версії|версій}}", - "nviews": "$1 {{PLURAL:$1|перегляд|перегляди|переглядів}}", + "nimagelinks": "Використовується на $1 {{PLURAL:$1|1=сторінці|сторінках}}", "ntransclusions": "використовується на $1 {{PLURAL:$1|1=сторінці|сторінках}}", "specialpage-empty": "Запит не дав результатів.", diff --git a/languages/i18n/vec.json b/languages/i18n/vec.json index 2df5ff48..29a11bf5 100644 --- a/languages/i18n/vec.json +++ b/languages/i18n/vec.json @@ -1370,7 +1370,7 @@ "nlinks": "$1 {{PLURAL:$1|colegamento|colegamenti}}", "nmembers": "$1 {{PLURAL:$1|elemento|elementi}}", "nrevisions": "$1 {{PLURAL:$1|revision}}", - "nviews": "$1 {{PLURAL:$1|visita|visite}}", + "nimagelinks": "Doparà su $1 {{PLURAL:$1|pagina|pagine}}", "ntransclusions": "doparà su $1 {{PLURAL:$1|pagina|pagine}}", "specialpage-empty": "Sto raporto no'l contien nissun risultato.", diff --git a/languages/i18n/vep.json b/languages/i18n/vep.json index 36f17887..7caba5d5 100644 --- a/languages/i18n/vep.json +++ b/languages/i18n/vep.json @@ -1179,7 +1179,7 @@ "nlinks": "$1 {{PLURAL:$1|kosketuz|kosketust}}", "nmembers": "$1 {{PLURAL:$1|ühtnii|ühtnijad}}", "nrevisions": "$1 {{PLURAL:$1|versii|versijad}}", - "nviews": "$1 {{PLURAL:$1|kacund|kacundad}}", + "specialpage-empty": "Ecind ei ole andnu rezul'tatad.", "lonelypages": "Üksjäižed lehtpoled", "lonelypagestext": "Ozutadud lehtpolid ei kosketagoi toižed necen saitan lehtpoled; ozutadud lehtpoled mugažo ei olgoi mülütadud toižihe lehtpolihe.", diff --git a/languages/i18n/vi.json b/languages/i18n/vi.json index 21f39b23..fa257187 100644 --- a/languages/i18n/vi.json +++ b/languages/i18n/vi.json @@ -1528,7 +1528,7 @@ "nmembers": "$1 trang", "nmemberschanged": "$1 → $2 trang", "nrevisions": "$1 {{PLURAL:$1|phiên bản|phiên bản}}", - "nviews": "$1 {{PLURAL:$1|lượt truy cập|lượt truy cập}}", + "nimagelinks": "Được sử dụng trong $1 trang", "ntransclusions": "được sử dụng trong $1 trang", "specialpage-empty": "Trang này đang trống.", diff --git a/languages/i18n/vo.json b/languages/i18n/vo.json index d51a5fca..5783728a 100644 --- a/languages/i18n/vo.json +++ b/languages/i18n/vo.json @@ -1112,7 +1112,7 @@ "nlinks": "{{PLURAL:$1|yüm|yüms}} $1", "nmembers": "{{PLURAL:$1|liman|limans}} $1", "nrevisions": "{{PLURAL:$1|fomam|fomams}} $1", - "nviews": "{{PLURAL:$1|logam|logams}} $1", + "nimagelinks": "Pageböl in {{PLURAL:$1|pad|pads}} $1", "ntransclusions": "pageböl in {{PLURAL:$1|pad|pads}} $1", "specialpage-empty": "Pad at vagon.", diff --git a/languages/i18n/vro.json b/languages/i18n/vro.json index a65ac571..33365089 100644 --- a/languages/i18n/vro.json +++ b/languages/i18n/vro.json @@ -967,7 +967,7 @@ "nlinks": "$1 {{PLURAL:$1|link|linki}}", "nmembers": "$1 {{PLURAL:$1|liigõq|liigõt}}", "nrevisions": "$1 {{PLURAL:$1|muutminõ|muutmist}}", - "nviews": "Käümiisi: $1", + "specialpage-empty": "Taa leht om tühi.", "lonelypages": "Artikliq, kohe olõ-i linke", "lonelypagestext": "Nailõ lehile olõ-i muialt vikist linke.", diff --git a/languages/i18n/wa.json b/languages/i18n/wa.json index 939fbe35..187ce81f 100644 --- a/languages/i18n/wa.json +++ b/languages/i18n/wa.json @@ -888,7 +888,7 @@ "nlinks": "$1 {{PLURAL:$1|loyén|loyéns}}", "nmembers": "$1 {{PLURAL:$1|mimbe|mimbes}}", "nrevisions": "$1 {{PLURAL:$1|modêye|modêyes}}", - "nviews": "léjhowe $1 {{PLURAL:$1|côp|côps}}", + "nimagelinks": "Eployî so $1 pådje{{PLURAL:$1||s}}", "ntransclusions": "eployî so $1 pådje{{PLURAL:$1||s}}", "specialpage-empty": "Cisse pådje cial est vude.", diff --git a/languages/i18n/war.json b/languages/i18n/war.json index d2df1139..ae8b94a5 100644 --- a/languages/i18n/war.json +++ b/languages/i18n/war.json @@ -1147,7 +1147,7 @@ "nlinks": "$1 {{PLURAL:$1|nga sumpay|nga mga sumpay}}", "nmembers": "$1 {{PLURAL:$1|nga api|nga mga api}}", "nrevisions": "$1 {{PLURAL:$1|nga pagliwat|nga mga pagliwat}}", - "nviews": "$1 {{PLURAL:$1|nga pangita|nga mga pangita}}", + "nimagelinks": "Gingamit ha $1 {{PLURAL:$1|nga pakli|nga mga pakli}}", "ntransclusions": "gingamit ha $1 {{PLURAL:$1|nga pakli|nga mga pakli}}", "specialpage-empty": "Waray mga resulta para hini nga report.", diff --git a/languages/i18n/wo.json b/languages/i18n/wo.json index 48db3591..a4840962 100644 --- a/languages/i18n/wo.json +++ b/languages/i18n/wo.json @@ -1004,7 +1004,7 @@ "nlinks": "$1 {{PLURAL:$1|lëkkalekaay|ciy lëkkalekaay}}", "nmembers": "$1 {{PLURAL:$1|xët|ciy xët}} ci biir", "nrevisions": "$1 {{PLURAL:$1|sumb|sumb}}", - "nviews": "$1 {{PLURAL:$1|nemmeeku|nemmeeku}}", + "specialpage-empty": "Xët wii amul dara", "lonelypages": "Xëti jiriim", "lonelypagestext": "Xët yiy toftal amuñuy lëkkalekaay yu ne ci yeneen xët yu leen di ubbi te ëmbuwuñu itam ci benn xëtu {{SITENAME}}.", diff --git a/languages/i18n/yi.json b/languages/i18n/yi.json index fa623c1c..9add79f9 100644 --- a/languages/i18n/yi.json +++ b/languages/i18n/yi.json @@ -1492,7 +1492,7 @@ "nmembers": "$1 {{PLURAL:$1|בלאט|בלעטער}}", "nmemberschanged": "$1 → $2 {{PLURAL:$2|מיטגליד|מיטגלידער}}", "nrevisions": "{{PLURAL:$1|איין רעוויזיע|$1 רעוויזיעס}}", - "nviews": "{{PLURAL:$1|איין קוק|$1 קוקן}}", + "nimagelinks": "געניצט אויף $1 {{PLURAL:$1|בלאַט|בלעטער}}", "ntransclusions": "געניצט אויף $1 {{PLURAL:$1|בלאַט|בלעטער}}", "specialpage-empty": "דער בלאט איז ליידיג.", diff --git a/languages/i18n/yo.json b/languages/i18n/yo.json index 4106e1b8..d4d75c0f 100644 --- a/languages/i18n/yo.json +++ b/languages/i18n/yo.json @@ -1366,7 +1366,7 @@ "nlinks": "{{PLURAL:$1|ìjápọ̀|àwọn ìjápọ̀}} $1", "nmembers": "{{PLURAL:$1|ará|àwọn ará}} $1", "nrevisions": "{{PLURAL:$1|àtúnyẹ̀wò|àwọn àtúnyẹ̀wò}} $1", - "nviews": "{{PLURAL:$1|Ìwò|Àwọn ìwò}} $1", + "nimagelinks": "Lílò lórí {{PLURAL:$1|ojúewé|àwọn ojúewé}} $1", "ntransclusions": "lílò lórí {{PLURAL:$1|ojúewé|àwọn ojúewé}} $1", "specialpage-empty": "Kò sí àwọn èsì kankan fún ìjábọ̀ yìí.", diff --git a/languages/i18n/yue.json b/languages/i18n/yue.json index d1a97840..1e0b62e0 100644 --- a/languages/i18n/yue.json +++ b/languages/i18n/yue.json @@ -1454,7 +1454,7 @@ "nmembers": "$1 位成員", "nmemberschanged": "$1 → $2 {{PLURAL:$2|位成員}}", "nrevisions": "$1 次修訂", - "nviews": "$1 次瀏覽", + "nimagelinks": "用響$1版", "ntransclusions": "用響$1版", "specialpage-empty": "呢個報告嘅結果係空嘅。", diff --git a/languages/i18n/zh-hans.json b/languages/i18n/zh-hans.json index 91a19dc4..0f713d66 100644 --- a/languages/i18n/zh-hans.json +++ b/languages/i18n/zh-hans.json @@ -1588,7 +1588,7 @@ "nmembers": "$1个成员", "nmemberschanged": "$1 → $2个成员", "nrevisions": "$1个版本", - "nviews": "$1次浏览", + "nimagelinks": "用于$1个页面中", "ntransclusions": "用于$1个页面中", "specialpage-empty": "此报告无结果。", diff --git a/languages/i18n/zh-hant.json b/languages/i18n/zh-hant.json index 4b756d34..763be52b 100644 --- a/languages/i18n/zh-hant.json +++ b/languages/i18n/zh-hant.json @@ -1562,7 +1562,7 @@ "nmembers": "$1 個成員", "nmemberschanged": "$1 → $2 個成員", "nrevisions": "$1 次修訂", - "nviews": "$1 次檢視", + "nimagelinks": "被 $1 個頁面使用", "ntransclusions": "被 $1 個頁面使用", "specialpage-empty": "此報表無查無任何結果。", diff --git a/languages/i18n/zh-tw.json b/languages/i18n/zh-tw.json index 9abb1375..09ead418 100644 --- a/languages/i18n/zh-tw.json +++ b/languages/i18n/zh-tw.json @@ -339,7 +339,6 @@ "lonelypagestext": "以下頁面尚未被這個wiki中的其它頁面連結。", "uncategorizedimages": "待分類圖片", "unusedimages": "未使用圖片", - "popularpages": "熱門頁面", "mostimages": "最多連結圖片", "prefixindex": "所有頁面之前綴", "deadendpagestext": "以下頁面沒有連結到這個wiki中的其它頁面。", diff --git a/languages/messages/MessagesAce.php b/languages/messages/MessagesAce.php index 40627a25..4bbe9664 100644 --- a/languages/messages/MessagesAce.php +++ b/languages/messages/MessagesAce.php @@ -116,7 +116,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Peugah_haba_lon' ), 'Newimages' => array( 'Beureukaih_baro' ), 'Newpages' => array( 'On_baro' ), - 'Popularpages' => array( 'On_meuceuhu' ), + 'Preferences' => array( 'Geunalak' ), 'Prefixindex' => array( 'Dapeuta_neuaway' ), 'Protectedpages' => array( 'On_nyang_geupeulindong' ), diff --git a/languages/messages/MessagesAf.php b/languages/messages/MessagesAf.php index 7482841a..b6ba4f58 100644 --- a/languages/messages/MessagesAf.php +++ b/languages/messages/MessagesAf.php @@ -151,7 +151,7 @@ $specialPageAliases = array( 'Newimages' => array( 'Nuwe_beelde', 'Nuwebeelde', 'Nuwe_lêers', 'Nuwelêers' ), 'Newpages' => array( 'Nuwe_bladsye', 'Nuwebladsye' ), 'PasswordReset' => array( 'WagwoordHerstel' ), - 'Popularpages' => array( 'PopulêreBladsye' ), + 'Preferences' => array( 'Voorkeure' ), 'Prefixindex' => array( 'VoorvoegselIndeks' ), 'Protectedpages' => array( 'BeskermdeBladsye' ), diff --git a/languages/messages/MessagesAln.php b/languages/messages/MessagesAln.php index 588cf340..df4f9678 100644 --- a/languages/messages/MessagesAln.php +++ b/languages/messages/MessagesAln.php @@ -44,7 +44,7 @@ $namespaceGenderAliases = array( ); $specialPageAliases = array( - 'Popularpages' => array( 'Faqe të famshme' ), + 'Search' => array( 'Kërko' ), ); diff --git a/languages/messages/MessagesAn.php b/languages/messages/MessagesAn.php index 7ec924e6..2a4a45fd 100644 --- a/languages/messages/MessagesAn.php +++ b/languages/messages/MessagesAn.php @@ -88,7 +88,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'A_mía_descusión', 'A_mía_pachina_de_descusión' ), 'Newimages' => array( 'Nuevos_fichers', 'Nuevas_imáchens', 'Nuevas_imachens', 'Nuebas_imachens' ), 'Newpages' => array( 'Pachinas_nuevas', 'Pachinas_recients', 'Pachinas_nuebas', 'Pachinas_más_nuebas', 'Pachinas_más_rezients', 'Pachinas_rezients' ), - 'Popularpages' => array( 'Pachinas_populars', 'Pachinas_más_populars' ), + 'Preferences' => array( 'Preferencias' ), 'Prefixindex' => array( 'Pachinas_por_prefixo', 'Mirar_por_prefixo' ), 'Protectedpages' => array( 'Pachinas_protechitas', 'Pachinas_protechidas' ), diff --git a/languages/messages/MessagesAr.php b/languages/messages/MessagesAr.php index 78179900..b3ba0b5c 100644 --- a/languages/messages/MessagesAr.php +++ b/languages/messages/MessagesAr.php @@ -373,7 +373,7 @@ $specialPageAliases = array( 'PageLanguage' => array( 'لغة_الصفحة' ), 'PasswordReset' => array( 'إعادة_ضبط_كلمة_السر' ), 'PermanentLink' => array( 'وصلة_دائمة', 'رابط_دائم' ), - 'Popularpages' => array( 'صفحات_مشهورة' ), + 'Preferences' => array( 'تفضيلات' ), 'Prefixindex' => array( 'فهرس_بادئة' ), 'Protectedpages' => array( 'صفحات_محمية' ), diff --git a/languages/messages/MessagesArc.php b/languages/messages/MessagesArc.php index f88650b3..fdcde474 100644 --- a/languages/messages/MessagesArc.php +++ b/languages/messages/MessagesArc.php @@ -70,7 +70,7 @@ $specialPageAliases = array( 'Newimages' => array( 'ܠܦܦ̈ܐ_ܚܕ̈ܬܐ', 'ܨܘܪ̈ܬܐ_ܚܕ̈ܬܬܐ' ), 'Newpages' => array( 'ܦܐܬܬ̈ܐ_ܚܕ̈ܬܬܐ' ), 'PermanentLink' => array( 'ܐܣܘܪܐ_ܦܝܘܫܐ' ), - 'Popularpages' => array( 'ܦܐܬܬ̈ܐ_ܡܫܡܗ̈ܐ' ), + 'Preferences' => array( 'ܨܒܝܢܝܘ̈ܬܐ' ), 'Protectedpages' => array( 'ܦܐܬܬ̈ܐ_ܢܛܝܪ̈ܬܐ' ), 'Protectedtitles' => array( 'ܟܘܢܝ̈ܐ_ܢܛܝܪ̈ܐ' ), diff --git a/languages/messages/MessagesArz.php b/languages/messages/MessagesArz.php index 4d0b3db6..15fd87c6 100644 --- a/languages/messages/MessagesArz.php +++ b/languages/messages/MessagesArz.php @@ -102,7 +102,7 @@ $specialPageAliases = array( 'PageLanguage' => array( 'لغه_الصفحه' ), 'PasswordReset' => array( 'ضبط_الباسوورد' ), 'PermanentLink' => array( 'وصله_دايمه' ), - 'Popularpages' => array( 'صفح_مشهوره' ), + 'Preferences' => array( 'تفضيلات' ), 'Prefixindex' => array( 'فهرس_بدايه' ), 'Protectedpages' => array( 'صفح_محميه' ), diff --git a/languages/messages/MessagesAs.php b/languages/messages/MessagesAs.php index 9afe0201..157ca84c 100644 --- a/languages/messages/MessagesAs.php +++ b/languages/messages/MessagesAs.php @@ -106,7 +106,7 @@ $specialPageAliases = array( 'Newpages' => array( 'পৰৱৰ্তী_পৃষ্ঠা' ), 'PasswordReset' => array( 'গুপ্তশব্দ_ঘূৰাই_আনক' ), 'PermanentLink' => array( 'স্থায়ী_সংযোগ' ), - 'Popularpages' => array( 'জনপ্ৰিয়_পৃষ্ঠাসমূহ' ), + 'Preferences' => array( 'পচন্দ' ), 'Protectedpages' => array( 'সুৰক্ষিত_পৃষ্ঠাসমূহ' ), 'Protectedtitles' => array( 'সুৰক্ষিত_শিৰোনামসমূহ' ), diff --git a/languages/messages/MessagesAv.php b/languages/messages/MessagesAv.php index ea64271c..b97de929 100644 --- a/languages/messages/MessagesAv.php +++ b/languages/messages/MessagesAv.php @@ -72,7 +72,7 @@ $specialPageAliases = array( 'Newpages' => array( 'ЦІиял_гьумерал' ), 'PasswordReset' => array( 'Сброс_пароля' ), 'PermanentLink' => array( 'Даимаб_ссылка' ), - 'Popularpages' => array( 'Машгьурал_гьумерал' ), + 'Preferences' => array( 'Рекъезабиял' ), 'Prefixindex' => array( 'ЦІаразул_бетІералде_бихьизаби' ), 'Protectedpages' => array( 'ЦІунарал_гьумерал' ), diff --git a/languages/messages/MessagesAvk.php b/languages/messages/MessagesAvk.php index 076d402c..61b5e4e1 100644 --- a/languages/messages/MessagesAvk.php +++ b/languages/messages/MessagesAvk.php @@ -62,7 +62,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'JinafaPrilara' ), 'Newimages' => array( 'WarzafEwaveem' ), 'Newpages' => array( 'WarzafBueem' ), - 'Popularpages' => array( 'LorupenBueem' ), + 'Preferences' => array( 'Lodamaceem' ), 'Protectedpages' => array( 'NendanBueem' ), 'Protectedtitles' => array( 'NendanVergumvelteem' ), diff --git a/languages/messages/MessagesBa.php b/languages/messages/MessagesBa.php index aaf6c2b7..580a15b3 100644 --- a/languages/messages/MessagesBa.php +++ b/languages/messages/MessagesBa.php @@ -91,7 +91,7 @@ $specialPageAliases = array( 'Newpages' => array( 'Яңы_биттәр' ), 'PasswordReset' => array( 'Паролде_яңыртыу' ), 'PermanentLink' => array( 'Даими_һылтанма' ), - 'Popularpages' => array( 'Популяр_биттәр' ), + 'Preferences' => array( 'Көйләүҙәр' ), 'Protectedpages' => array( 'Һаҡланған_биттәр' ), 'Protectedtitles' => array( 'Һаҡланған_исемдәр' ), diff --git a/languages/messages/MessagesBcc.php b/languages/messages/MessagesBcc.php index f5ade224..ce983bcd 100644 --- a/languages/messages/MessagesBcc.php +++ b/languages/messages/MessagesBcc.php @@ -97,7 +97,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'منی گپ' ), 'Newimages' => array( 'نوکین عکسان' ), 'Newpages' => array( 'نوکین صفحات' ), - 'Popularpages' => array( 'مردمی صفحات' ), + 'Preferences' => array( 'ترجیحات' ), 'Prefixindex' => array( 'ایندکس پیشوند' ), 'Protectedpages' => array( 'صفحات محافظتی' ), diff --git a/languages/messages/MessagesBe_tarask.php b/languages/messages/MessagesBe_tarask.php index 5a2a7a07..adeeee41 100644 --- a/languages/messages/MessagesBe_tarask.php +++ b/languages/messages/MessagesBe_tarask.php @@ -72,7 +72,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Мае_размовы' ), 'Newimages' => array( 'Новыя_файлы' ), 'Newpages' => array( 'Новыя_старонкі' ), - 'Popularpages' => array( 'Папулярныя_старонкі' ), + 'Protectedpages' => array( 'Абароненыя_старонкі' ), 'Protectedtitles' => array( 'Забароненыя_старонкі' ), 'Randompage' => array( 'Выпадковая_старонка' ), diff --git a/languages/messages/MessagesBg.php b/languages/messages/MessagesBg.php index afe608d8..a0e83da2 100644 --- a/languages/messages/MessagesBg.php +++ b/languages/messages/MessagesBg.php @@ -85,7 +85,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Моята_беседа' ), 'Newimages' => array( 'Нови_файлове' ), 'Newpages' => array( 'Нови_страници' ), - 'Popularpages' => array( 'Най-посещавани_страници' ), + 'Preferences' => array( 'Настройки' ), 'Prefixindex' => array( 'Всички_страници_с_представка', 'Представка' ), 'Protectedpages' => array( 'Защитени_страници' ), diff --git a/languages/messages/MessagesBjn.php b/languages/messages/MessagesBjn.php index 07246a4a..3f164c88 100644 --- a/languages/messages/MessagesBjn.php +++ b/languages/messages/MessagesBjn.php @@ -99,7 +99,7 @@ $specialPageAliases = array( 'Newimages' => array( 'Barakas_hanyar' ), 'Newpages' => array( 'Tungkaran_hanyar' ), 'PermanentLink' => array( 'Tautan_tatap' ), - 'Popularpages' => array( 'Tungkaran_popular' ), + 'Preferences' => array( 'Kakatujuan' ), 'Protectedpages' => array( 'Tungkaran_nang_dilindungi' ), 'Protectedtitles' => array( 'Judul_nang_dilindungi' ), diff --git a/languages/messages/MessagesBr.php b/languages/messages/MessagesBr.php index 66cef9ed..ac35cc3b 100644 --- a/languages/messages/MessagesBr.php +++ b/languages/messages/MessagesBr.php @@ -71,7 +71,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'MaC\'haozeadennoù' ), 'Newimages' => array( 'RestroùNevez', 'SkeudennoùNevez' ), 'Newpages' => array( 'PajennoùNevez' ), - 'Popularpages' => array( 'PajennoùPoblek' ), + 'Preferences' => array( 'Penndibaboù' ), 'Protectedpages' => array( 'PajennoùGwarezet' ), 'Protectedtitles' => array( 'TitloùGwarezet' ), diff --git a/languages/messages/MessagesBs.php b/languages/messages/MessagesBs.php index 6fda8084..2a75d383 100644 --- a/languages/messages/MessagesBs.php +++ b/languages/messages/MessagesBs.php @@ -90,7 +90,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'MojRazgovor' ), 'Newimages' => array( 'Nove_datoteke', 'Nove_slike' ), 'Newpages' => array( 'NoveStranice' ), - 'Popularpages' => array( 'PopularneStranice' ), + 'Preferences' => array( 'Postavke' ), 'Prefixindex' => array( 'IndeksPrefiksa' ), 'Protectedpages' => array( 'ZasticeneStranice' ), diff --git a/languages/messages/MessagesBxr.php b/languages/messages/MessagesBxr.php index f9a58ca4..28b07530 100644 --- a/languages/messages/MessagesBxr.php +++ b/languages/messages/MessagesBxr.php @@ -60,7 +60,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Минии_хэлэлсэл' ), 'Myuploads' => array( 'Минии_ашаалһан_зүйл' ), 'Newpages' => array( 'Шэнэ_хуудаһан' ), - 'Popularpages' => array( 'Оло_уншагдаһан_хуудаһан' ), + 'Protectedpages' => array( 'Хамгаалалтатай_хуудаһан' ), 'Protectedtitles' => array( 'Хамгаалалтатай_гаршаг' ), 'Recentchanges' => array( 'Сайтдахи_хубилалтанууд' ), diff --git a/languages/messages/MessagesCa.php b/languages/messages/MessagesCa.php index 29c9a162..3f58d582 100644 --- a/languages/messages/MessagesCa.php +++ b/languages/messages/MessagesCa.php @@ -82,7 +82,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Discussió_personal' ), 'Newimages' => array( 'Imatges_noves', 'Fitxers_nous' ), 'Newpages' => array( 'Pàgines_noves' ), - 'Popularpages' => array( 'Pàgines_populars' ), + 'Preferences' => array( 'Preferències' ), 'Prefixindex' => array( 'Cerca_per_prefix' ), 'Protectedpages' => array( 'Pàgines_protegides' ), diff --git a/languages/messages/MessagesCdo.php b/languages/messages/MessagesCdo.php index 1bc43858..bd0e2e71 100644 --- a/languages/messages/MessagesCdo.php +++ b/languages/messages/MessagesCdo.php @@ -88,7 +88,7 @@ $specialPageAliases = array( 'Newpages' => array( '新其頁面' ), 'PasswordReset' => array( '密碼重置' ), 'PermanentLink' => array( '永久鏈接' ), - 'Popularpages' => array( '受歡迎其頁面' ), + 'Preferences' => array( '喜好' ), 'Prefixindex' => array( '前綴索引' ), 'Protectedpages' => array( '受保護其頁面' ), diff --git a/languages/messages/MessagesCe.php b/languages/messages/MessagesCe.php index 7ee29c12..a626981e 100644 --- a/languages/messages/MessagesCe.php +++ b/languages/messages/MessagesCe.php @@ -126,7 +126,7 @@ $specialPageAliases = array( 'Newpages' => array( 'Керла_агӀонаш' ), 'PasswordReset' => array( 'Пароль_кхоссар' ), 'PermanentLink' => array( 'Гуттарлера_хьажорг' ), - 'Popularpages' => array( 'ГӀараяьлла_агӀонаш' ), + 'Preferences' => array( 'ГӀирсаш' ), 'Prefixindex' => array( 'Хьалха_агӀонийн_цӀераш_хӀотто_еза' ), 'Protectedpages' => array( 'ГӀаролла_дина_агӀонаш' ), diff --git a/languages/messages/MessagesCkb.php b/languages/messages/MessagesCkb.php index 027161fb..9cf2a00d 100644 --- a/languages/messages/MessagesCkb.php +++ b/languages/messages/MessagesCkb.php @@ -81,7 +81,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'لێدوانەکەم' ), 'Newimages' => array( 'پەڕگە_نوێکان' ), 'Newpages' => array( 'پەڕە_نوێکان' ), - 'Popularpages' => array( 'پەڕە_ناودارەکان' ), + 'Preferences' => array( 'ھەڵبژاردەکان' ), 'Protectedpages' => array( 'پەڕە_پارێزراوەکان' ), 'Protectedtitles' => array( 'بابەتە_پارێزراوەکان' ), diff --git a/languages/messages/MessagesCs.php b/languages/messages/MessagesCs.php index b796acad..10f7160d 100644 --- a/languages/messages/MessagesCs.php +++ b/languages/messages/MessagesCs.php @@ -98,7 +98,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Moje_diskuse' ), 'Newimages' => array( 'Nové_obrázky', 'Galerie_nových_obrázků', 'Nove_obrazky' ), 'Newpages' => array( 'Nové_stránky', 'Nove_stranky', 'Nejnovější_stránky', 'Nejnovejsi_stranky' ), - 'Popularpages' => array( 'Nejnavštěvovanější_stránky', 'Nejnavstevovanejsi_stranky' ), + 'Preferences' => array( 'Nastavení', 'Nastaveni' ), 'Protectedpages' => array( 'Zamčené_stránky', 'Zamcene_stranky' ), 'Protectedtitles' => array( 'Zamčené_názvy', 'Zamcene_nazvy', 'Stránky_které_nelze_vytvořit' ), diff --git a/languages/messages/MessagesDa.php b/languages/messages/MessagesDa.php index 075369ed..92cd58cd 100644 --- a/languages/messages/MessagesDa.php +++ b/languages/messages/MessagesDa.php @@ -87,7 +87,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Min_diskussionsside' ), 'Newimages' => array( 'Nye_filer' ), 'Newpages' => array( 'Nye_sider' ), - 'Popularpages' => array( 'Populære_sider' ), + 'Preferences' => array( 'Indstillinger' ), 'Prefixindex' => array( 'Præfiksindeks' ), 'Protectedpages' => array( 'Beskyttede_sider' ), diff --git a/languages/messages/MessagesDe.php b/languages/messages/MessagesDe.php index c9994e26..320a0068 100644 --- a/languages/messages/MessagesDe.php +++ b/languages/messages/MessagesDe.php @@ -105,7 +105,7 @@ $specialPageAliases = array( 'PageLanguage' => array( 'Seitensprache' ), 'PasswordReset' => array( 'Passwort_neu_vergeben' ), 'PermanentLink' => array( 'Permanenter_Link', 'Permalink' ), - 'Popularpages' => array( 'Beliebteste_Seiten' ), + 'Preferences' => array( 'Einstellungen' ), 'Prefixindex' => array( 'Präfixindex' ), 'Protectedpages' => array( 'Geschützte_Seiten' ), diff --git a/languages/messages/MessagesDiq.php b/languages/messages/MessagesDiq.php index 445aba04..e3dcdce4 100644 --- a/languages/messages/MessagesDiq.php +++ b/languages/messages/MessagesDiq.php @@ -118,7 +118,7 @@ $specialPageAliases = array( 'PageLanguage' => array( 'Zıwanê_Pele' ), 'PasswordReset' => array( 'ParolaPeysereştış' ), 'PermanentLink' => array( 'GıreyoDaimi' ), - 'Popularpages' => array( 'PelêPopuleri' ), + 'Preferences' => array( 'Tercihi' ), 'Prefixindex' => array( 'VerbendZerrek' ), 'Protectedpages' => array( 'PelêKeŞevekiyayiyé' ), diff --git a/languages/messages/MessagesDsb.php b/languages/messages/MessagesDsb.php index d6f268fb..3c6423e8 100644 --- a/languages/messages/MessagesDsb.php +++ b/languages/messages/MessagesDsb.php @@ -89,7 +89,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Mója_diskusija' ), 'Newimages' => array( 'Nowe_dataje' ), 'Newpages' => array( 'Nowe_boki' ), - 'Popularpages' => array( 'Woblubowane_boki' ), + 'Preferences' => array( 'Nastajenja' ), 'Prefixindex' => array( 'Indeks_prefiksow' ), 'Protectedpages' => array( 'Šćitane_boki' ), diff --git a/languages/messages/MessagesEl.php b/languages/messages/MessagesEl.php index 0334344e..06f8fd56 100644 --- a/languages/messages/MessagesEl.php +++ b/languages/messages/MessagesEl.php @@ -117,7 +117,7 @@ $specialPageAliases = array( 'Myuploads' => array( 'ΤαΑρχείαΜου', 'ΤαΑνεβάσματάΜου', 'ΟιΕπιφορτώσειςΜου' ), 'Newimages' => array( 'ΝέαΑρχεία', 'ΝέεςΕικόνες' ), 'Newpages' => array( 'ΝέεςΣελίδες' ), - 'Popularpages' => array( 'ΔημοφιλείςΣελίδες' ), + 'Preferences' => array( 'Προτιμήσεις' ), 'Prefixindex' => array( 'ΕυρετήριοΠροθεμάτων' ), 'Protectedpages' => array( 'ΠροστατευμένεςΣελίδες' ), diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index 23b702cb..8abb491b 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -451,7 +451,6 @@ $specialPageAliases = array( 'PageLanguage' => array( 'PageLanguage' ), 'PasswordReset' => array( 'PasswordReset' ), 'PermanentLink' => array( 'PermanentLink', 'PermaLink' ), - 'Popularpages' => array( 'PopularPages' ), 'Preferences' => array( 'Preferences' ), 'Prefixindex' => array( 'PrefixIndex' ), 'Protectedpages' => array( 'ProtectedPages' ), diff --git a/languages/messages/MessagesEo.php b/languages/messages/MessagesEo.php index e31710b9..851245e0 100644 --- a/languages/messages/MessagesEo.php +++ b/languages/messages/MessagesEo.php @@ -109,7 +109,7 @@ $specialPageAliases = array( 'Newpages' => array( 'Novaj_paĝoj' ), 'PasswordReset' => array( 'Ŝanĝo_de_pasvorto' ), 'PermanentLink' => array( 'Daŭra_ligilo' ), - 'Popularpages' => array( 'Popularaj_paĝoj' ), + 'Preferences' => array( 'Preferoj' ), 'Prefixindex' => array( 'Indekso_de_prefiksoj' ), 'Protectedpages' => array( 'Protektitaj_paĝoj' ), diff --git a/languages/messages/MessagesEs.php b/languages/messages/MessagesEs.php index 52e363c4..ff42a2e3 100644 --- a/languages/messages/MessagesEs.php +++ b/languages/messages/MessagesEs.php @@ -99,7 +99,7 @@ $specialPageAliases = array( 'Newpages' => array( 'PáginasNuevas', 'Páginas_nuevas' ), 'PasswordReset' => array( 'RestablecerContraseña' ), 'PermanentLink' => array( 'EnlacePermanente' ), - 'Popularpages' => array( 'PáginasMásVisitadas', 'PáginasPopulares', 'Páginas_más_visitadas' ), + 'Preferences' => array( 'Preferencias' ), 'Prefixindex' => array( 'PáginasPorPrefijo', 'Páginas_por_prefijo' ), 'Protectedpages' => array( 'PáginasProtegidas', 'Páginas_protegidas' ), diff --git a/languages/messages/MessagesEt.php b/languages/messages/MessagesEt.php index 1aaabd6e..7006db01 100644 --- a/languages/messages/MessagesEt.php +++ b/languages/messages/MessagesEt.php @@ -94,7 +94,7 @@ $specialPageAliases = array( 'PagesWithProp' => array( 'Atribuudiga_leheküljed' ), 'PasswordReset' => array( 'Parooli_lähtestamine' ), 'PermanentLink' => array( 'Püsilink' ), - 'Popularpages' => array( 'Loetumad_leheküljed' ), + 'Preferences' => array( 'Eelistused' ), 'Prefixindex' => array( 'Kõik_pealkirjad_eesliitega' ), 'Protectedpages' => array( 'Kaitstud_leheküljed' ), diff --git a/languages/messages/MessagesFa.php b/languages/messages/MessagesFa.php index dd1cc553..a7fd8677 100644 --- a/languages/messages/MessagesFa.php +++ b/languages/messages/MessagesFa.php @@ -105,7 +105,7 @@ $specialPageAliases = array( 'PageLanguage' => array( 'زبان_صفحه' ), 'PasswordReset' => array( 'بازنشاندن_گذرواژه' ), 'PermanentLink' => array( 'پیوند_دائمی' ), - 'Popularpages' => array( 'صفحههای_محبوب' ), + 'Preferences' => array( 'ترجیحات' ), 'Prefixindex' => array( 'نمایه_پیشوندی' ), 'Protectedpages' => array( 'صفحههای_محافظتشده' ), diff --git a/languages/messages/MessagesFi.php b/languages/messages/MessagesFi.php index 12199119..a663d414 100644 --- a/languages/messages/MessagesFi.php +++ b/languages/messages/MessagesFi.php @@ -98,7 +98,7 @@ $specialPageAliases = array( 'PageLanguage' => array( 'Sivun_kieli' ), 'PasswordReset' => array( 'Unohtuneen_salasanan_vaihto' ), 'PermanentLink' => array( 'Ikilinkki' ), - 'Popularpages' => array( 'Suositut_sivut' ), + 'Preferences' => array( 'Asetukset' ), 'Prefixindex' => array( 'Etuliiteluettelo' ), 'Protectedpages' => array( 'Suojatut_sivut' ), diff --git a/languages/messages/MessagesFr.php b/languages/messages/MessagesFr.php index b9e8b544..034e09c5 100644 --- a/languages/messages/MessagesFr.php +++ b/languages/messages/MessagesFr.php @@ -100,7 +100,7 @@ $specialPageAliases = array( 'PagesWithProp' => array( 'Pages_avec_la_propriété' ), 'PasswordReset' => array( 'Réinitialisation_du_mot_de_passe', 'RéinitialisationDuMotDePasse' ), 'PermanentLink' => array( 'LienPermanent', 'Lien_permanent' ), - 'Popularpages' => array( 'Pages_les_plus_visitées', 'Pages_les_plus_visitees', 'Pageslesplusvisitées', 'Pageslesplusvisitees' ), + 'Preferences' => array( 'Préférences' ), 'Prefixindex' => array( 'Index', 'Préfixes', 'Prefixes' ), 'Protectedpages' => array( 'Pages_protégées', 'PagesProtégées', 'Pages_protegees', 'PagesProtegees' ), diff --git a/languages/messages/MessagesFrp.php b/languages/messages/MessagesFrp.php index 51a0e132..6a8bdfcf 100644 --- a/languages/messages/MessagesFrp.php +++ b/languages/messages/MessagesFrp.php @@ -102,7 +102,7 @@ $specialPageAliases = array( 'Newimages' => array( 'Novéls_fichiérs', 'NovélsFichiérs', 'Émâges_novèles', 'ÉmâgesNovèles' ), 'Newpages' => array( 'Pâges_novèles', 'PâgesNovèles' ), 'PermanentLink' => array( 'Lim_fixo', 'LimFixo' ), - 'Popularpages' => array( 'Pâges_les_ples_consultâs', 'PâgesLesPlesConsultâs' ), + 'Preferences' => array( 'Prèferences' ), 'Prefixindex' => array( 'Endèxe_des_prèfixos', 'EndèxeDesPrèfixos' ), 'Protectedpages' => array( 'Pâges_protègiês', 'PâgesProtègiês' ), diff --git a/languages/messages/MessagesFur.php b/languages/messages/MessagesFur.php index 52fdee8a..e0a1e70c 100644 --- a/languages/messages/MessagesFur.php +++ b/languages/messages/MessagesFur.php @@ -64,7 +64,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'MêsDiscussions' ), 'Newimages' => array( 'GnovisFiguris' ), 'Newpages' => array( 'GnovisPagjinis' ), - 'Popularpages' => array( 'PagjinisPopolârs' ), + 'Preferences' => array( 'Preferencis' ), 'Prefixindex' => array( 'Prefìs' ), 'Protectedpages' => array( 'PagjinisProtezudis' ), diff --git a/languages/messages/MessagesFy.php b/languages/messages/MessagesFy.php index e02baf0c..0d76208c 100644 --- a/languages/messages/MessagesFy.php +++ b/languages/messages/MessagesFy.php @@ -94,7 +94,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Myn oerlis' ), 'Newimages' => array( 'Nije ôfbylden', 'Nije ôfbyldings', 'Nije ôfbyldingen', 'List mei nije ôfbylden', 'Nije Ofbylden' ), 'Newpages' => array( 'Nije siden' ), - 'Popularpages' => array( 'Populêre siden', 'Grage siden' ), + 'Preferences' => array( 'Ynstellings', 'Ynsteld' ), 'Prefixindex' => array( 'Alle siden neffens foarheaksel' ), 'Protectedpages' => array( 'Befeilige siden', 'Skoattele siden' ), diff --git a/languages/messages/MessagesGag.php b/languages/messages/MessagesGag.php index 390e6589..4ac7b037 100644 --- a/languages/messages/MessagesGag.php +++ b/languages/messages/MessagesGag.php @@ -66,7 +66,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'SözleşmäkSayfam', 'SözleşmäkYapraım' ), 'Newimages' => array( 'EniDosyeler', 'EniPätretler' ), 'Newpages' => array( 'EniYazılar', 'EniSayfalar', 'EniYapraklar' ), - 'Popularpages' => array( 'EnAnılmışSayfalar', 'EnAnılmışYazılar' ), + 'Preferences' => array( 'Seçimner' ), 'Prefixindex' => array( 'Prefiksİndeksi' ), 'Randompage' => array( 'Razgele', 'RazgeleYazı', 'RazgeleSayfa', 'RazgeleYaprak' ), diff --git a/languages/messages/MessagesGl.php b/languages/messages/MessagesGl.php index 8ab5bccc..8bba00dc 100644 --- a/languages/messages/MessagesGl.php +++ b/languages/messages/MessagesGl.php @@ -113,7 +113,7 @@ $specialPageAliases = array( 'PagesWithProp' => array( 'Páxinas_con_propiedades' ), 'PasswordReset' => array( 'Restablecer_o_contrasinal', 'Restablecer_contrasinal' ), 'PermanentLink' => array( 'Ligazón_permanente' ), - 'Popularpages' => array( 'Páxinas_populares' ), + 'Preferences' => array( 'Preferencias' ), 'Prefixindex' => array( 'Índice_de_prefixos' ), 'Protectedpages' => array( 'Páxinas_protexidas' ), diff --git a/languages/messages/MessagesGsw.php b/languages/messages/MessagesGsw.php index d1654958..7dc4d1aa 100644 --- a/languages/messages/MessagesGsw.php +++ b/languages/messages/MessagesGsw.php @@ -68,7 +68,7 @@ $specialPageAliases = array( 'Newpages' => array( 'Neji_Syte' ), 'PasswordReset' => array( 'Passwort_zruggsetze' ), 'PermanentLink' => array( 'Permalink' ), - 'Popularpages' => array( 'Beliebteschti_Syte' ), + 'Preferences' => array( 'Ystellige' ), 'Prefixindex' => array( 'Vorsilbeverzeichnis' ), 'Protectedpages' => array( 'Gschitzti_Syte' ), diff --git a/languages/messages/MessagesGu.php b/languages/messages/MessagesGu.php index 3fc9f6bd..8b6f8e14 100644 --- a/languages/messages/MessagesGu.php +++ b/languages/messages/MessagesGu.php @@ -74,7 +74,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'મારીચર્ચા' ), 'Newimages' => array( 'નવીફાઇલો', 'નવાંચિત્રો' ), 'Newpages' => array( 'નવાપાનાં' ), - 'Popularpages' => array( 'લોકપ્રિયપાનાં' ), + 'Preferences' => array( 'પસંદ' ), 'Prefixindex' => array( 'ઉપસર્ગ' ), 'Protectedpages' => array( 'સંરક્ષિતપાનાં' ), diff --git a/languages/messages/MessagesHe.php b/languages/messages/MessagesHe.php index 3d7fc43d..144b4080 100644 --- a/languages/messages/MessagesHe.php +++ b/languages/messages/MessagesHe.php @@ -108,7 +108,7 @@ $specialPageAliases = array( 'PageLanguage' => array( 'שפת_הדף' ), 'PasswordReset' => array( 'איפוס_סיסמה' ), 'PermanentLink' => array( 'קישור_קבוע' ), - 'Popularpages' => array( 'הדפים_הנצפים_ביותר', 'דפים_פופולריים' ), + 'Preferences' => array( 'העדפות', 'ההעדפות_שלי' ), 'Prefixindex' => array( 'דפים_המתחילים_ב' ), 'Protectedpages' => array( 'דפים_מוגנים' ), diff --git a/languages/messages/MessagesHr.php b/languages/messages/MessagesHr.php index 65077c1e..ffde28cf 100644 --- a/languages/messages/MessagesHr.php +++ b/languages/messages/MessagesHr.php @@ -88,7 +88,7 @@ $specialPageAliases = array( 'Myuploads' => array( 'Moje_datoteke' ), 'Newimages' => array( 'Nove_datoteke', 'Nove_slike' ), 'Newpages' => array( 'Nove_stranice' ), - 'Popularpages' => array( 'Popularne_stranice' ), + 'Preferences' => array( 'Postavke' ), 'Prefixindex' => array( 'Prefiks_indeks', 'Stranice_po_prefiksu' ), 'Protectedpages' => array( 'Zaštićene_stranice' ), diff --git a/languages/messages/MessagesHsb.php b/languages/messages/MessagesHsb.php index fb8fdb3b..f6314d54 100644 --- a/languages/messages/MessagesHsb.php +++ b/languages/messages/MessagesHsb.php @@ -106,7 +106,7 @@ $specialPageAliases = array( 'Newimages' => array( 'Nowe_dataje' ), 'Newpages' => array( 'Nowe_strony' ), 'PermanentLink' => array( 'Trajny_wotkaz' ), - 'Popularpages' => array( 'Najwoblubowaniše_strony' ), + 'Preferences' => array( 'Nastajenja' ), 'Prefixindex' => array( 'Prefiksindeks' ), 'Protectedpages' => array( 'Škitane_strony' ), diff --git a/languages/messages/MessagesHt.php b/languages/messages/MessagesHt.php index 18e4a2df..4b7d4a1c 100644 --- a/languages/messages/MessagesHt.php +++ b/languages/messages/MessagesHt.php @@ -94,7 +94,7 @@ $specialPageAliases = array( 'Newpages' => array( 'PajNouvo' ), 'PasswordReset' => array( 'ResètMopas2' ), 'PermanentLink' => array( 'LyenPouToutTan' ), - 'Popularpages' => array( 'PajPopilè' ), + 'Preferences' => array( 'Preferans' ), 'Prefixindex' => array( 'EndèksPrefiks' ), 'Protectedpages' => array( 'PajPwoteje' ), diff --git a/languages/messages/MessagesHu.php b/languages/messages/MessagesHu.php index 0019a4b8..a076874e 100644 --- a/languages/messages/MessagesHu.php +++ b/languages/messages/MessagesHu.php @@ -98,7 +98,7 @@ $specialPageAliases = array( 'Newimages' => array( 'Új_fájlok', 'Új_képek', 'Új_képek_galériája' ), 'Newpages' => array( 'Új_lapok' ), 'PasswordReset' => array( 'Jelszó_helyreállítása' ), - 'Popularpages' => array( 'Népszerű_lapok', 'Népszerű_oldalak' ), + 'Preferences' => array( 'Beállításaim' ), 'Prefixindex' => array( 'Keresés_előtag_szerint' ), 'Protectedpages' => array( 'Védett_lapok' ), diff --git a/languages/messages/MessagesHy.php b/languages/messages/MessagesHy.php index ea23ef05..7ce48dfe 100644 --- a/languages/messages/MessagesHy.php +++ b/languages/messages/MessagesHy.php @@ -223,7 +223,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Իմքննարկումները' ), 'Newimages' => array( 'Նորպատկերներ' ), 'Newpages' => array( 'Նորէջերը' ), - 'Popularpages' => array( 'Հանրաճանաչէջերը' ), + 'Preferences' => array( 'Նախընտրությունները' ), 'Prefixindex' => array( 'Որոնումնախածանցով' ), 'Randompage' => array( 'Պատահականէջ' ), diff --git a/languages/messages/MessagesIa.php b/languages/messages/MessagesIa.php index 0d4fd18c..d0dd5476 100644 --- a/languages/messages/MessagesIa.php +++ b/languages/messages/MessagesIa.php @@ -93,7 +93,7 @@ $specialPageAliases = array( 'Newpages' => array( 'Paginas_nove', 'Nove_paginas' ), 'PasswordReset' => array( 'Reinitialisar_contrasigno' ), 'PermanentLink' => array( 'Ligamine_permanente' ), - 'Popularpages' => array( 'Paginas_popular' ), + 'Preferences' => array( 'Preferentias' ), 'Prefixindex' => array( 'Indice_de_prefixos' ), 'Protectedpages' => array( 'Paginas_protegite' ), diff --git a/languages/messages/MessagesId.php b/languages/messages/MessagesId.php index 35109313..80472764 100644 --- a/languages/messages/MessagesId.php +++ b/languages/messages/MessagesId.php @@ -252,7 +252,7 @@ $specialPageAliases = array( 'Newpages' => array( 'Halaman_baru', 'HalamanBaru' ), 'PasswordReset' => array( 'Reset_sandi', 'ResetSandi' ), 'PermanentLink' => array( 'Pranala_permanen' ), - 'Popularpages' => array( 'Halaman_populer', 'HalamanPopuler' ), + 'Preferences' => array( 'Preferensi' ), 'Prefixindex' => array( 'Indeks_awalan', 'IndeksAwalan' ), 'Protectedpages' => array( 'Halaman_yang_dilindungi', 'HalamanDilindungi' ), diff --git a/languages/messages/MessagesIe.php b/languages/messages/MessagesIe.php index 748f82b8..1a42d266 100644 --- a/languages/messages/MessagesIe.php +++ b/languages/messages/MessagesIe.php @@ -81,7 +81,7 @@ $specialPageAliases = array( 'Newpages' => array( 'Nov_págines' ), 'PasswordReset' => array( 'Recomensar_parol-clave' ), 'PermanentLink' => array( 'Catenun_permanen' ), - 'Popularpages' => array( 'Págines_populari' ), + 'Preferences' => array( 'Preferenties' ), 'Prefixindex' => array( 'Index_de_prefixe' ), 'Protectedpages' => array( 'Págines_gardat' ), diff --git a/languages/messages/MessagesIs.php b/languages/messages/MessagesIs.php index effce71c..c3a8f95a 100644 --- a/languages/messages/MessagesIs.php +++ b/languages/messages/MessagesIs.php @@ -169,7 +169,7 @@ $specialPageAliases = array( 'Newimages' => array( 'Nýjar_myndir' ), 'Newpages' => array( 'Nýjustu_greinar' ), 'PasswordReset' => array( 'Endursetja_lykilorð' ), - 'Popularpages' => array( 'Vinsælar_síður' ), + 'Preferences' => array( 'Stillingar' ), 'Prefixindex' => array( 'Forskeyti' ), 'Protectedpages' => array( 'Verndaðar_síður' ), diff --git a/languages/messages/MessagesIt.php b/languages/messages/MessagesIt.php index 27bbe784..5e98dea5 100644 --- a/languages/messages/MessagesIt.php +++ b/languages/messages/MessagesIt.php @@ -111,7 +111,7 @@ $specialPageAliases = array( 'PagesWithProp' => array( 'PagineConProprietà' ), 'PasswordReset' => array( 'ReimpostaPassword' ), 'PermanentLink' => array( 'LinkPermanente' ), - 'Popularpages' => array( 'PaginePiùVisitate' ), + 'Preferences' => array( 'Preferenze' ), 'Prefixindex' => array( 'Prefissi' ), 'Protectedpages' => array( 'PagineProtette' ), diff --git a/languages/messages/MessagesJa.php b/languages/messages/MessagesJa.php index caca23dd..f4104563 100644 --- a/languages/messages/MessagesJa.php +++ b/languages/messages/MessagesJa.php @@ -125,7 +125,7 @@ $specialPageAliases = array( 'PageLanguage' => array( 'ページ言語' ), 'PasswordReset' => array( 'パスワード再設定', 'パスワードの再設定', 'パスワードのリセット', 'パスワードリセット' ), 'PermanentLink' => array( '固定リンク', 'パーマリンク' ), - 'Popularpages' => array( '人気ページ' ), + 'Preferences' => array( '個人設定', 'オプション' ), 'Prefixindex' => array( '前方一致ページ一覧', '始点指定ページ一覧' ), 'Protectedpages' => array( '保護されているページ' ), diff --git a/languages/messages/MessagesKa.php b/languages/messages/MessagesKa.php index 598f1011..bcca2d2d 100644 --- a/languages/messages/MessagesKa.php +++ b/languages/messages/MessagesKa.php @@ -79,7 +79,7 @@ $specialPageAliases = array( 'Myuploads' => array( 'ჩემი_ატვირთვები' ), 'Newimages' => array( 'ახალი_ფაილები' ), 'Newpages' => array( 'ახალი_გვერდები' ), - 'Popularpages' => array( 'პოპგვერდები' ), + 'Preferences' => array( 'კონფიგურაცია' ), 'Protectedpages' => array( 'დაცული_გვერდები' ), 'Protectedtitles' => array( 'დაცული_სათაურები' ), diff --git a/languages/messages/MessagesKaa.php b/languages/messages/MessagesKaa.php index 44b7224e..3d57771c 100644 --- a/languages/messages/MessagesKaa.php +++ b/languages/messages/MessagesKaa.php @@ -70,7 +70,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Menin\' sa\'wbetim' ), 'Newimages' => array( 'Taza su\'wretler' ), 'Newpages' => array( 'Taza betler' ), - 'Popularpages' => array( 'Ko\'p ko\'rilgen betler' ), + 'Preferences' => array( 'Sazlawlar' ), 'Protectedpages' => array( 'Qorg\'alg\'an betler' ), 'Randompage' => array( 'Qa\'legen', 'Qa\'legen bet' ), diff --git a/languages/messages/MessagesKk_arab.php b/languages/messages/MessagesKk_arab.php index 8749ccbe..990bd861 100644 --- a/languages/messages/MessagesKk_arab.php +++ b/languages/messages/MessagesKk_arab.php @@ -348,7 +348,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'تالقىلاۋىم' ), 'Newimages' => array( 'جاڭا_سۋرەتتەر' ), 'Newpages' => array( 'جاڭا_بەتتەر' ), - 'Popularpages' => array( 'ەڭ_كوپ_قارالعان_بەتتەر', 'ايگىلى_بەتتەر' ), + 'Preferences' => array( 'باپتالىمدار', 'باپتاۋ' ), 'Prefixindex' => array( 'ٴباستاۋىش_ٴتىزىمى' ), 'Protectedpages' => array( 'قورعالعان_بەتتەر' ), diff --git a/languages/messages/MessagesKk_cyrl.php b/languages/messages/MessagesKk_cyrl.php index 680c2eab..2f4eb88f 100644 --- a/languages/messages/MessagesKk_cyrl.php +++ b/languages/messages/MessagesKk_cyrl.php @@ -322,7 +322,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Талқылауым' ), 'Newimages' => array( 'Жаңа_суреттер' ), 'Newpages' => array( 'Жаңа_беттер' ), - 'Popularpages' => array( 'Ең_көп_қаралған_беттер', 'Әйгілі_беттер' ), + 'Preferences' => array( 'Бапталымдар', 'Баптау' ), 'Prefixindex' => array( 'Бастауыш_тізімі' ), 'Protectedpages' => array( 'Қорғалған_беттер' ), diff --git a/languages/messages/MessagesKk_latn.php b/languages/messages/MessagesKk_latn.php index b7f8c6fc..1bdc40ad 100644 --- a/languages/messages/MessagesKk_latn.php +++ b/languages/messages/MessagesKk_latn.php @@ -316,7 +316,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Talqılawım' ), 'Newimages' => array( 'Jaña_swretter' ), 'Newpages' => array( 'Jaña_better' ), - 'Popularpages' => array( 'Eñ_köp_qaralğan_better', 'Äýgili_better' ), + 'Preferences' => array( 'Baptalımdar', 'Baptaw' ), 'Prefixindex' => array( 'Bastawış_tizimi' ), 'Protectedpages' => array( 'Qorğalğan_better' ), diff --git a/languages/messages/MessagesKm.php b/languages/messages/MessagesKm.php index 289e5c2f..cf7c4245 100644 --- a/languages/messages/MessagesKm.php +++ b/languages/messages/MessagesKm.php @@ -147,7 +147,7 @@ $specialPageAliases = array( 'Newpages' => array( 'ទំព័រថ្មីៗ' ), 'PasswordReset' => array( 'កំណត់ពាក្យសំងាត់ឡើងវិញ' ), 'PermanentLink' => array( 'តំណភ្ជាប់អចិន្ត្រែយ៍' ), - 'Popularpages' => array( 'ទំព័រដែលមានប្រជាប្រិយ' ), + 'Preferences' => array( 'ចំណង់ចំណូលចិត្ត' ), 'Prefixindex' => array( 'លិបិក្រមបុព្វបទ' ), 'Protectedpages' => array( 'ទំព័របានការពារ' ), diff --git a/languages/messages/MessagesKo.php b/languages/messages/MessagesKo.php index d34e249a..3eb43d00 100644 --- a/languages/messages/MessagesKo.php +++ b/languages/messages/MessagesKo.php @@ -139,7 +139,7 @@ $specialPageAliases = array( 'PageLanguage' => array( '문서언어' ), 'PasswordReset' => array( '비밀번호재설정', '비밀번호초기화' ), 'PermanentLink' => array( '고유링크', '영구링크' ), - 'Popularpages' => array( '인기있는문서' ), + 'Preferences' => array( '환경설정' ), 'Prefixindex' => array( '접두어찾기' ), 'Protectedpages' => array( '보호된문서' ), diff --git a/languages/messages/MessagesKrc.php b/languages/messages/MessagesKrc.php index 6b621607..f5c7ff4e 100644 --- a/languages/messages/MessagesKrc.php +++ b/languages/messages/MessagesKrc.php @@ -87,7 +87,7 @@ $specialPageAliases = array( 'Newpages' => array( 'Джангы_бетле' ), 'PasswordReset' => array( 'Паролну_ийиу' ), 'PermanentLink' => array( 'Дайым_джибериу' ), - 'Popularpages' => array( 'Популяр_бетле' ), + 'Preferences' => array( 'Джарашдырыула' ), 'Protectedpages' => array( 'Джакъланнган_бетле' ), 'Protectedtitles' => array( 'Джакъланнган_атла' ), diff --git a/languages/messages/MessagesKsh.php b/languages/messages/MessagesKsh.php index b1c9d3b3..f39769cb 100644 --- a/languages/messages/MessagesKsh.php +++ b/languages/messages/MessagesKsh.php @@ -158,7 +158,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Ming_Klaafsigg', 'Klaaf' ), 'Newimages' => array( 'Neu_Dateie' ), 'Newpages' => array( 'Neu_Atikelle' ), - 'Popularpages' => array( 'Miehts_affjeroofe_Sigge' ), + 'Preferences' => array( 'Ming_Enstellunge', 'Enstellunge' ), 'Prefixindex' => array( 'Sigge_met_Aanfang' ), 'Protectedpages' => array( 'Siggeschotz' ), diff --git a/languages/messages/MessagesKw.php b/languages/messages/MessagesKw.php index b093b584..fdd18366 100644 --- a/languages/messages/MessagesKw.php +++ b/languages/messages/MessagesKw.php @@ -118,7 +118,7 @@ $specialPageAliases = array( 'Newpages' => array( 'FolennowNowyth' ), 'PasswordReset' => array( 'DassetyaGerTremena' ), 'PermanentLink' => array( 'KevrenFast' ), - 'Popularpages' => array( 'FolennowGerysDa' ), + 'Preferences' => array( 'Dewisyansow' ), 'Prefixindex' => array( 'MenegvaRagerow' ), 'Protectedpages' => array( 'FolennowDifresys' ), diff --git a/languages/messages/MessagesLa.php b/languages/messages/MessagesLa.php index 9f3d9043..b37c5b11 100644 --- a/languages/messages/MessagesLa.php +++ b/languages/messages/MessagesLa.php @@ -120,7 +120,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Disputatio_mea' ), 'Newimages' => array( 'Fasciculi_novi', 'Imagines_novae' ), 'Newpages' => array( 'Paginae_novae' ), - 'Popularpages' => array( 'Paginae_saepe_monstratae' ), + 'Preferences' => array( 'Praeferentiae' ), 'Prefixindex' => array( 'Praefixa', 'Quaerere_per_praefixa' ), 'Protectedpages' => array( 'Paginae_protectae' ), diff --git a/languages/messages/MessagesLad.php b/languages/messages/MessagesLad.php index cbeb69ee..a6cd3454 100644 --- a/languages/messages/MessagesLad.php +++ b/languages/messages/MessagesLad.php @@ -129,7 +129,7 @@ $specialPageAliases = array( 'Newpages' => array( 'HojasMuevas' ), 'PasswordReset' => array( 'Meter_á_zero_el_kóddiche' ), 'PermanentLink' => array( 'AtamientoPermanente' ), - 'Popularpages' => array( 'HojasMásVisitadas' ), + 'Preferences' => array( 'Preferencias' ), 'Prefixindex' => array( 'Fijhrist_de_prefiksos' ), 'Protectedpages' => array( 'HojasGuardadas' ), diff --git a/languages/messages/MessagesLb.php b/languages/messages/MessagesLb.php index 203788c6..9d5e9a18 100644 --- a/languages/messages/MessagesLb.php +++ b/languages/messages/MessagesLb.php @@ -116,7 +116,7 @@ $specialPageAliases = array( 'PageLanguage' => array( 'Sprooch_vun_der_Säit' ), 'PasswordReset' => array( 'Zrécksetze_vum_Passwuert' ), 'PermanentLink' => array( 'Permanente_Link' ), - 'Popularpages' => array( 'Beléifst_Säiten' ), + 'Preferences' => array( 'Astellungen' ), 'Prefixindex' => array( 'Indexsich' ), 'Protectedpages' => array( 'Protegéiert_Säiten' ), diff --git a/languages/messages/MessagesLi.php b/languages/messages/MessagesLi.php index 4efd38cc..029df318 100644 --- a/languages/messages/MessagesLi.php +++ b/languages/messages/MessagesLi.php @@ -100,7 +100,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Mien_euverlèk' ), 'Newimages' => array( 'Nuuj_plaetjes' ), 'Newpages' => array( 'Nuuj_pagina\'s' ), - 'Popularpages' => array( 'Populair_pagina\'s' ), + 'Preferences' => array( 'Veurkäöre' ), 'Prefixindex' => array( 'Alle_artikele' ), 'Protectedpages' => array( 'Beveiligde_pagina\'s' ), diff --git a/languages/messages/MessagesLij.php b/languages/messages/MessagesLij.php index 8cc1a214..398b20b7 100644 --- a/languages/messages/MessagesLij.php +++ b/languages/messages/MessagesLij.php @@ -87,7 +87,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Mæ Discûscioîn' ), 'Newimages' => array( 'Immaggini reçenti' ), 'Newpages' => array( 'Paggine ciû reçenti' ), - 'Popularpages' => array( 'Paggine ciû viscitæ' ), + 'Preferences' => array( 'Preferense' ), 'Prefixindex' => array( 'Prefisci' ), 'Protectedpages' => array( 'Paggine protezûe' ), diff --git a/languages/messages/MessagesLrc.php b/languages/messages/MessagesLrc.php index ada5dc28..45defa49 100644 --- a/languages/messages/MessagesLrc.php +++ b/languages/messages/MessagesLrc.php @@ -99,7 +99,7 @@ $specialPageAliases = array( 'PageLanguage' => array( 'بلگه_زون' ), 'PasswordReset' => array( 'د_نو_زنه_کردن_رازینه_گواردن' ), 'PermanentLink' => array( 'هوم_پیوند_دایمی' ), - 'Popularpages' => array( 'صفحههای_محبوب' ), + 'Preferences' => array( 'میزونکاریا' ), 'Prefixindex' => array( 'پیشون_سیائه' ), 'Protectedpages' => array( 'بلگه_یا_پر_و_پیم_بیه' ), diff --git a/languages/messages/MessagesLt.php b/languages/messages/MessagesLt.php index a2ce260a..3819ed43 100644 --- a/languages/messages/MessagesLt.php +++ b/languages/messages/MessagesLt.php @@ -107,7 +107,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Mano_aptarimas' ), 'Newimages' => array( 'Nauji_paveikslėliai' ), 'Newpages' => array( 'Naujausi_puslapiai' ), - 'Popularpages' => array( 'Populiarūs_puslapiai' ), + 'Preferences' => array( 'Nustatymai' ), 'Prefixindex' => array( 'Prasidedantys' ), 'Protectedpages' => array( 'Užrakinti_puslapiai' ), diff --git a/languages/messages/MessagesMdf.php b/languages/messages/MessagesMdf.php index 274b7242..a68cb1b2 100644 --- a/languages/messages/MessagesMdf.php +++ b/languages/messages/MessagesMdf.php @@ -101,7 +101,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'МоньКорхнемазе' ), 'Newimages' => array( 'ОдНяйфне' ), 'Newpages' => array( 'ОдЛопат' ), - 'Popularpages' => array( 'СидестаЛопатне' ), + 'Preferences' => array( 'Латцематне' ), 'Prefixindex' => array( 'ВалынгольксИндекс' ), 'Protectedpages' => array( 'АралафЛопат' ), diff --git a/languages/messages/MessagesMg.php b/languages/messages/MessagesMg.php index 4c962add..19c4c2d7 100644 --- a/languages/messages/MessagesMg.php +++ b/languages/messages/MessagesMg.php @@ -187,7 +187,7 @@ $specialPageAliases = array( 'PageLanguage' => array( 'Fitenim-pejy', 'Fitenimpejy' ), 'PasswordReset' => array( 'Famerenan-tenimiafina', 'Famerenantenimiafina' ), 'PermanentLink' => array( 'Rohy_maharitra', 'RohyMaharitra' ), - 'Popularpages' => array( 'Pejy_be_mpitsidika_indrindra' ), + 'Preferences' => array( 'Safidy' ), 'Prefixindex' => array( 'Index' ), 'Protectedpages' => array( 'Pejy_voaaro' ), diff --git a/languages/messages/MessagesMin.php b/languages/messages/MessagesMin.php index 451e3734..e379df2a 100644 --- a/languages/messages/MessagesMin.php +++ b/languages/messages/MessagesMin.php @@ -116,7 +116,7 @@ $specialPageAliases = array( 'PagesWithProp' => array( 'LamanJoProperti', 'Laman_jo_properti' ), 'PasswordReset' => array( 'TukaSandi', 'Tuka_baliak_sandi' ), 'PermanentLink' => array( 'PautanPamanen', 'Pautan_pamanen' ), - 'Popularpages' => array( 'LamanPopuler', 'Laman_populer' ), + 'Preferences' => array( 'Rujuakan' ), 'Prefixindex' => array( 'DaptaAwalan' ), 'Protectedpages' => array( 'LamanTalinduang', 'Laman_nan_dilinduang' ), diff --git a/languages/messages/MessagesMk.php b/languages/messages/MessagesMk.php index 9f74d16a..ad8e2454 100644 --- a/languages/messages/MessagesMk.php +++ b/languages/messages/MessagesMk.php @@ -159,7 +159,7 @@ $specialPageAliases = array( 'PageLanguage' => array( 'ЈазикНаСтраницата' ), 'PasswordReset' => array( 'ПроменаНаЛозинка' ), 'PermanentLink' => array( 'ПостојанаВрска' ), - 'Popularpages' => array( 'ПопуларниСтраници' ), + 'Preferences' => array( 'Нагодувања' ), 'Prefixindex' => array( 'ИндексНаПретставки' ), 'Protectedpages' => array( 'ЗаштитениСтраници' ), diff --git a/languages/messages/MessagesMl.php b/languages/messages/MessagesMl.php index 39f48b23..b9c395d1 100644 --- a/languages/messages/MessagesMl.php +++ b/languages/messages/MessagesMl.php @@ -148,7 +148,7 @@ $specialPageAliases = array( 'PageLanguage' => array( 'താളിന്റെഭാഷ' ), 'PasswordReset' => array( 'രഹസ്യവാക്ക്പുനക്രമീകരണം' ), 'PermanentLink' => array( 'സ്ഥിരംകണ്ണി' ), - 'Popularpages' => array( 'ജനപ്രിയതാളുകൾ' ), + 'Preferences' => array( 'ക്രമീകരണങ്ങൾ' ), 'Prefixindex' => array( 'പൂർവ്വപദസൂചിക' ), 'Protectedpages' => array( 'സംരക്ഷിത_താളുകൾ' ), diff --git a/languages/messages/MessagesMr.php b/languages/messages/MessagesMr.php index 4f9b0cd0..5347ca6a 100644 --- a/languages/messages/MessagesMr.php +++ b/languages/messages/MessagesMr.php @@ -128,7 +128,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'माझ्या_चर्चा' ), 'Newimages' => array( 'नवीन_संचिका', 'नवीन_चित्रे' ), 'Newpages' => array( 'नवीन_पाने' ), - 'Popularpages' => array( 'प्रसिद्ध_पाने' ), + 'Preferences' => array( 'पसंती' ), 'Prefixindex' => array( 'उपसर्गसुची' ), 'Protectedpages' => array( 'सुरक्षित_पाने' ), diff --git a/languages/messages/MessagesMs.php b/languages/messages/MessagesMs.php index fb972b0a..7466aed6 100644 --- a/languages/messages/MessagesMs.php +++ b/languages/messages/MessagesMs.php @@ -170,7 +170,7 @@ $specialPageAliases = array( 'PageLanguage' => array( 'Bahasa_laman' ), 'PasswordReset' => array( 'Tetap_semula_kata_kunci' ), 'PermanentLink' => array( 'Pautan_kekal' ), - 'Popularpages' => array( 'Laman_popular' ), + 'Preferences' => array( 'Keutamaan' ), 'Prefixindex' => array( 'Indeks_awalan' ), 'Protectedpages' => array( 'Laman_dilindungi' ), diff --git a/languages/messages/MessagesMt.php b/languages/messages/MessagesMt.php index 2529cc98..87a84909 100644 --- a/languages/messages/MessagesMt.php +++ b/languages/messages/MessagesMt.php @@ -100,7 +100,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'DiskussjonijietTiegħi' ), 'Newimages' => array( 'StampiĠodda', 'FajlsĠodda' ), 'Newpages' => array( 'PaġniĠodda' ), - 'Popularpages' => array( 'PaġniPopolari' ), + 'Preferences' => array( 'Preferenzi' ), 'Prefixindex' => array( 'IndiċiPrefiss' ), 'Protectedpages' => array( 'PaġniProtetti' ), diff --git a/languages/messages/MessagesMyv.php b/languages/messages/MessagesMyv.php index e5e189c5..cc0f856a 100644 --- a/languages/messages/MessagesMyv.php +++ b/languages/messages/MessagesMyv.php @@ -79,7 +79,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'МоньКортамом' ), 'Newimages' => array( 'ОдАртовкст' ), 'Newpages' => array( 'ОдЛопат' ), - 'Popularpages' => array( 'ЛисийСовийМартоЛопат' ), + 'Protectedpages' => array( 'ВанстоньЛопат' ), 'Protectedtitles' => array( 'ВанстоньКонякст' ), 'Randompage' => array( 'КодамоПонгсьЛопа' ), diff --git a/languages/messages/MessagesNb.php b/languages/messages/MessagesNb.php index 6f9cf1f9..15b282a2 100644 --- a/languages/messages/MessagesNb.php +++ b/languages/messages/MessagesNb.php @@ -160,7 +160,7 @@ $specialPageAliases = array( 'PagesWithProp' => array( 'Sider_med_egenskap' ), 'PasswordReset' => array( 'Nullstill_passord' ), 'PermanentLink' => array( 'Permanent_lenke' ), - 'Popularpages' => array( 'Populære_sider' ), + 'Preferences' => array( 'Innstillinger' ), 'Prefixindex' => array( 'Prefiksindeks' ), 'Protectedpages' => array( 'Beskyttede_sider' ), diff --git a/languages/messages/MessagesNds.php b/languages/messages/MessagesNds.php index f87d770c..cf35e7ae 100644 --- a/languages/messages/MessagesNds.php +++ b/languages/messages/MessagesNds.php @@ -179,7 +179,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Miene Diskuschoonssiet' ), 'Newimages' => array( 'Nee Datein' ), 'Newpages' => array( 'Nee Sieden' ), - 'Popularpages' => array( 'Veel besöchte Sieden' ), + 'Preferences' => array( 'Instellungen' ), 'Prefixindex' => array( 'Sieden de anfangt mit' ), 'Protectedpages' => array( 'Schuulte Sieden' ), diff --git a/languages/messages/MessagesNds_nl.php b/languages/messages/MessagesNds_nl.php index 5e82e82c..784176ac 100644 --- a/languages/messages/MessagesNds_nl.php +++ b/languages/messages/MessagesNds_nl.php @@ -278,7 +278,7 @@ $specialPageAliases = array( 'PagesWithProp' => array( 'Ziejen_mit_eigenschap' ), 'PasswordReset' => array( 'Wachtwoord_opniej_instellen' ), 'PermanentLink' => array( 'Vaste_verwiezing' ), - 'Popularpages' => array( 'Populaere_artikels' ), + 'Preferences' => array( 'Veurkeuren' ), 'Prefixindex' => array( 'Veurvoegselindex' ), 'Protectedpages' => array( 'Beveiligden_ziejen' ), diff --git a/languages/messages/MessagesNl.php b/languages/messages/MessagesNl.php index 7d7fa054..28927282 100644 --- a/languages/messages/MessagesNl.php +++ b/languages/messages/MessagesNl.php @@ -335,7 +335,7 @@ $specialPageAliases = array( 'PageLanguage' => array( 'Paginataal' ), 'PasswordReset' => array( 'WachtwoordOpnieuwInstellen' ), 'PermanentLink' => array( 'PermanenteVerwijzing' ), - 'Popularpages' => array( 'PopulairePaginas', 'PopulairePagina’s', 'PopulairePagina\'s' ), + 'Preferences' => array( 'Voorkeuren' ), 'Prefixindex' => array( 'Voorvoegselindex' ), 'Protectedpages' => array( 'BeveiligdePaginas', 'BeveiligdePagina\'s', 'BeschermdePaginas', 'BeschermdePagina’s', 'BeschermdePagina\'s' ), diff --git a/languages/messages/MessagesNn.php b/languages/messages/MessagesNn.php index 606f7205..0f1ec900 100644 --- a/languages/messages/MessagesNn.php +++ b/languages/messages/MessagesNn.php @@ -274,7 +274,7 @@ $specialPageAliases = array( 'Newimages' => array( 'Nye_filer' ), 'Newpages' => array( 'Nye_sider' ), 'PermanentLink' => array( 'Permanent_lenkje', 'Permanent_lenke' ), - 'Popularpages' => array( 'Populære_sider' ), + 'Preferences' => array( 'Innstillingar' ), 'Prefixindex' => array( 'Prefiksindeks' ), 'Protectedpages' => array( 'Verna_sider' ), diff --git a/languages/messages/MessagesOc.php b/languages/messages/MessagesOc.php index 64220d89..0c01eb33 100644 --- a/languages/messages/MessagesOc.php +++ b/languages/messages/MessagesOc.php @@ -106,7 +106,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Mas_discussions', 'Masdiscussions' ), 'Newimages' => array( 'Imatges_novèls', 'ImatgesNovèls' ), 'Newpages' => array( 'Paginas_novèlas' ), - 'Popularpages' => array( 'Paginas_mai_visitadas', 'Paginas_las_mai_visitadas', 'Paginasmaivisitadas' ), + 'Preferences' => array( 'Preferéncias' ), 'Prefixindex' => array( 'Indèx' ), 'Protectedpages' => array( 'Paginas_protegidas' ), diff --git a/languages/messages/MessagesOr.php b/languages/messages/MessagesOr.php index f3bea174..2b09a770 100644 --- a/languages/messages/MessagesOr.php +++ b/languages/messages/MessagesOr.php @@ -131,7 +131,7 @@ $specialPageAliases = array( 'Newimages' => array( 'ନୂଆଫାଇଲ' ), 'Newpages' => array( 'ନୂଆପୃଷ୍ଠା' ), 'PermanentLink' => array( 'ଚିରକାଳଲିଙ୍କ' ), - 'Popularpages' => array( 'ଜଣାଶୁଣାପୃଷ୍ଠା' ), + 'Preferences' => array( 'ପସନ୍ଦ' ), 'Prefixindex' => array( 'ଆଗରେଯୋଡ଼ାହେବାଇଣ୍ଡେକ୍ସ' ), 'Protectedpages' => array( 'କିଳାଯାଇଥିବାପୃଷ୍ଠା' ), diff --git a/languages/messages/MessagesOs.php b/languages/messages/MessagesOs.php index 3c656108..88caf28b 100644 --- a/languages/messages/MessagesOs.php +++ b/languages/messages/MessagesOs.php @@ -109,7 +109,7 @@ $specialPageAliases = array( 'Newpages' => array( 'НогФæрстæ' ), 'PasswordReset' => array( 'ПарольНогКæнын' ), 'PermanentLink' => array( 'УдгасÆрвитæн' ), - 'Popularpages' => array( 'АрæхФæрстæ' ), + 'Preferences' => array( 'Уагæвæрдтæ' ), 'Prefixindex' => array( 'РазæфтуантыИндекс' ), 'Protectedpages' => array( 'ÆхгæдФæрстæ' ), diff --git a/languages/messages/MessagesPa.php b/languages/messages/MessagesPa.php index 3e3090c6..ffe1305d 100644 --- a/languages/messages/MessagesPa.php +++ b/languages/messages/MessagesPa.php @@ -128,7 +128,7 @@ $specialPageAliases = array( 'PageLanguage' => array( 'ਸਫ਼ੇ_ਦੀ_ਭਾਸ਼ਾ' ), 'PasswordReset' => array( 'ਪਾਸਵਰਡ_ਰੀਸੈੱਟ' ), 'PermanentLink' => array( 'ਪੱਕਾ_ਲਿੰਕ', 'ਪੱਕੀ_ਕੜੀ' ), - 'Popularpages' => array( 'ਮਸ਼ਹੂਰ_ਸਫ਼ੇ' ), + 'Preferences' => array( 'ਪਸੰਦਾਂ' ), 'Prefixindex' => array( 'ਅਗੇਤਰ_ਤਤਕਰਾ' ), 'Protectedpages' => array( 'ਸੁਰੱਖਿਅਤ_ਸਫ਼ੇ' ), diff --git a/languages/messages/MessagesPl.php b/languages/messages/MessagesPl.php index 4c822760..5d4030e4 100644 --- a/languages/messages/MessagesPl.php +++ b/languages/messages/MessagesPl.php @@ -187,7 +187,7 @@ $specialPageAliases = array( 'PagesWithProp' => array( 'Strony_z_własnością' ), 'PasswordReset' => array( 'Wyczyść_hasło' ), 'PermanentLink' => array( 'Niezmienny_link' ), - 'Popularpages' => array( 'Popularne_strony' ), + 'Preferences' => array( 'Preferencje' ), 'Prefixindex' => array( 'Strony_według_prefiksu' ), 'Protectedpages' => array( 'Zabezpieczone_strony' ), diff --git a/languages/messages/MessagesPs.php b/languages/messages/MessagesPs.php index fbc94194..f579bdba 100644 --- a/languages/messages/MessagesPs.php +++ b/languages/messages/MessagesPs.php @@ -64,7 +64,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'زما_خبرې_اترې' ), 'Newimages' => array( 'نوي_انځورونه' ), 'Newpages' => array( 'نوي_مخونه' ), - 'Popularpages' => array( 'نامتومخونه' ), + 'Preferences' => array( 'غوره_توبونه' ), 'Prefixindex' => array( 'د_مختاړيو_ليکلړ' ), 'Protectedpages' => array( 'ژغورلي_مخونه' ), diff --git a/languages/messages/MessagesPt.php b/languages/messages/MessagesPt.php index 7a293f6d..bf25c78a 100644 --- a/languages/messages/MessagesPt.php +++ b/languages/messages/MessagesPt.php @@ -174,7 +174,7 @@ $specialPageAliases = array( 'PagesWithProp' => array( 'Propriedades_de_página' ), 'PasswordReset' => array( 'Redefinir_autenticação' ), 'PermanentLink' => array( 'Ligação_permanente', 'Link_permanente' ), - 'Popularpages' => array( 'Páginas_populares', 'Artigos_populares' ), + 'Preferences' => array( 'Preferências' ), 'Prefixindex' => array( 'Índice_por_prefixo', 'Índice_de_prefixo' ), 'Protectedpages' => array( 'Páginas_protegidas', 'Artigos_protegidos' ), diff --git a/languages/messages/MessagesPt_br.php b/languages/messages/MessagesPt_br.php index 8a634706..158fe2ed 100644 --- a/languages/messages/MessagesPt_br.php +++ b/languages/messages/MessagesPt_br.php @@ -177,7 +177,7 @@ $specialPageAliases = array( 'Newimages' => array( 'Arquivos_novos', 'Imagens_novas', 'Ficheiros_novos' ), 'Newpages' => array( 'Páginas_novas', 'Artigos_novos' ), 'PermanentLink' => array( 'Ligação_permanente', 'Link_permanente' ), - 'Popularpages' => array( 'Páginas_populares', 'Artigos_populares' ), + 'Preferences' => array( 'Preferências' ), 'Prefixindex' => array( 'Índice_de_prefixo', 'Índice_por_prefixo' ), 'Protectedpages' => array( 'Páginas_protegidas', 'Artigos_protegidos' ), diff --git a/languages/messages/MessagesQu.php b/languages/messages/MessagesQu.php index 97afe6ba..d5ab0dc0 100644 --- a/languages/messages/MessagesQu.php +++ b/languages/messages/MessagesQu.php @@ -100,7 +100,7 @@ $specialPageAliases = array( 'Newpages' => array( 'MusuqPanqa' ), 'PasswordReset' => array( 'YaykunaRimaKutichina' ), 'PermanentLink' => array( 'KakuqTinki' ), - 'Popularpages' => array( 'WatukuqsapaPanqa', 'RikuqsapaPanqa', 'QhawaqsapaPanqa' ), + 'Preferences' => array( 'Allinkachina', 'Allinkachinakuna' ), 'Prefixindex' => array( 'QallarinaKaskaSutisuyu' ), 'Protectedpages' => array( 'AmachasqaPanqa' ), diff --git a/languages/messages/MessagesRo.php b/languages/messages/MessagesRo.php index 3d62d431..2708a45d 100644 --- a/languages/messages/MessagesRo.php +++ b/languages/messages/MessagesRo.php @@ -243,7 +243,7 @@ $specialPageAliases = array( 'Newimages' => array( 'Imagini_noi' ), 'Newpages' => array( 'Pagini_noi' ), 'PasswordReset' => array( 'Resetare_parolă' ), - 'Popularpages' => array( 'Pagini_populare' ), + 'Preferences' => array( 'Preferințe' ), 'Prefixindex' => array( 'Index' ), 'Protectedpages' => array( 'Pagini_protejate' ), diff --git a/languages/messages/MessagesRu.php b/languages/messages/MessagesRu.php index a74c9db9..5e3f6b4c 100644 --- a/languages/messages/MessagesRu.php +++ b/languages/messages/MessagesRu.php @@ -194,7 +194,7 @@ $specialPageAliases = array( 'Newpages' => array( 'Новые_страницы' ), 'PasswordReset' => array( 'Сброс_пароля' ), 'PermanentLink' => array( 'Постоянная_ссылка' ), - 'Popularpages' => array( 'Популярные_страницы' ), + 'Preferences' => array( 'Настройки' ), 'Prefixindex' => array( 'Указатель_по_началу_названия' ), 'Protectedpages' => array( 'Защищённые_страницы' ), diff --git a/languages/messages/MessagesRue.php b/languages/messages/MessagesRue.php index cb237418..b08eecdd 100644 --- a/languages/messages/MessagesRue.php +++ b/languages/messages/MessagesRue.php @@ -100,7 +100,7 @@ $specialPageAliases = array( 'Newpages' => array( 'Новы_сторінкы' ), 'PasswordReset' => array( 'Ресет_гесла' ), 'PermanentLink' => array( 'Тырвалый_одказ' ), - 'Popularpages' => array( 'Популарны_сторінкы' ), + 'Preferences' => array( 'Наставлїня' ), 'Protectedpages' => array( 'Замкнуты_сторінкы' ), 'Protectedtitles' => array( 'Замкнуты_назвы' ), diff --git a/languages/messages/MessagesSa.php b/languages/messages/MessagesSa.php index 14a8f99f..c3990893 100644 --- a/languages/messages/MessagesSa.php +++ b/languages/messages/MessagesSa.php @@ -132,7 +132,7 @@ $specialPageAliases = array( 'Newimages' => array( 'नूतनसंचिका', 'नूतनचित्रानि' ), 'Newpages' => array( 'नूतनपृष्टानि' ), 'PasswordReset' => array( 'सङ्केतशब्दपुन:प्रयु्क्ता' ), - 'Popularpages' => array( 'लोकप्रियपृष्टानि' ), + 'Preferences' => array( 'इष्टतमानि' ), 'Prefixindex' => array( 'उपसर्गअनुक्रमणी' ), 'Protectedpages' => array( 'सुरक्षितपृष्टानि' ), diff --git a/languages/messages/MessagesScn.php b/languages/messages/MessagesScn.php index 74ca0bcb..5714e434 100644 --- a/languages/messages/MessagesScn.php +++ b/languages/messages/MessagesScn.php @@ -110,7 +110,7 @@ $specialPageAliases = array( 'Newpages' => array( 'PaginePiùRecenti' ), 'PasswordReset' => array( 'ReimpostaPassword' ), 'PermanentLink' => array( 'LinkPermanente' ), - 'Popularpages' => array( 'PaginePiùVisitate' ), + 'Preferences' => array( 'Preferenze' ), 'Prefixindex' => array( 'Prefissi' ), 'Protectedpages' => array( 'PagineProtette' ), diff --git a/languages/messages/MessagesSd.php b/languages/messages/MessagesSd.php index adfc05e3..21270265 100644 --- a/languages/messages/MessagesSd.php +++ b/languages/messages/MessagesSd.php @@ -66,7 +66,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'مون سان ڳالهه' ), 'Newimages' => array( 'نوان عڪس' ), 'Newpages' => array( 'نوان صفحا' ), - 'Popularpages' => array( 'مقبول صفحا' ), + 'Preferences' => array( 'ترجيحات' ), 'Prefixindex' => array( 'اڳياڙي ڏسڻي' ), 'Protectedpages' => array( 'تحفظيل صفحا' ), diff --git a/languages/messages/MessagesSdc.php b/languages/messages/MessagesSdc.php index 4ab9c11c..c1d9cc3e 100644 --- a/languages/messages/MessagesSdc.php +++ b/languages/messages/MessagesSdc.php @@ -68,7 +68,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'MéDischussioni' ), 'Newimages' => array( 'ImmaginiRizzenti' ), 'Newpages' => array( 'PàginiPiùRizzenti' ), - 'Popularpages' => array( 'PàginiPiùVisitaddi' ), + 'Preferences' => array( 'Prifirènzi' ), 'Prefixindex' => array( 'Prefissi' ), 'Protectedpages' => array( 'PàginiPrutiggiddi' ), diff --git a/languages/messages/MessagesSe.php b/languages/messages/MessagesSe.php index 1917f32b..c819a760 100644 --- a/languages/messages/MessagesSe.php +++ b/languages/messages/MessagesSe.php @@ -80,7 +80,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Mu_ságastallan' ), 'Newimages' => array( 'Ođđa_govat', 'Ođđa_fiillat' ), 'Newpages' => array( 'Ođđa_siiddut' ), - 'Popularpages' => array( 'Bivnnuhis_siiddut' ), + 'Preferences' => array( 'Válljemat', 'Ásahusat' ), 'Protectedpages' => array( 'Suodjaluvvon_siiddut' ), 'Protectedtitles' => array( 'Suodjaluvvon_bajilčállagat', 'Suodjaluvvon_siidonamat' ), diff --git a/languages/messages/MessagesSh.php b/languages/messages/MessagesSh.php index f8aa19f7..c1eac9d7 100644 --- a/languages/messages/MessagesSh.php +++ b/languages/messages/MessagesSh.php @@ -76,7 +76,7 @@ $specialPageAliases = array( 'Myuploads' => array( 'Moje_postavljene_datoteke' ), 'Newimages' => array( 'Nove_datoteke', 'Nove_slike' ), 'Newpages' => array( 'Nove_stranice' ), - 'Popularpages' => array( 'Popularne_stranice' ), + 'Preferences' => array( 'Postavke' ), 'Prefixindex' => array( 'Prefiks_indeks', 'Stranice_po_prefiksu' ), 'Protectedpages' => array( 'Zaštićene_stranice' ), diff --git a/languages/messages/MessagesSi.php b/languages/messages/MessagesSi.php index 1ac48a00..209a907f 100644 --- a/languages/messages/MessagesSi.php +++ b/languages/messages/MessagesSi.php @@ -107,7 +107,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'මගේ_සාකච්ඡාව' ), 'Newimages' => array( 'නව_ගොනු', 'නව_රූප' ), 'Newpages' => array( 'නව_පිටුව' ), - 'Popularpages' => array( 'ජනප්රිය_පිටු' ), + 'Preferences' => array( 'අභිරුචියන්' ), 'Prefixindex' => array( 'උපසර්ග_සූචිය' ), 'Protectedpages' => array( 'ආරක්ෂිත_පිටුව' ), diff --git a/languages/messages/MessagesSk.php b/languages/messages/MessagesSk.php index 83155dab..6f114ac7 100644 --- a/languages/messages/MessagesSk.php +++ b/languages/messages/MessagesSk.php @@ -81,7 +81,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'MojaDiskusia' ), 'Newimages' => array( 'NovéSúbory' ), 'Newpages' => array( 'NovéStránky' ), - 'Popularpages' => array( 'PopulárneStránky' ), + 'Preferences' => array( 'Nastavenia' ), 'Prefixindex' => array( 'IndexPredpon' ), 'Protectedpages' => array( 'ZamknutéStránky' ), diff --git a/languages/messages/MessagesSl.php b/languages/messages/MessagesSl.php index ea6b569d..a42774d9 100644 --- a/languages/messages/MessagesSl.php +++ b/languages/messages/MessagesSl.php @@ -81,7 +81,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'MojPogovor' ), 'Newimages' => array( 'NoveDatoteke', 'NoveSlike' ), 'Newpages' => array( 'NoveStrani' ), - 'Popularpages' => array( 'PriljubljeneStrani' ), + 'Preferences' => array( 'Nastavitve' ), 'Protectedpages' => array( 'ZaščiteneStrani' ), 'Protectedtitles' => array( 'ZaščiteniNaslovi' ), diff --git a/languages/messages/MessagesSq.php b/languages/messages/MessagesSq.php index 987464a3..cd45321e 100644 --- a/languages/messages/MessagesSq.php +++ b/languages/messages/MessagesSq.php @@ -96,7 +96,7 @@ $specialPageAliases = array( 'Myuploads' => array( 'NgarkimeteMia' ), 'Newimages' => array( 'SkedaTëReja' ), 'Newpages' => array( 'FaqeteReja' ), - 'Popularpages' => array( 'FaqetëFamshme' ), + 'Preferences' => array( 'Preferencat' ), 'Protectedpages' => array( 'FaqeteMbrojtura' ), 'Protectedtitles' => array( 'TitujteMbrojtur' ), diff --git a/languages/messages/MessagesSr_ec.php b/languages/messages/MessagesSr_ec.php index 0f89cca6..0bc37d5c 100644 --- a/languages/messages/MessagesSr_ec.php +++ b/languages/messages/MessagesSr_ec.php @@ -143,7 +143,7 @@ $specialPageAliases = array( 'Newimages' => array( 'НовеДатотеке', 'НовиФајлови', 'НовеСлике' ), 'Newpages' => array( 'НовеСтране' ), 'PermanentLink' => array( 'Привремена_веза' ), - 'Popularpages' => array( 'Популарне_странице' ), + 'Preferences' => array( 'Подешавања', 'Поставке' ), 'Protectedpages' => array( 'ЗаштићенеСтранице', 'Заштићене_странице' ), 'Protectedtitles' => array( 'ЗаштићениНаслови', 'Заштићени_наслови' ), diff --git a/languages/messages/MessagesSu.php b/languages/messages/MessagesSu.php index 87c69215..8b1f3f1f 100644 --- a/languages/messages/MessagesSu.php +++ b/languages/messages/MessagesSu.php @@ -88,7 +88,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'ObrolanKuring' ), 'Newimages' => array( 'GambarAnyar' ), 'Newpages' => array( 'KacaAnyar' ), - 'Popularpages' => array( 'KacaPayu' ), + 'Preferences' => array( 'Preferensi' ), 'Prefixindex' => array( 'IndeksAwalan' ), 'Protectedpages' => array( 'KacaDikonci' ), diff --git a/languages/messages/MessagesSv.php b/languages/messages/MessagesSv.php index 48e35111..dfcb6cd3 100644 --- a/languages/messages/MessagesSv.php +++ b/languages/messages/MessagesSv.php @@ -156,7 +156,7 @@ $specialPageAliases = array( 'PageLanguage' => array( 'Sidspråk' ), 'PasswordReset' => array( 'Återställ_lösenord' ), 'PermanentLink' => array( 'Permanent_länk' ), - 'Popularpages' => array( 'Populära_sidor' ), + 'Preferences' => array( 'Inställningar' ), 'Protectedpages' => array( 'Skyddade_sidor' ), 'Protectedtitles' => array( 'Skyddade_titlar' ), diff --git a/languages/messages/MessagesSw.php b/languages/messages/MessagesSw.php index c653de30..9d5c2a25 100644 --- a/languages/messages/MessagesSw.php +++ b/languages/messages/MessagesSw.php @@ -89,7 +89,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'MajadilianoYangu' ), 'Newimages' => array( 'FailiMpya', 'FailimpyazaPicha' ), 'Newpages' => array( 'KurasaMpya' ), - 'Popularpages' => array( 'KurasaMaarufu' ), + 'Preferences' => array( 'Mapendekezo' ), 'Prefixindex' => array( 'KurasaKuu' ), 'Protectedpages' => array( 'KurasaZilizolindwa' ), diff --git a/languages/messages/MessagesTe.php b/languages/messages/MessagesTe.php index 5a5e44bf..e84a6c36 100644 --- a/languages/messages/MessagesTe.php +++ b/languages/messages/MessagesTe.php @@ -101,7 +101,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'నాచర్చ' ), 'Newimages' => array( 'కొత్తఫైళ్లు', 'కొత్తబొమ్మలు' ), 'Newpages' => array( 'కొత్తపేజీలు' ), - 'Popularpages' => array( 'ప్రాచుర్యంపొందినపేజీలు' ), + 'Preferences' => array( 'అభిరుచులు' ), 'Protectedpages' => array( 'సంరక్షితపేజీలు' ), 'Randompage' => array( 'యాదృచ్చికపేజీ' ), diff --git a/languages/messages/MessagesTh.php b/languages/messages/MessagesTh.php index 140073ab..7e8027a5 100644 --- a/languages/messages/MessagesTh.php +++ b/languages/messages/MessagesTh.php @@ -110,7 +110,7 @@ $specialPageAliases = array( 'Newpages' => array( 'หน้าใหม่' ), 'PasswordReset' => array( 'ตั้งรหัสผ่านใหม่' ), 'PermanentLink' => array( 'ลิงก์ถาวร' ), - 'Popularpages' => array( 'หน้าที่ได้รับความนิยม' ), + 'Preferences' => array( 'การตั้งค่า', 'ตั้งค่า' ), 'Prefixindex' => array( 'ดัชนีตามคำขึ้นต้น' ), 'Protectedpages' => array( 'หน้าที่ถูกป้องกัน' ), diff --git a/languages/messages/MessagesTl.php b/languages/messages/MessagesTl.php index 799dc345..04bf9d75 100644 --- a/languages/messages/MessagesTl.php +++ b/languages/messages/MessagesTl.php @@ -104,7 +104,7 @@ $specialPageAliases = array( 'Newpages' => array( 'Bagong_mga_pahina' ), 'PasswordReset' => array( 'Muling_Pagtatakda_ng_Hudyat' ), 'PermanentLink' => array( 'Pamalagiang_Kawing' ), - 'Popularpages' => array( 'Sikat_na_mga_pahina' ), + 'Preferences' => array( 'Mga_nais' ), 'Prefixindex' => array( 'Talatuntunan_ng_unlapi' ), 'Protectedpages' => array( 'Mga_pahinang_nakasanggalang' ), diff --git a/languages/messages/MessagesTr.php b/languages/messages/MessagesTr.php index 0f61a96b..df8b19b5 100644 --- a/languages/messages/MessagesTr.php +++ b/languages/messages/MessagesTr.php @@ -153,7 +153,7 @@ $specialPageAliases = array( 'Newpages' => array( 'YeniSayfalar' ), 'PasswordReset' => array( 'ParolaSıfırlama' ), 'PermanentLink' => array( 'KalıcıBağ' ), - 'Popularpages' => array( 'PopülerSayfalar' ), + 'Preferences' => array( 'Tercihler', 'Ayarlar' ), 'Prefixindex' => array( 'ÖnekDizini' ), 'Protectedpages' => array( 'KorunanSayfalar' ), diff --git a/languages/messages/MessagesTt_cyrl.php b/languages/messages/MessagesTt_cyrl.php index a9dbf3a9..1dd06096 100644 --- a/languages/messages/MessagesTt_cyrl.php +++ b/languages/messages/MessagesTt_cyrl.php @@ -145,7 +145,7 @@ $specialPageAliases = array( 'Mytalk' => array( 'Бәхәсем' ), 'Newimages' => array( 'Яңа_файл' ), 'Newpages' => array( 'Яңа_бит' ), - 'Popularpages' => array( 'Популяр_битләр' ), + 'Preferences' => array( 'Көйләнмәләр' ), 'Protectedpages' => array( 'Якланган_битләр' ), 'Protectedtitles' => array( 'Якланган_башлыклар' ), diff --git a/languages/messages/MessagesUk.php b/languages/messages/MessagesUk.php index 2caaefaa..173924e7 100644 --- a/languages/messages/MessagesUk.php +++ b/languages/messages/MessagesUk.php @@ -176,7 +176,7 @@ $specialPageAliases = array( 'Newpages' => array( 'Нові_сторінки' ), 'PasswordReset' => array( 'Скинути_пароль' ), 'PermanentLink' => array( 'Постійне_посилання' ), - 'Popularpages' => array( 'Популярні_сторінки' ), + 'Preferences' => array( 'Налаштування' ), 'Prefixindex' => array( 'Покажчик_за_початком_назви' ), 'Protectedpages' => array( 'Захищені_сторінки' ), diff --git a/languages/messages/MessagesUr.php b/languages/messages/MessagesUr.php index 81a6d2f0..2e323841 100644 --- a/languages/messages/MessagesUr.php +++ b/languages/messages/MessagesUr.php @@ -104,7 +104,7 @@ $specialPageAliases = array( 'Newimages' => array( 'جدید_املاف', 'جدید_تصاویر' ), 'Newpages' => array( 'جدید_صفحات' ), 'PermanentLink' => array( 'مستقل_ربط' ), - 'Popularpages' => array( 'مقبول_صفحات' ), + 'Preferences' => array( 'ترجیحات' ), 'Prefixindex' => array( 'اشاریہ_سابقہ' ), 'Protectedpages' => array( 'محفوظ_صفحات' ), diff --git a/languages/messages/MessagesVec.php b/languages/messages/MessagesVec.php index 9242d839..23eadc6a 100644 --- a/languages/messages/MessagesVec.php +++ b/languages/messages/MessagesVec.php @@ -117,7 +117,7 @@ $specialPageAliases = array( 'Newpages' => array( 'PagineNove' ), 'PasswordReset' => array( 'ReinpostaPassword' ), 'PermanentLink' => array( 'LinkParmanente' ), - 'Popularpages' => array( 'PaginePiassèVisità' ), + 'Preferences' => array( 'Preferense' ), 'Prefixindex' => array( 'Prefissi' ), 'Protectedpages' => array( 'PagineProtete' ), diff --git a/languages/messages/MessagesVi.php b/languages/messages/MessagesVi.php index 2724a60a..6c03a466 100644 --- a/languages/messages/MessagesVi.php +++ b/languages/messages/MessagesVi.php @@ -125,7 +125,7 @@ $specialPageAliases = array( 'PageLanguage' => array( 'Ngôn_ngữ_trang' ), 'PasswordReset' => array( 'Tái_tạo_mật_khẩu', 'Đặt_lại_mật_khẩu' ), 'PermanentLink' => array( 'Liên_kết_thường_trực' ), - 'Popularpages' => array( 'Trang_phổ_biến' ), + 'Preferences' => array( 'Tùy_chọn', 'Tuỳ_chọn' ), 'Prefixindex' => array( 'Tiền_tố' ), 'Protectedpages' => array( 'Trang_khóa', 'Trang_khoá' ), diff --git a/languages/messages/MessagesYi.php b/languages/messages/MessagesYi.php index ed61df43..69366567 100644 --- a/languages/messages/MessagesYi.php +++ b/languages/messages/MessagesYi.php @@ -110,7 +110,7 @@ $specialPageAliases = array( 'Myuploads' => array( 'מיינע_ארויפלאדונגען' ), 'Newimages' => array( 'נייע_בילדער' ), 'Newpages' => array( 'נייע_בלעטער' ), - 'Popularpages' => array( 'פאפולערע_בלעטער' ), + 'Preferences' => array( 'פרעפערענצן' ), 'Prefixindex' => array( 'בלעטער_וואס_הייבן_אן_מיט' ), 'Protectedpages' => array( 'געשיצטע_בלעטער' ), diff --git a/languages/messages/MessagesYue.php b/languages/messages/MessagesYue.php index dcbc3e1f..106a1469 100644 --- a/languages/messages/MessagesYue.php +++ b/languages/messages/MessagesYue.php @@ -151,7 +151,7 @@ $specialPageAliases = array( 'Newpages' => array( '新版' ), 'PasswordReset' => array( '重設密碼' ), 'PermanentLink' => array( '永久鏈' ), - 'Popularpages' => array( '最歡迎頁' ), + 'Preferences' => array( '喜好設定' ), 'Prefixindex' => array( '全部頁嘅前綴' ), 'Protectedpages' => array( '保護頁' ), diff --git a/languages/messages/MessagesZh.php b/languages/messages/MessagesZh.php index 8ee87f07..d6102683 100644 --- a/languages/messages/MessagesZh.php +++ b/languages/messages/MessagesZh.php @@ -144,7 +144,7 @@ $specialPageAliases = array( 'Newimages' => array( '新建文件', '新建檔案' ), 'Newpages' => array( '最新页面', '最新頁面' ), 'PasswordReset' => array( '重置密码', '重設密碼' ), - 'Popularpages' => array( '热点页面', '熱點頁面' ), + 'Preferences' => array( '参数设置', '偏好設定', '參數設置' ), 'Prefixindex' => array( '前缀索引', '前綴索引', '字首索引' ), 'Protectedpages' => array( '已保护页面', '已保護頁面' ), diff --git a/languages/messages/MessagesZh_hans.php b/languages/messages/MessagesZh_hans.php index 84d43734..57c9a614 100644 --- a/languages/messages/MessagesZh_hans.php +++ b/languages/messages/MessagesZh_hans.php @@ -199,7 +199,6 @@ $specialPageAliases = array( 'PageLanguage' => array( '页面语言' ), 'PasswordReset' => array( '重设密码' ), 'PermanentLink' => array( '固定链接', '永久链接' ), - 'Popularpages' => array( '热点页面' ), 'Preferences' => array( '参数设置', '设置' ), 'Prefixindex' => array( '前缀索引' ), 'Protectedpages' => array( '已保护页面' ), diff --git a/languages/messages/MessagesZh_hant.php b/languages/messages/MessagesZh_hant.php index 6e5dea11..1f6bcfaa 100644 --- a/languages/messages/MessagesZh_hant.php +++ b/languages/messages/MessagesZh_hant.php @@ -183,7 +183,6 @@ $specialPageAliases = array( 'PageLanguage' => array( '頁面語言' ), 'PasswordReset' => array( '重設密碼' ), 'PermanentLink' => array( '靜態連結', '永久連結' ), - 'Popularpages' => array( '熱門頁面', '熱點頁面' ), 'Preferences' => array( '偏好設定' ), 'Prefixindex' => array( '字首索引', '前綴索引' ), 'Protectedpages' => array( '受保護頁面', '已保護頁面' ), diff --git a/maintenance/Maintenance.php b/maintenance/Maintenance.php index 923c5b41..5dafdfc0 100644 --- a/maintenance/Maintenance.php +++ b/maintenance/Maintenance.php @@ -1097,7 +1097,7 @@ abstract class Maintenance { */ private function lockSearchindex( $db ) { $write = array( 'searchindex' ); - $read = array( 'page', 'revision', 'text', 'interwiki', 'l10n_cache', 'user' ); + $read = array( 'page', 'revision', 'text', 'interwiki', 'l10n_cache', 'user', 'page_restrictions' ); $db->lockTables( $read, $write, __CLASS__ . '::' . __METHOD__ ); } diff --git a/maintenance/dictionary/mediawiki.dic b/maintenance/dictionary/mediawiki.dic index dd27c8ca..ad19a1ce 100644 --- a/maintenance/dictionary/mediawiki.dic +++ b/maintenance/dictionary/mediawiki.dic @@ -3158,7 +3158,6 @@ pnmtopng pointsize poolcounter popts -popularpages portlet portlets posplus diff --git a/resources/Resources.php b/resources/Resources.php index 2c0ca9d9..feda8a53 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -1202,6 +1202,7 @@ return array( 'jquery.textSelection', 'mediawiki.jqueryMsg', 'mediawiki.confirmCloseWindow', + 'user.options', ), 'messages' => array( 'editwarning-warning', @@ -1483,6 +1484,7 @@ return array( 'mediawiki.Title', 'mediawiki.util', 'mediawiki.confirmCloseWindow', + 'user.options', ), ), 'mediawiki.special.userlogin.common.styles' => array( diff --git a/resources/assets/file-type-icons/fileicon-djvu.xcf b/resources/assets/file-type-icons/fileicon-djvu.xcf Binary files differnew file mode 100644 index 00000000..8043dcdb --- /dev/null +++ b/resources/assets/file-type-icons/fileicon-djvu.xcf diff --git a/resources/assets/file-type-icons/fileicon-ogg.xcf b/resources/assets/file-type-icons/fileicon-ogg.xcf Binary files differnew file mode 100644 index 00000000..a91024bf --- /dev/null +++ b/resources/assets/file-type-icons/fileicon-ogg.xcf diff --git a/tests/parser/preprocess/All_system_messages.expected b/tests/parser/preprocess/All_system_messages.expected index 2ee805e0..3665e3c1 100644 --- a/tests/parser/preprocess/All_system_messages.expected +++ b/tests/parser/preprocess/All_system_messages.expected @@ -3193,13 +3193,6 @@ About </td><td> <template lineStart="1"><title>int:Nstab-wp</title></template> </td></tr><tr><td> -[http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Nviews&action=edit nviews]<br> -[[MediaWiki_talk:Nviews|Talk]] -</td><td> -$1 views -</td><td> -<template lineStart="1"><title>int:Nviews</title></template> -</td></tr><tr><td> [http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Ok&action=edit ok]<br> [[MediaWiki_talk:Ok|Talk]] </td><td> @@ -3319,13 +3312,6 @@ Personal tools </td><td> <template lineStart="1"><title>int:Personaltools</title></template> </td></tr><tr><td> -[http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Popularpages&action=edit popularpages]<br> -[[MediaWiki_talk:Popularpages|Talk]] -</td><td> -Popular pages -</td><td> -<template lineStart="1"><title>int:Popularpages</title></template> -</td></tr><tr><td> [http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Portal&action=edit portal]<br> [[MediaWiki_talk:Portal|Talk]] </td><td> diff --git a/tests/parser/preprocess/All_system_messages.txt b/tests/parser/preprocess/All_system_messages.txt index 4a30f56f..c619df7b 100644 --- a/tests/parser/preprocess/All_system_messages.txt +++ b/tests/parser/preprocess/All_system_messages.txt @@ -3193,13 +3193,6 @@ About </td><td> {{int:Nstab-wp}} </td></tr><tr><td> -[http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Nviews&action=edit nviews]<br> -[[MediaWiki_talk:Nviews|Talk]] -</td><td> -$1 views -</td><td> -{{int:Nviews}} -</td></tr><tr><td> [http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Ok&action=edit ok]<br> [[MediaWiki_talk:Ok|Talk]] </td><td> @@ -3319,13 +3312,6 @@ Personal tools </td><td> {{int:Personaltools}} </td></tr><tr><td> -[http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Popularpages&action=edit popularpages]<br> -[[MediaWiki_talk:Popularpages|Talk]] -</td><td> -Popular pages -</td><td> -{{int:Popularpages}} -</td></tr><tr><td> [http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Portal&action=edit portal]<br> [[MediaWiki_talk:Portal|Talk]] </td><td> diff --git a/tests/phpunit/data/media/80x60-2layers.xcf b/tests/phpunit/data/media/80x60-2layers.xcf Binary files differnew file mode 100644 index 00000000..c51e980c --- /dev/null +++ b/tests/phpunit/data/media/80x60-2layers.xcf diff --git a/tests/phpunit/data/media/80x60-Greyscale.xcf b/tests/phpunit/data/media/80x60-Greyscale.xcf Binary files differnew file mode 100644 index 00000000..84bf3e67 --- /dev/null +++ b/tests/phpunit/data/media/80x60-Greyscale.xcf diff --git a/tests/phpunit/data/media/80x60-RGB.xcf b/tests/phpunit/data/media/80x60-RGB.xcf Binary files differnew file mode 100644 index 00000000..1d58f16d --- /dev/null +++ b/tests/phpunit/data/media/80x60-RGB.xcf diff --git a/tests/phpunit/includes/registration/ExtensionRegistryTest.php b/tests/phpunit/includes/registration/ExtensionRegistryTest.php index 1b24628c..d7d4f198 100644 --- a/tests/phpunit/includes/registration/ExtensionRegistryTest.php +++ b/tests/phpunit/includes/registration/ExtensionRegistryTest.php @@ -189,7 +189,19 @@ class ExtensionRegistryTest extends MediaWikiTestCase { ) ), ), - ) + ), + array( + 'False local setting should not be overridden (T100767)', + array( + 'mwtestT100767' => false, + ), + array( + 'mwtestT100767' => true, + ), + array( + 'mwtestT100767' => false, + ), + ), ); } } @@ -167,7 +167,7 @@ function wfStreamThumb( array $params ) { // Check if the file is hidden if ( $img->isDeleted( File::DELETED_FILE ) ) { - wfThumbError( 404, "The source file '$fileName' does not exist." ); + wfThumbErrorText( 404, "The source file '$fileName' does not exist." ); return; } @@ -221,10 +221,10 @@ function wfStreamThumb( array $params ) { } // If its not a redirect that has a target as a local file, give 404. - wfThumbError( 404, "The source file '$fileName' does not exist." ); + wfThumbErrorText( 404, "The source file '$fileName' does not exist." ); return; } elseif ( $img->getPath() === false ) { - wfThumbError( 500, "The source file '$fileName' is not locally accessible." ); + wfThumbErrorText( 500, "The source file '$fileName' is not locally accessible." ); return; } @@ -286,7 +286,7 @@ function wfStreamThumb( array $params ) { } return; } else { - wfThumbError( 404, "The given path of the specified thumbnail is incorrect; + wfThumbErrorText( 404, "The given path of the specified thumbnail is incorrect; expected '" . $img->getThumbRel( $thumbName ) . "' but got '" . rawurldecode( $rel404 ) . "'." ); return; @@ -544,14 +544,26 @@ function wfExtractThumbParams( $file, $params ) { return null; } + +/** + * Output a thumbnail generation error message + * + * @param int $status + * @param string $msg Plain text (will be html escaped) + * @return void + */ +function wfThumbErrorText( $status, $msgText ) { + return wfThumbError( $status, htmlspecialchars( $msgText ) ); +} + /** * Output a thumbnail generation error message * * @param int $status - * @param string $msg HTML + * @param string $msgHtml HTML * @return void */ -function wfThumbError( $status, $msg ) { +function wfThumbError( $status, $msgHtml ) { global $wgShowHostnames; header( 'Cache-Control: no-cache' ); @@ -583,7 +595,7 @@ function wfThumbError( $status, $msg ) { <body> <h1>Error generating thumbnail</h1> <p> -$msg +$msgHtml </p> $debug </body> diff --git a/vendor/README.md b/vendor/README.md new file mode 100644 index 00000000..247d4df5 --- /dev/null +++ b/vendor/README.md @@ -0,0 +1,28 @@ +MediaWiki-Core-Vendor +===================== + +[Composer] managed libraries required or recommended for use with [MediaWiki]. +This repository is maintained for use on the Wikimedia Foundation production +and testing clusters, but may be useful for anyone wishing to avoid directly +managing MediaWiki dependencies with Composer. + + +Usage +----- + +Checkout this library into $IP/vendor using `git clone <URL>` or add the +repository as a git submodule using `git submodule add <URL> vendor` followed +by `git submodule update --init`. + + +Adding or updating libraries +---------------------------- + +1. Edit the composer.json file +2. Run `composer update` to download files and update the autoloader files. +3. Add and commit changes as a gerrit patch. +4. Review and merge changes. + + +[Composer]: https://getcomposer.org/ +[MediaWiki]: https://www.mediawiki.org/wiki/MediaWiki diff --git a/vendor/autoload.php b/vendor/autoload.php index 69e72b37..9bcfa9fe 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInit9b10cc5cf6896d6e4a31983fc3498786::getLoader(); +return ComposerAutoloaderInit_mediawiki_vendor::getLoader(); diff --git a/vendor/composer.json b/vendor/composer.json new file mode 100644 index 00000000..0cee8f3c --- /dev/null +++ b/vendor/composer.json @@ -0,0 +1,25 @@ +{ + "require": { + "cssjanus/cssjanus": "1.1.1", + "leafo/lessphp": "0.5.0", + "liuggio/statsd-php-client": "1.0.12", + "php": ">=5.3.3", + "psr/log": "1.0.0", + "monolog/monolog": "1.12.0", + "ruflin/elastica": "1.3.0.0", + "oojs/oojs-ui": "0.11.3", + "wikimedia/cdb": "1.0.1", + "wikimedia/composer-merge-plugin": "1.0.0", + "wikimedia/utfnormal": "1.0.2", + "zordius/lightncandy": "0.18" + }, + "prefer-stable": true, + "config": { + "autoloader-suffix": "_mediawiki_vendor", + "classmap-authoritative": true, + "preferred-install": "dist", + "vendor-dir": ".", + "prepend-autoloader": false, + "optimize-autoloader": true + } +} diff --git a/composer.lock b/vendor/composer.lock index be756552..e238ed8a 100644 --- a/composer.lock +++ b/vendor/composer.lock @@ -1,10 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "0a4e1a6fe7b47b5659f5ebe278ab2f42", + "hash": "99d794be1df1caf0b238fd68d2a37058", "packages": [ { "name": "cssjanus/cssjanus", @@ -132,6 +132,78 @@ "time": "2014-09-17 21:37:49" }, { + "name": "monolog/monolog", + "version": "1.12.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "1fbe8c2641f2b163addf49cc5e18f144bec6b19f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1fbe8c2641f2b163addf49cc5e18f144bec6b19f", + "reference": "1fbe8c2641f2b163addf49cc5e18f144bec6b19f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "psr/log": "~1.0" + }, + "provide": { + "psr/log-implementation": "1.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "~2.4, >2.4.8", + "doctrine/couchdb": "~1.0@dev", + "graylog2/gelf-php": "~1.0", + "phpunit/phpunit": "~4.0", + "raven/raven": "~0.5", + "ruflin/elastica": "0.90.*", + "videlalvaro/php-amqplib": "~2.4" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-mongo": "Allow sending log messages to a MongoDB server", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "raven/raven": "Allow sending log messages to a Sentry server", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server", + "videlalvaro/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "http://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "time": "2014-12-29 21:29:35" + }, + { "name": "oojs/oojs-ui", "version": "v0.11.3", "source": { @@ -206,6 +278,65 @@ "time": "2012-12-21 11:40:51" }, { + "name": "ruflin/elastica", + "version": "v1.3.0.0", + "source": { + "type": "git", + "url": "https://github.com/ruflin/Elastica.git", + "reference": "92155a36c94ebe15b09661ae804acbe4bdd4ad6b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ruflin/Elastica/zipball/92155a36c94ebe15b09661ae804acbe4bdd4ad6b", + "reference": "92155a36c94ebe15b09661ae804acbe4bdd4ad6b", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "munkie/elasticsearch-thrift-php": "1.4.*", + "phpunit/phpunit": "4.1.*", + "psr/log": "~1.0", + "satooshi/php-coveralls": "dev-master" + }, + "suggest": { + "guzzlehttp/guzzle": "Allow using guzzle 4.x as the http transport (requires php 5.4)", + "monolog/monolog": "Logging request", + "munkie/elasticsearch-thrift-php": "Allow using thrift transport", + "psr/log": "for logging" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-0": { + "Elastica": "lib/", + "Elastica\\Test": "test/lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache 2.0" + ], + "authors": [ + { + "name": "Nicolas Ruflin", + "homepage": "http://ruflin.com/" + } + ], + "description": "Elasticsearch Client", + "homepage": "http://elastica.io/", + "keywords": [ + "client", + "search" + ], + "time": "2014-07-27 13:45:09" + }, + { "name": "wikimedia/cdb", "version": "1.0.1", "source": { @@ -381,14 +512,13 @@ "time": "2015-01-01 04:37:19" } ], - "packages-dev": null, + "packages-dev": [], "aliases": [], "minimum-stability": "stable", "stability-flags": [], - "prefer-stable": false, + "prefer-stable": true, "prefer-lowest": false, "platform": { - "ext-iconv": "*", "php": ">=5.3.3" }, "platform-dev": [] diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index 5e1469e8..4e05d3b1 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -351,7 +351,7 @@ class ClassLoader foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { if (0 === strpos($class, $prefix)) { foreach ($this->prefixDirsPsr4[$prefix] as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { + if (is_file($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { return $file; } } @@ -361,7 +361,7 @@ class ClassLoader // PSR-4 fallback dirs foreach ($this->fallbackDirsPsr4 as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { return $file; } } @@ -380,7 +380,7 @@ class ClassLoader foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { if (0 === strpos($class, $prefix)) { foreach ($dirs as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { return $file; } } @@ -390,7 +390,7 @@ class ClassLoader // PSR-0 fallback dirs foreach ($this->fallbackDirsPsr0 as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { return $file; } } diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 79053ea1..7455d6e6 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -3,7 +3,7 @@ // autoload_classmap.php @generated by Composer $vendorDir = dirname(dirname(__FILE__)); -$baseDir = dirname($vendorDir); +$baseDir = $vendorDir; return array( 'CSSJanus' => $vendorDir . '/cssjanus/cssjanus/src/CSSJanus.php', @@ -16,7 +16,183 @@ return array( 'Cdb\\Writer' => $vendorDir . '/wikimedia/cdb/src/Writer.php', 'Cdb\\Writer\\DBA' => $vendorDir . '/wikimedia/cdb/src/Writer/DBA.php', 'Cdb\\Writer\\PHP' => $vendorDir . '/wikimedia/cdb/src/Writer/PHP.php', - 'ComposerHookHandler' => $baseDir . '/includes/composer/ComposerHookHandler.php', + 'Elastica\\AbstractUpdateAction' => $vendorDir . '/ruflin/elastica/lib/Elastica/AbstractUpdateAction.php', + 'Elastica\\Aggregation\\AbstractAggregation' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/AbstractAggregation.php', + 'Elastica\\Aggregation\\AbstractSimpleAggregation' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/AbstractSimpleAggregation.php', + 'Elastica\\Aggregation\\Avg' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/Avg.php', + 'Elastica\\Aggregation\\Cardinality' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/Cardinality.php', + 'Elastica\\Aggregation\\DateHistogram' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/DateHistogram.php', + 'Elastica\\Aggregation\\DateRange' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/DateRange.php', + 'Elastica\\Aggregation\\ExtendedStats' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/ExtendedStats.php', + 'Elastica\\Aggregation\\Filter' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/Filter.php', + 'Elastica\\Aggregation\\GeoDistance' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/GeoDistance.php', + 'Elastica\\Aggregation\\GeohashGrid' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/GeohashGrid.php', + 'Elastica\\Aggregation\\GlobalAggregation' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/GlobalAggregation.php', + 'Elastica\\Aggregation\\Histogram' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/Histogram.php', + 'Elastica\\Aggregation\\IpRange' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/IpRange.php', + 'Elastica\\Aggregation\\Max' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/Max.php', + 'Elastica\\Aggregation\\Min' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/Min.php', + 'Elastica\\Aggregation\\Missing' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/Missing.php', + 'Elastica\\Aggregation\\Nested' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/Nested.php', + 'Elastica\\Aggregation\\Range' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/Range.php', + 'Elastica\\Aggregation\\ReverseNested' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/ReverseNested.php', + 'Elastica\\Aggregation\\Stats' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/Stats.php', + 'Elastica\\Aggregation\\Sum' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/Sum.php', + 'Elastica\\Aggregation\\Terms' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/Terms.php', + 'Elastica\\Aggregation\\ValueCount' => $vendorDir . '/ruflin/elastica/lib/Elastica/Aggregation/ValueCount.php', + 'Elastica\\Bulk' => $vendorDir . '/ruflin/elastica/lib/Elastica/Bulk.php', + 'Elastica\\Bulk\\Action' => $vendorDir . '/ruflin/elastica/lib/Elastica/Bulk/Action.php', + 'Elastica\\Bulk\\Action\\AbstractDocument' => $vendorDir . '/ruflin/elastica/lib/Elastica/Bulk/Action/AbstractDocument.php', + 'Elastica\\Bulk\\Action\\CreateDocument' => $vendorDir . '/ruflin/elastica/lib/Elastica/Bulk/Action/CreateDocument.php', + 'Elastica\\Bulk\\Action\\DeleteDocument' => $vendorDir . '/ruflin/elastica/lib/Elastica/Bulk/Action/DeleteDocument.php', + 'Elastica\\Bulk\\Action\\IndexDocument' => $vendorDir . '/ruflin/elastica/lib/Elastica/Bulk/Action/IndexDocument.php', + 'Elastica\\Bulk\\Action\\UpdateDocument' => $vendorDir . '/ruflin/elastica/lib/Elastica/Bulk/Action/UpdateDocument.php', + 'Elastica\\Bulk\\Response' => $vendorDir . '/ruflin/elastica/lib/Elastica/Bulk/Response.php', + 'Elastica\\Bulk\\ResponseSet' => $vendorDir . '/ruflin/elastica/lib/Elastica/Bulk/ResponseSet.php', + 'Elastica\\Client' => $vendorDir . '/ruflin/elastica/lib/Elastica/Client.php', + 'Elastica\\Cluster' => $vendorDir . '/ruflin/elastica/lib/Elastica/Cluster.php', + 'Elastica\\Cluster\\Health' => $vendorDir . '/ruflin/elastica/lib/Elastica/Cluster/Health.php', + 'Elastica\\Cluster\\Health\\Index' => $vendorDir . '/ruflin/elastica/lib/Elastica/Cluster/Health/Index.php', + 'Elastica\\Cluster\\Health\\Shard' => $vendorDir . '/ruflin/elastica/lib/Elastica/Cluster/Health/Shard.php', + 'Elastica\\Cluster\\Settings' => $vendorDir . '/ruflin/elastica/lib/Elastica/Cluster/Settings.php', + 'Elastica\\Connection' => $vendorDir . '/ruflin/elastica/lib/Elastica/Connection.php', + 'Elastica\\Document' => $vendorDir . '/ruflin/elastica/lib/Elastica/Document.php', + 'Elastica\\Exception\\BulkException' => $vendorDir . '/ruflin/elastica/lib/Elastica/Exception/BulkException.php', + 'Elastica\\Exception\\Bulk\\ResponseException' => $vendorDir . '/ruflin/elastica/lib/Elastica/Exception/Bulk/ResponseException.php', + 'Elastica\\Exception\\Bulk\\Response\\ActionException' => $vendorDir . '/ruflin/elastica/lib/Elastica/Exception/Bulk/Response/ActionException.php', + 'Elastica\\Exception\\Bulk\\UdpException' => $vendorDir . '/ruflin/elastica/lib/Elastica/Exception/Bulk/UdpException.php', + 'Elastica\\Exception\\ClientException' => $vendorDir . '/ruflin/elastica/lib/Elastica/Exception/ClientException.php', + 'Elastica\\Exception\\ConnectionException' => $vendorDir . '/ruflin/elastica/lib/Elastica/Exception/ConnectionException.php', + 'Elastica\\Exception\\Connection\\GuzzleException' => $vendorDir . '/ruflin/elastica/lib/Elastica/Exception/Connection/GuzzleException.php', + 'Elastica\\Exception\\Connection\\HttpException' => $vendorDir . '/ruflin/elastica/lib/Elastica/Exception/Connection/HttpException.php', + 'Elastica\\Exception\\Connection\\ThriftException' => $vendorDir . '/ruflin/elastica/lib/Elastica/Exception/Connection/ThriftException.php', + 'Elastica\\Exception\\ElasticsearchException' => $vendorDir . '/ruflin/elastica/lib/Elastica/Exception/ElasticsearchException.php', + 'Elastica\\Exception\\ExceptionInterface' => $vendorDir . '/ruflin/elastica/lib/Elastica/Exception/ExceptionInterface.php', + 'Elastica\\Exception\\InvalidException' => $vendorDir . '/ruflin/elastica/lib/Elastica/Exception/InvalidException.php', + 'Elastica\\Exception\\JSONParseException' => $vendorDir . '/ruflin/elastica/lib/Elastica/Exception/JSONParseException.php', + 'Elastica\\Exception\\NotFoundException' => $vendorDir . '/ruflin/elastica/lib/Elastica/Exception/NotFoundException.php', + 'Elastica\\Exception\\NotImplementedException' => $vendorDir . '/ruflin/elastica/lib/Elastica/Exception/NotImplementedException.php', + 'Elastica\\Exception\\PartialShardFailureException' => $vendorDir . '/ruflin/elastica/lib/Elastica/Exception/PartialShardFailureException.php', + 'Elastica\\Exception\\ResponseException' => $vendorDir . '/ruflin/elastica/lib/Elastica/Exception/ResponseException.php', + 'Elastica\\Exception\\RuntimeException' => $vendorDir . '/ruflin/elastica/lib/Elastica/Exception/RuntimeException.php', + 'Elastica\\Facet\\AbstractFacet' => $vendorDir . '/ruflin/elastica/lib/Elastica/Facet/AbstractFacet.php', + 'Elastica\\Facet\\DateHistogram' => $vendorDir . '/ruflin/elastica/lib/Elastica/Facet/DateHistogram.php', + 'Elastica\\Facet\\Filter' => $vendorDir . '/ruflin/elastica/lib/Elastica/Facet/Filter.php', + 'Elastica\\Facet\\GeoCluster' => $vendorDir . '/ruflin/elastica/lib/Elastica/Facet/GeoCluster.php', + 'Elastica\\Facet\\GeoDistance' => $vendorDir . '/ruflin/elastica/lib/Elastica/Facet/GeoDistance.php', + 'Elastica\\Facet\\Histogram' => $vendorDir . '/ruflin/elastica/lib/Elastica/Facet/Histogram.php', + 'Elastica\\Facet\\Query' => $vendorDir . '/ruflin/elastica/lib/Elastica/Facet/Query.php', + 'Elastica\\Facet\\Range' => $vendorDir . '/ruflin/elastica/lib/Elastica/Facet/Range.php', + 'Elastica\\Facet\\Statistical' => $vendorDir . '/ruflin/elastica/lib/Elastica/Facet/Statistical.php', + 'Elastica\\Facet\\Terms' => $vendorDir . '/ruflin/elastica/lib/Elastica/Facet/Terms.php', + 'Elastica\\Facet\\TermsStats' => $vendorDir . '/ruflin/elastica/lib/Elastica/Facet/TermsStats.php', + 'Elastica\\Filter\\AbstractFilter' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/AbstractFilter.php', + 'Elastica\\Filter\\AbstractGeoDistance' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/AbstractGeoDistance.php', + 'Elastica\\Filter\\AbstractGeoShape' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/AbstractGeoShape.php', + 'Elastica\\Filter\\AbstractMulti' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/AbstractMulti.php', + 'Elastica\\Filter\\Bool' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/Bool.php', + 'Elastica\\Filter\\BoolAnd' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/BoolAnd.php', + 'Elastica\\Filter\\BoolNot' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/BoolNot.php', + 'Elastica\\Filter\\BoolOr' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/BoolOr.php', + 'Elastica\\Filter\\Exists' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/Exists.php', + 'Elastica\\Filter\\GeoBoundingBox' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/GeoBoundingBox.php', + 'Elastica\\Filter\\GeoDistance' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/GeoDistance.php', + 'Elastica\\Filter\\GeoDistanceRange' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/GeoDistanceRange.php', + 'Elastica\\Filter\\GeoPolygon' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/GeoPolygon.php', + 'Elastica\\Filter\\GeoShapePreIndexed' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/GeoShapePreIndexed.php', + 'Elastica\\Filter\\GeoShapeProvided' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/GeoShapeProvided.php', + 'Elastica\\Filter\\GeohashCell' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/GeohashCell.php', + 'Elastica\\Filter\\HasChild' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/HasChild.php', + 'Elastica\\Filter\\HasParent' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/HasParent.php', + 'Elastica\\Filter\\Ids' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/Ids.php', + 'Elastica\\Filter\\Indices' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/Indices.php', + 'Elastica\\Filter\\Limit' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/Limit.php', + 'Elastica\\Filter\\MatchAll' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/MatchAll.php', + 'Elastica\\Filter\\Missing' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/Missing.php', + 'Elastica\\Filter\\Nested' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/Nested.php', + 'Elastica\\Filter\\NumericRange' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/NumericRange.php', + 'Elastica\\Filter\\Prefix' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/Prefix.php', + 'Elastica\\Filter\\Query' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/Query.php', + 'Elastica\\Filter\\Range' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/Range.php', + 'Elastica\\Filter\\Regexp' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/Regexp.php', + 'Elastica\\Filter\\Script' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/Script.php', + 'Elastica\\Filter\\Term' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/Term.php', + 'Elastica\\Filter\\Terms' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/Terms.php', + 'Elastica\\Filter\\Type' => $vendorDir . '/ruflin/elastica/lib/Elastica/Filter/Type.php', + 'Elastica\\Index' => $vendorDir . '/ruflin/elastica/lib/Elastica/Index.php', + 'Elastica\\Index\\Settings' => $vendorDir . '/ruflin/elastica/lib/Elastica/Index/Settings.php', + 'Elastica\\Index\\Stats' => $vendorDir . '/ruflin/elastica/lib/Elastica/Index/Stats.php', + 'Elastica\\Index\\Status' => $vendorDir . '/ruflin/elastica/lib/Elastica/Index/Status.php', + 'Elastica\\JSON' => $vendorDir . '/ruflin/elastica/lib/Elastica/JSON.php', + 'Elastica\\Log' => $vendorDir . '/ruflin/elastica/lib/Elastica/Log.php', + 'Elastica\\Multi\\ResultSet' => $vendorDir . '/ruflin/elastica/lib/Elastica/Multi/ResultSet.php', + 'Elastica\\Multi\\Search' => $vendorDir . '/ruflin/elastica/lib/Elastica/Multi/Search.php', + 'Elastica\\Node' => $vendorDir . '/ruflin/elastica/lib/Elastica/Node.php', + 'Elastica\\Node\\Info' => $vendorDir . '/ruflin/elastica/lib/Elastica/Node/Info.php', + 'Elastica\\Node\\Stats' => $vendorDir . '/ruflin/elastica/lib/Elastica/Node/Stats.php', + 'Elastica\\Param' => $vendorDir . '/ruflin/elastica/lib/Elastica/Param.php', + 'Elastica\\Percolator' => $vendorDir . '/ruflin/elastica/lib/Elastica/Percolator.php', + 'Elastica\\Query' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query.php', + 'Elastica\\Query\\AbstractQuery' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/AbstractQuery.php', + 'Elastica\\Query\\Bool' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/Bool.php', + 'Elastica\\Query\\Boosting' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/Boosting.php', + 'Elastica\\Query\\Builder' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/Builder.php', + 'Elastica\\Query\\Common' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/Common.php', + 'Elastica\\Query\\ConstantScore' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/ConstantScore.php', + 'Elastica\\Query\\DisMax' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/DisMax.php', + 'Elastica\\Query\\Filtered' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/Filtered.php', + 'Elastica\\Query\\FunctionScore' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/FunctionScore.php', + 'Elastica\\Query\\Fuzzy' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/Fuzzy.php', + 'Elastica\\Query\\FuzzyLikeThis' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/FuzzyLikeThis.php', + 'Elastica\\Query\\HasChild' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/HasChild.php', + 'Elastica\\Query\\HasParent' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/HasParent.php', + 'Elastica\\Query\\Ids' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/Ids.php', + 'Elastica\\Query\\Match' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/Match.php', + 'Elastica\\Query\\MatchAll' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/MatchAll.php', + 'Elastica\\Query\\MoreLikeThis' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/MoreLikeThis.php', + 'Elastica\\Query\\MultiMatch' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/MultiMatch.php', + 'Elastica\\Query\\Nested' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/Nested.php', + 'Elastica\\Query\\Prefix' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/Prefix.php', + 'Elastica\\Query\\QueryString' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/QueryString.php', + 'Elastica\\Query\\Range' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/Range.php', + 'Elastica\\Query\\Simple' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/Simple.php', + 'Elastica\\Query\\SimpleQueryString' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/SimpleQueryString.php', + 'Elastica\\Query\\Term' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/Term.php', + 'Elastica\\Query\\Terms' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/Terms.php', + 'Elastica\\Query\\TopChildren' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/TopChildren.php', + 'Elastica\\Query\\Wildcard' => $vendorDir . '/ruflin/elastica/lib/Elastica/Query/Wildcard.php', + 'Elastica\\Request' => $vendorDir . '/ruflin/elastica/lib/Elastica/Request.php', + 'Elastica\\Rescore\\AbstractRescore' => $vendorDir . '/ruflin/elastica/lib/Elastica/Rescore/AbstractRescore.php', + 'Elastica\\Rescore\\Query' => $vendorDir . '/ruflin/elastica/lib/Elastica/Rescore/Query.php', + 'Elastica\\Response' => $vendorDir . '/ruflin/elastica/lib/Elastica/Response.php', + 'Elastica\\Result' => $vendorDir . '/ruflin/elastica/lib/Elastica/Result.php', + 'Elastica\\ResultSet' => $vendorDir . '/ruflin/elastica/lib/Elastica/ResultSet.php', + 'Elastica\\ScanAndScroll' => $vendorDir . '/ruflin/elastica/lib/Elastica/ScanAndScroll.php', + 'Elastica\\Script' => $vendorDir . '/ruflin/elastica/lib/Elastica/Script.php', + 'Elastica\\ScriptFields' => $vendorDir . '/ruflin/elastica/lib/Elastica/ScriptFields.php', + 'Elastica\\Search' => $vendorDir . '/ruflin/elastica/lib/Elastica/Search.php', + 'Elastica\\SearchableInterface' => $vendorDir . '/ruflin/elastica/lib/Elastica/SearchableInterface.php', + 'Elastica\\Snapshot' => $vendorDir . '/ruflin/elastica/lib/Elastica/Snapshot.php', + 'Elastica\\Status' => $vendorDir . '/ruflin/elastica/lib/Elastica/Status.php', + 'Elastica\\Suggest' => $vendorDir . '/ruflin/elastica/lib/Elastica/Suggest.php', + 'Elastica\\Suggest\\AbstractSuggest' => $vendorDir . '/ruflin/elastica/lib/Elastica/Suggest/AbstractSuggest.php', + 'Elastica\\Suggest\\CandidateGenerator\\AbstractCandidateGenerator' => $vendorDir . '/ruflin/elastica/lib/Elastica/Suggest/CandidateGenerator/AbstractCandidateGenerator.php', + 'Elastica\\Suggest\\CandidateGenerator\\DirectGenerator' => $vendorDir . '/ruflin/elastica/lib/Elastica/Suggest/CandidateGenerator/DirectGenerator.php', + 'Elastica\\Suggest\\Phrase' => $vendorDir . '/ruflin/elastica/lib/Elastica/Suggest/Phrase.php', + 'Elastica\\Suggest\\Term' => $vendorDir . '/ruflin/elastica/lib/Elastica/Suggest/Term.php', + 'Elastica\\Test\\Base' => $vendorDir . '/ruflin/elastica/test/lib/Elastica/Test/Base.php', + 'Elastica\\Test\\Filter\\ExistsTest' => $vendorDir . '/ruflin/elastica/test/lib/Elastica/Test/Filter/ExistsTests.php', + 'Elastica\\Transport\\AbstractTransport' => $vendorDir . '/ruflin/elastica/lib/Elastica/Transport/AbstractTransport.php', + 'Elastica\\Transport\\Guzzle' => $vendorDir . '/ruflin/elastica/lib/Elastica/Transport/Guzzle.php', + 'Elastica\\Transport\\Http' => $vendorDir . '/ruflin/elastica/lib/Elastica/Transport/Http.php', + 'Elastica\\Transport\\Https' => $vendorDir . '/ruflin/elastica/lib/Elastica/Transport/Https.php', + 'Elastica\\Transport\\Memcache' => $vendorDir . '/ruflin/elastica/lib/Elastica/Transport/Memcache.php', + 'Elastica\\Transport\\Null' => $vendorDir . '/ruflin/elastica/lib/Elastica/Transport/Null.php', + 'Elastica\\Transport\\Thrift' => $vendorDir . '/ruflin/elastica/lib/Elastica/Transport/Thrift.php', + 'Elastica\\Type' => $vendorDir . '/ruflin/elastica/lib/Elastica/Type.php', + 'Elastica\\Type\\AbstractType' => $vendorDir . '/ruflin/elastica/lib/Elastica/Type/AbstractType.php', + 'Elastica\\Type\\Mapping' => $vendorDir . '/ruflin/elastica/lib/Elastica/Type/Mapping.php', + 'Elastica\\Util' => $vendorDir . '/ruflin/elastica/lib/Elastica/Util.php', 'LCRun3' => $vendorDir . '/zordius/lightncandy/src/lightncandy.php', 'LightnCandy' => $vendorDir . '/zordius/lightncandy/src/lightncandy.php', 'Liuggio\\StatsdClient\\Entity\\StatsdData' => $vendorDir . '/liuggio/statsd-php-client/src/Liuggio/StatsdClient/Entity/StatsdData.php', @@ -32,6 +208,84 @@ return array( 'Liuggio\\StatsdClient\\Sender\\SysLogSender' => $vendorDir . '/liuggio/statsd-php-client/src/Liuggio/StatsdClient/Sender/SysLogSender.php', 'Liuggio\\StatsdClient\\StatsdClient' => $vendorDir . '/liuggio/statsd-php-client/src/Liuggio/StatsdClient/StatsdClient.php', 'Liuggio\\StatsdClient\\StatsdClientInterface' => $vendorDir . '/liuggio/statsd-php-client/src/Liuggio/StatsdClient/StatsdClientInterface.php', + 'Monolog\\ErrorHandler' => $vendorDir . '/monolog/monolog/src/Monolog/ErrorHandler.php', + 'Monolog\\Formatter\\ChromePHPFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php', + 'Monolog\\Formatter\\ElasticaFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php', + 'Monolog\\Formatter\\FlowdockFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php', + 'Monolog\\Formatter\\FormatterInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php', + 'Monolog\\Formatter\\GelfMessageFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php', + 'Monolog\\Formatter\\HtmlFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php', + 'Monolog\\Formatter\\JsonFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php', + 'Monolog\\Formatter\\LineFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LineFormatter.php', + 'Monolog\\Formatter\\LogglyFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php', + 'Monolog\\Formatter\\LogstashFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php', + 'Monolog\\Formatter\\MongoDBFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php', + 'Monolog\\Formatter\\NormalizerFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php', + 'Monolog\\Formatter\\ScalarFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php', + 'Monolog\\Formatter\\WildfireFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php', + 'Monolog\\Handler\\AbstractHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractHandler.php', + 'Monolog\\Handler\\AbstractProcessingHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php', + 'Monolog\\Handler\\AbstractSyslogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php', + 'Monolog\\Handler\\AmqpHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AmqpHandler.php', + 'Monolog\\Handler\\BrowserConsoleHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php', + 'Monolog\\Handler\\BufferHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/BufferHandler.php', + 'Monolog\\Handler\\ChromePHPHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php', + 'Monolog\\Handler\\CouchDBHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php', + 'Monolog\\Handler\\CubeHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/CubeHandler.php', + 'Monolog\\Handler\\DoctrineCouchDBHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php', + 'Monolog\\Handler\\DynamoDbHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php', + 'Monolog\\Handler\\ElasticSearchHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php', + 'Monolog\\Handler\\ErrorLogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php', + 'Monolog\\Handler\\FilterHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FilterHandler.php', + 'Monolog\\Handler\\FingersCrossedHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php', + 'Monolog\\Handler\\FingersCrossed\\ActivationStrategyInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php', + 'Monolog\\Handler\\FingersCrossed\\ChannelLevelActivationStrategy' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php', + 'Monolog\\Handler\\FingersCrossed\\ErrorLevelActivationStrategy' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php', + 'Monolog\\Handler\\FirePHPHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php', + 'Monolog\\Handler\\FleepHookHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php', + 'Monolog\\Handler\\FlowdockHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php', + 'Monolog\\Handler\\GelfHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/GelfHandler.php', + 'Monolog\\Handler\\GroupHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/GroupHandler.php', + 'Monolog\\Handler\\HandlerInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/HandlerInterface.php', + 'Monolog\\Handler\\HipChatHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/HipChatHandler.php', + 'Monolog\\Handler\\LogEntriesHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php', + 'Monolog\\Handler\\LogglyHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/LogglyHandler.php', + 'Monolog\\Handler\\MailHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MailHandler.php', + 'Monolog\\Handler\\MandrillHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MandrillHandler.php', + 'Monolog\\Handler\\MissingExtensionException' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php', + 'Monolog\\Handler\\MongoDBHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php', + 'Monolog\\Handler\\NativeMailerHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php', + 'Monolog\\Handler\\NewRelicHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php', + 'Monolog\\Handler\\NullHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NullHandler.php', + 'Monolog\\Handler\\PsrHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/PsrHandler.php', + 'Monolog\\Handler\\PushoverHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/PushoverHandler.php', + 'Monolog\\Handler\\RavenHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RavenHandler.php', + 'Monolog\\Handler\\RedisHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RedisHandler.php', + 'Monolog\\Handler\\RollbarHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RollbarHandler.php', + 'Monolog\\Handler\\RotatingFileHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php', + 'Monolog\\Handler\\SamplingHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SamplingHandler.php', + 'Monolog\\Handler\\SlackHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SlackHandler.php', + 'Monolog\\Handler\\SocketHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SocketHandler.php', + 'Monolog\\Handler\\StreamHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/StreamHandler.php', + 'Monolog\\Handler\\SwiftMailerHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php', + 'Monolog\\Handler\\SyslogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogHandler.php', + 'Monolog\\Handler\\SyslogUdpHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php', + 'Monolog\\Handler\\SyslogUdp\\UdpSocket' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php', + 'Monolog\\Handler\\TestHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/TestHandler.php', + 'Monolog\\Handler\\WhatFailureGroupHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php', + 'Monolog\\Handler\\ZendMonitorHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php', + 'Monolog\\Logger' => $vendorDir . '/monolog/monolog/src/Monolog/Logger.php', + 'Monolog\\Processor\\GitProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/GitProcessor.php', + 'Monolog\\Processor\\IntrospectionProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php', + 'Monolog\\Processor\\MemoryPeakUsageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php', + 'Monolog\\Processor\\MemoryProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php', + 'Monolog\\Processor\\MemoryUsageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php', + 'Monolog\\Processor\\ProcessIdProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php', + 'Monolog\\Processor\\PsrLogMessageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php', + 'Monolog\\Processor\\TagProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/TagProcessor.php', + 'Monolog\\Processor\\UidProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/UidProcessor.php', + 'Monolog\\Processor\\WebProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/WebProcessor.php', + 'Monolog\\Registry' => $vendorDir . '/monolog/monolog/src/Monolog/Registry.php', 'OOUI\\ApexTheme' => $vendorDir . '/oojs/oojs-ui/php/themes/ApexTheme.php', 'OOUI\\ButtonElement' => $vendorDir . '/oojs/oojs-ui/php/elements/ButtonElement.php', 'OOUI\\ButtonGroupWidget' => $vendorDir . '/oojs/oojs-ui/php/widgets/ButtonGroupWidget.php', @@ -69,9 +323,7 @@ return array( 'Psr\\Log\\InvalidArgumentException' => $vendorDir . '/psr/log/Psr/Log/InvalidArgumentException.php', 'Psr\\Log\\LogLevel' => $vendorDir . '/psr/log/Psr/Log/LogLevel.php', 'Psr\\Log\\LoggerAwareInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerAwareInterface.php', - 'Psr\\Log\\LoggerAwareTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerAwareTrait.php', 'Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerInterface.php', - 'Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerTrait.php', 'Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/Psr/Log/NullLogger.php', 'UtfNormal\\Constants' => $vendorDir . '/wikimedia/utfnormal/src/Constants.php', 'UtfNormal\\Utils' => $vendorDir . '/wikimedia/utfnormal/src/Util.php', diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php index a0f180fa..fd316bf5 100644 --- a/vendor/composer/autoload_namespaces.php +++ b/vendor/composer/autoload_namespaces.php @@ -3,11 +3,12 @@ // autoload_namespaces.php @generated by Composer $vendorDir = dirname(dirname(__FILE__)); -$baseDir = dirname($vendorDir); +$baseDir = $vendorDir; return array( 'Psr\\Log\\' => array($vendorDir . '/psr/log'), 'Liuggio' => array($vendorDir . '/liuggio/statsd-php-client/src'), - 'ComposerHookHandler' => array($baseDir . '/includes/composer'), + 'Elastica\\Test' => array($vendorDir . '/ruflin/elastica/test/lib'), + 'Elastica' => array($vendorDir . '/ruflin/elastica/lib'), '' => array($vendorDir . '/cssjanus/cssjanus/src'), ); diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 74a09133..abd6ba84 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -3,8 +3,9 @@ // autoload_psr4.php @generated by Composer $vendorDir = dirname(dirname(__FILE__)); -$baseDir = dirname($vendorDir); +$baseDir = $vendorDir; return array( 'Wikimedia\\Composer\\' => array($vendorDir . '/wikimedia/composer-merge-plugin/src'), + 'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'), ); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 3e640297..10158fed 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit9b10cc5cf6896d6e4a31983fc3498786 +class ComposerAutoloaderInit_mediawiki_vendor { private static $loader; @@ -19,9 +19,9 @@ class ComposerAutoloaderInit9b10cc5cf6896d6e4a31983fc3498786 return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit9b10cc5cf6896d6e4a31983fc3498786', 'loadClassLoader'), true, false); + spl_autoload_register(array('ComposerAutoloaderInit_mediawiki_vendor', 'loadClassLoader'), true, false); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInit9b10cc5cf6896d6e4a31983fc3498786', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit_mediawiki_vendor', 'loadClassLoader')); $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { @@ -38,13 +38,14 @@ class ComposerAutoloaderInit9b10cc5cf6896d6e4a31983fc3498786 $loader->addClassMap($classMap); } + $loader->setClassMapAuthoritative(true); $loader->register(false); return $loader; } } -function composerRequire9b10cc5cf6896d6e4a31983fc3498786($file) +function composerRequire_mediawiki_vendor($file) { require $file; } diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index e882cda4..20564c68 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1,46 +1,104 @@ [ { - "name": "wikimedia/composer-merge-plugin", - "version": "v1.0.0", + "name": "psr/log", + "version": "1.0.0", "version_normalized": "1.0.0.0", "source": { "type": "git", - "url": "https://github.com/wikimedia/composer-merge-plugin.git", - "reference": "ed426b785f9f786b33be4fd78584e43f4e962356" + "url": "https://github.com/php-fig/log.git", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wikimedia/composer-merge-plugin/zipball/ed426b785f9f786b33be4fd78584e43f4e962356", - "reference": "ed426b785f9f786b33be4fd78584e43f4e962356", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "shasum": "" + }, + "time": "2012-12-21 11:40:51", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "Psr\\Log\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "keywords": [ + "log", + "psr", + "psr-3" + ] + }, + { + "name": "ruflin/elastica", + "version": "v1.3.0.0", + "version_normalized": "1.3.0.0", + "source": { + "type": "git", + "url": "https://github.com/ruflin/Elastica.git", + "reference": "92155a36c94ebe15b09661ae804acbe4bdd4ad6b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ruflin/Elastica/zipball/92155a36c94ebe15b09661ae804acbe4bdd4ad6b", + "reference": "92155a36c94ebe15b09661ae804acbe4bdd4ad6b", "shasum": "" }, "require": { - "composer-plugin-api": "1.0.0", - "php": ">=5.3.2" + "php": ">=5.3.3" }, "require-dev": { - "composer/composer": "1.0.*@dev", - "jakub-onderka/php-parallel-lint": "~0.8", - "phpspec/prophecy-phpunit": "~1.0", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.1.0" + "munkie/elasticsearch-thrift-php": "1.4.*", + "phpunit/phpunit": "4.1.*", + "psr/log": "~1.0", + "satooshi/php-coveralls": "dev-master" }, - "time": "2015-02-21 00:57:13", - "type": "composer-plugin", + "suggest": { + "guzzlehttp/guzzle": "Allow using guzzle 4.x as the http transport (requires php 5.4)", + "monolog/monolog": "Logging request", + "munkie/elasticsearch-thrift-php": "Allow using thrift transport", + "psr/log": "for logging" + }, + "time": "2014-07-27 13:45:09", + "type": "library", "extra": { - "class": "Wikimedia\\Composer\\MergePlugin" + "branch-alias": { + "dev-master": "1.2.x-dev" + } }, "installation-source": "dist", "autoload": { - "psr-4": { - "Wikimedia\\Composer\\": "src/" + "psr-0": { + "Elastica": "lib/", + "Elastica\\Test": "test/lib/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "Apache 2.0" ], - "description": "Composer plugin to merge multiple composer.json files" + "authors": [ + { + "name": "Nicolas Ruflin", + "homepage": "http://ruflin.com/" + } + ], + "description": "Elasticsearch Client", + "homepage": "http://elastica.io/", + "keywords": [ + "client", + "search" + ] }, { "name": "cssjanus/cssjanus", @@ -123,115 +181,153 @@ "homepage": "http://leafo.net/lessphp/" }, { - "name": "liuggio/statsd-php-client", - "version": "v1.0.12", - "version_normalized": "1.0.12.0", + "name": "wikimedia/cdb", + "version": "1.0.1", + "version_normalized": "1.0.1.0", "source": { "type": "git", - "url": "https://github.com/liuggio/statsd-php-client.git", - "reference": "a8c9ccd2a3af6cc49c7fc4f5f689d7b148ab19d7" + "url": "https://github.com/wikimedia/cdb.git", + "reference": "3b7d5366c88eccf2517ebac57c59eb557c82f46c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/liuggio/statsd-php-client/zipball/a8c9ccd2a3af6cc49c7fc4f5f689d7b148ab19d7", - "reference": "a8c9ccd2a3af6cc49c7fc4f5f689d7b148ab19d7", + "url": "https://api.github.com/repos/wikimedia/cdb/zipball/3b7d5366c88eccf2517ebac57c59eb557c82f46c", + "reference": "3b7d5366c88eccf2517ebac57c59eb557c82f46c", "shasum": "" }, "require": { - "php": ">=5.2" + "php": ">=5.3.2" }, "require-dev": { - "monolog/monolog": ">=1.2.0" - }, - "suggest": { - "monolog/monolog": "Monolog, in order to do generate statistic from log >=1.2.0)" + "phpunit/phpunit": "*" }, - "time": "2014-09-17 21:37:49", + "time": "2014-12-08 19:26:44", "type": "library", "installation-source": "dist", "autoload": { - "psr-0": { - "Liuggio": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "GPL-2.0" ], "authors": [ { - "name": "Giulio De Donato", - "email": "liuggio@gmail.com" + "name": "Tim Starling", + "email": "tstarling@wikimedia.org" + }, + { + "name": "Chad Horohoe", + "email": "chad@wikimedia.org" } ], - "description": "Statsd (Object Oriented) client library for PHP", - "homepage": "https://github.com/liuggio/statsd-php-client/", - "keywords": [ - "etsy", - "monitoring", - "php", - "statsd" - ] + "description": "Constant Database (CDB) wrapper library for PHP. Provides pure-PHP fallback when dba_* functions are absent.", + "homepage": "https://www.mediawiki.org/wiki/CDB" }, { - "name": "oojs/oojs-ui", - "version": "v0.11.3", - "version_normalized": "0.11.3.0", + "name": "zordius/lightncandy", + "version": "v0.18", + "version_normalized": "0.18.0.0", "source": { "type": "git", - "url": "https://github.com/wikimedia/oojs-ui.git", - "reference": "a03de5681e28e4fad1e27f8cccab32a2c5b484e5" + "url": "https://github.com/zordius/lightncandy.git", + "reference": "24be6909c37391f4648ce1fdf19036b11bd56d05" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wikimedia/oojs-ui/zipball/a03de5681e28e4fad1e27f8cccab32a2c5b484e5", - "reference": "a03de5681e28e4fad1e27f8cccab32a2c5b484e5", + "url": "https://api.github.com/repos/zordius/lightncandy/zipball/24be6909c37391f4648ce1fdf19036b11bd56d05", + "reference": "24be6909c37391f4648ce1fdf19036b11bd56d05", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.0" }, "require-dev": { - "jakub-onderka/php-parallel-lint": "0.8.*", - "mediawiki/mediawiki-codesniffer": "0.1.0", - "squizlabs/php_codesniffer": "2.1.*" + "phpunit/phpunit": "4.0.17" }, - "time": "2015-05-12 11:58:55", + "time": "2015-01-01 04:37:19", "type": "library", "installation-source": "dist", "autoload": { "classmap": [ - "php/" + "src/lightncandy.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Provides library of common widgets, layouts, and windows.", - "homepage": "https://www.mediawiki.org/wiki/OOjs_UI" + "authors": [ + { + "name": "Zordius Chen", + "email": "zordius@yahoo-inc.com" + } + ], + "description": "An extremely fast PHP implementation of handlebars ( http://handlebarsjs.com/ ) and mustache ( http://mustache.github.io/ ).", + "homepage": "https://github.com/zordius/lightncandy", + "keywords": [ + "handlebars", + "logicless", + "mustache", + "php", + "template" + ] }, { - "name": "psr/log", - "version": "1.0.0", - "version_normalized": "1.0.0.0", + "name": "monolog/monolog", + "version": "1.12.0", + "version_normalized": "1.12.0.0", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + "url": "https://github.com/Seldaek/monolog.git", + "reference": "1fbe8c2641f2b163addf49cc5e18f144bec6b19f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1fbe8c2641f2b163addf49cc5e18f144bec6b19f", + "reference": "1fbe8c2641f2b163addf49cc5e18f144bec6b19f", "shasum": "" }, - "time": "2012-12-21 11:40:51", + "require": { + "php": ">=5.3.0", + "psr/log": "~1.0" + }, + "provide": { + "psr/log-implementation": "1.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "~2.4, >2.4.8", + "doctrine/couchdb": "~1.0@dev", + "graylog2/gelf-php": "~1.0", + "phpunit/phpunit": "~4.0", + "raven/raven": "~0.5", + "ruflin/elastica": "0.90.*", + "videlalvaro/php-amqplib": "~2.4" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-mongo": "Allow sending log messages to a MongoDB server", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "raven/raven": "Allow sending log messages to a Sentry server", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server", + "videlalvaro/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib" + }, + "time": "2014-12-29 21:29:35", "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12.x-dev" + } + }, "installation-source": "dist", "autoload": { - "psr-0": { - "Psr\\Log\\": "" + "psr-4": { + "Monolog\\": "src/Monolog" } }, "notification-url": "https://packagist.org/downloads/", @@ -240,62 +336,112 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" } ], - "description": "Common interface for logging libraries", + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "http://github.com/Seldaek/monolog", "keywords": [ "log", - "psr", + "logging", "psr-3" ] }, { - "name": "wikimedia/cdb", - "version": "1.0.1", - "version_normalized": "1.0.1.0", + "name": "wikimedia/composer-merge-plugin", + "version": "v1.0.0", + "version_normalized": "1.0.0.0", "source": { "type": "git", - "url": "https://github.com/wikimedia/cdb.git", - "reference": "3b7d5366c88eccf2517ebac57c59eb557c82f46c" + "url": "https://github.com/wikimedia/composer-merge-plugin.git", + "reference": "ed426b785f9f786b33be4fd78584e43f4e962356" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wikimedia/cdb/zipball/3b7d5366c88eccf2517ebac57c59eb557c82f46c", - "reference": "3b7d5366c88eccf2517ebac57c59eb557c82f46c", + "url": "https://api.github.com/repos/wikimedia/composer-merge-plugin/zipball/ed426b785f9f786b33be4fd78584e43f4e962356", + "reference": "ed426b785f9f786b33be4fd78584e43f4e962356", "shasum": "" }, "require": { + "composer-plugin-api": "1.0.0", "php": ">=5.3.2" }, "require-dev": { - "phpunit/phpunit": "*" + "composer/composer": "1.0.*@dev", + "jakub-onderka/php-parallel-lint": "~0.8", + "phpspec/prophecy-phpunit": "~1.0", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.1.0" }, - "time": "2014-12-08 19:26:44", + "time": "2015-02-21 00:57:13", + "type": "composer-plugin", + "extra": { + "class": "Wikimedia\\Composer\\MergePlugin" + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Wikimedia\\Composer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Composer plugin to merge multiple composer.json files" + }, + { + "name": "liuggio/statsd-php-client", + "version": "v1.0.12", + "version_normalized": "1.0.12.0", + "source": { + "type": "git", + "url": "https://github.com/liuggio/statsd-php-client.git", + "reference": "a8c9ccd2a3af6cc49c7fc4f5f689d7b148ab19d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/liuggio/statsd-php-client/zipball/a8c9ccd2a3af6cc49c7fc4f5f689d7b148ab19d7", + "reference": "a8c9ccd2a3af6cc49c7fc4f5f689d7b148ab19d7", + "shasum": "" + }, + "require": { + "php": ">=5.2" + }, + "require-dev": { + "monolog/monolog": ">=1.2.0" + }, + "suggest": { + "monolog/monolog": "Monolog, in order to do generate statistic from log >=1.2.0)" + }, + "time": "2014-09-17 21:37:49", "type": "library", "installation-source": "dist", "autoload": { - "classmap": [ - "src/" - ] + "psr-0": { + "Liuggio": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "GPL-2.0" + "MIT" ], "authors": [ { - "name": "Tim Starling", - "email": "tstarling@wikimedia.org" - }, - { - "name": "Chad Horohoe", - "email": "chad@wikimedia.org" + "name": "Giulio De Donato", + "email": "liuggio@gmail.com" } ], - "description": "Constant Database (CDB) wrapper library for PHP. Provides pure-PHP fallback when dba_* functions are absent.", - "homepage": "https://www.mediawiki.org/wiki/CDB" + "description": "Statsd (Object Oriented) client library for PHP", + "homepage": "https://github.com/liuggio/statsd-php-client/", + "keywords": [ + "etsy", + "monitoring", + "php", + "statsd" + ] }, { "name": "wikimedia/utfnormal", @@ -343,52 +489,41 @@ "homepage": "https://www.mediawiki.org/wiki/utfnormal" }, { - "name": "zordius/lightncandy", - "version": "v0.18", - "version_normalized": "0.18.0.0", + "name": "oojs/oojs-ui", + "version": "v0.11.3", + "version_normalized": "0.11.3.0", "source": { "type": "git", - "url": "https://github.com/zordius/lightncandy.git", - "reference": "24be6909c37391f4648ce1fdf19036b11bd56d05" + "url": "https://github.com/wikimedia/oojs-ui.git", + "reference": "a03de5681e28e4fad1e27f8cccab32a2c5b484e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zordius/lightncandy/zipball/24be6909c37391f4648ce1fdf19036b11bd56d05", - "reference": "24be6909c37391f4648ce1fdf19036b11bd56d05", + "url": "https://api.github.com/repos/wikimedia/oojs-ui/zipball/a03de5681e28e4fad1e27f8cccab32a2c5b484e5", + "reference": "a03de5681e28e4fad1e27f8cccab32a2c5b484e5", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=5.3.3" }, "require-dev": { - "phpunit/phpunit": "4.0.17" + "jakub-onderka/php-parallel-lint": "0.8.*", + "mediawiki/mediawiki-codesniffer": "0.1.0", + "squizlabs/php_codesniffer": "2.1.*" }, - "time": "2015-01-01 04:37:19", + "time": "2015-05-12 11:58:55", "type": "library", "installation-source": "dist", "autoload": { "classmap": [ - "src/lightncandy.php" + "php/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Zordius Chen", - "email": "zordius@yahoo-inc.com" - } - ], - "description": "An extremely fast PHP implementation of handlebars ( http://handlebarsjs.com/ ) and mustache ( http://mustache.github.io/ ).", - "homepage": "https://github.com/zordius/lightncandy", - "keywords": [ - "handlebars", - "logicless", - "mustache", - "php", - "template" - ] + "description": "Provides library of common widgets, layouts, and windows.", + "homepage": "https://www.mediawiki.org/wiki/OOjs_UI" } ] diff --git a/vendor/monolog/monolog/CHANGELOG.mdown b/vendor/monolog/monolog/CHANGELOG.mdown new file mode 100644 index 00000000..47042c73 --- /dev/null +++ b/vendor/monolog/monolog/CHANGELOG.mdown @@ -0,0 +1,202 @@ +### 1.12.0 (2014-12-29) + + * Break: HandlerInterface::isHandling now receives a partial record containing only a level key. This was always the intent and does not break any Monolog handler but is strictly speaking a BC break and you should check if you relied on any other field in your own handlers. + * Added PsrHandler to forward records to another PSR-3 logger + * Added SamplingHandler to wrap around a handler and include only every Nth record + * Added MongoDBFormatter to support better storage with MongoDBHandler (it must be enabled manually for now) + * Added exception codes in the output of most formatters + * Added LineFormatter::includeStacktraces to enable exception stack traces in logs (uses more than one line) + * Added $useShortAttachment to SlackHandler to minify attachment size and $includeExtra to append extra data + * Added $host to HipChatHandler for users of private instances + * Added $transactionName to NewRelicHandler and support for a transaction_name context value + * Fixed MandrillHandler to avoid outputing API call responses + * Fixed some non-standard behaviors in SyslogUdpHandler + +### 1.11.0 (2014-09-30) + + * Break: The NewRelicHandler extra and context data are now prefixed with extra_ and context_ to avoid clashes. Watch out if you have scripts reading those from the API and rely on names + * Added WhatFailureGroupHandler to suppress any exception coming from the wrapped handlers and avoid chain failures if a logging service fails + * Added MandrillHandler to send emails via the Mandrillapp.com API + * Added SlackHandler to log records to a Slack.com account + * Added FleepHookHandler to log records to a Fleep.io account + * Added LogglyHandler::addTag to allow adding tags to an existing handler + * Added $ignoreEmptyContextAndExtra to LineFormatter to avoid empty [] at the end + * Added $useLocking to StreamHandler and RotatingFileHandler to enable flock() while writing + * Added support for PhpAmqpLib in the AmqpHandler + * Added FingersCrossedHandler::clear and BufferHandler::clear to reset them between batches in long running jobs + * Added support for adding extra fields from $_SERVER in the WebProcessor + * Fixed support for non-string values in PrsLogMessageProcessor + * Fixed SwiftMailer messages being sent with the wrong date in long running scripts + * Fixed minor PHP 5.6 compatibility issues + * Fixed BufferHandler::close being called twice + +### 1.10.0 (2014-06-04) + + * Added Logger::getHandlers() and Logger::getProcessors() methods + * Added $passthruLevel argument to FingersCrossedHandler to let it always pass some records through even if the trigger level is not reached + * Added support for extra data in NewRelicHandler + * Added $expandNewlines flag to the ErrorLogHandler to create multiple log entries when a message has multiple lines + +### 1.9.1 (2014-04-24) + + * Fixed regression in RotatingFileHandler file permissions + * Fixed initialization of the BufferHandler to make sure it gets flushed after receiving records + * Fixed ChromePHPHandler and FirePHPHandler's activation strategies to be more conservative + +### 1.9.0 (2014-04-20) + + * Added LogEntriesHandler to send logs to a LogEntries account + * Added $filePermissions to tweak file mode on StreamHandler and RotatingFileHandler + * Added $useFormatting flag to MemoryProcessor to make it send raw data in bytes + * Added support for table formatting in FirePHPHandler via the table context key + * Added a TagProcessor to add tags to records, and support for tags in RavenHandler + * Added $appendNewline flag to the JsonFormatter to enable using it when logging to files + * Added sound support to the PushoverHandler + * Fixed multi-threading support in StreamHandler + * Fixed empty headers issue when ChromePHPHandler received no records + * Fixed default format of the ErrorLogHandler + +### 1.8.0 (2014-03-23) + + * Break: the LineFormatter now strips newlines by default because this was a bug, set $allowInlineLineBreaks to true if you need them + * Added BrowserConsoleHandler to send logs to any browser's console via console.log() injection in the output + * Added FilterHandler to filter records and only allow those of a given list of levels through to the wrapped handler + * Added FlowdockHandler to send logs to a Flowdock account + * Added RollbarHandler to send logs to a Rollbar account + * Added HtmlFormatter to send prettier log emails with colors for each log level + * Added GitProcessor to add the current branch/commit to extra record data + * Added a Monolog\Registry class to allow easier global access to pre-configured loggers + * Added support for the new official graylog2/gelf-php lib for GelfHandler, upgrade if you can by replacing the mlehner/gelf-php requirement + * Added support for HHVM + * Added support for Loggly batch uploads + * Added support for tweaking the content type and encoding in NativeMailerHandler + * Added $skipClassesPartials to tweak the ignored classes in the IntrospectionProcessor + * Fixed batch request support in GelfHandler + +### 1.7.0 (2013-11-14) + + * Added ElasticSearchHandler to send logs to an Elastic Search server + * Added DynamoDbHandler and ScalarFormatter to send logs to Amazon's Dynamo DB + * Added SyslogUdpHandler to send logs to a remote syslogd server + * Added LogglyHandler to send logs to a Loggly account + * Added $level to IntrospectionProcessor so it only adds backtraces when needed + * Added $version to LogstashFormatter to allow using the new v1 Logstash format + * Added $appName to NewRelicHandler + * Added configuration of Pushover notification retries/expiry + * Added $maxColumnWidth to NativeMailerHandler to change the 70 chars default + * Added chainability to most setters for all handlers + * Fixed RavenHandler batch processing so it takes the message from the record with highest priority + * Fixed HipChatHandler batch processing so it sends all messages at once + * Fixed issues with eAccelerator + * Fixed and improved many small things + +### 1.6.0 (2013-07-29) + + * Added HipChatHandler to send logs to a HipChat chat room + * Added ErrorLogHandler to send logs to PHP's error_log function + * Added NewRelicHandler to send logs to NewRelic's service + * Added Monolog\ErrorHandler helper class to register a Logger as exception/error/fatal handler + * Added ChannelLevelActivationStrategy for the FingersCrossedHandler to customize levels by channel + * Added stack traces output when normalizing exceptions (json output & co) + * Added Monolog\Logger::API constant (currently 1) + * Added support for ChromePHP's v4.0 extension + * Added support for message priorities in PushoverHandler, see $highPriorityLevel and $emergencyLevel + * Added support for sending messages to multiple users at once with the PushoverHandler + * Fixed RavenHandler's support for batch sending of messages (when behind a Buffer or FingersCrossedHandler) + * Fixed normalization of Traversables with very large data sets, only the first 1000 items are shown now + * Fixed issue in RotatingFileHandler when an open_basedir restriction is active + * Fixed minor issues in RavenHandler and bumped the API to Raven 0.5.0 + * Fixed SyslogHandler issue when many were used concurrently with different facilities + +### 1.5.0 (2013-04-23) + + * Added ProcessIdProcessor to inject the PID in log records + * Added UidProcessor to inject a unique identifier to all log records of one request/run + * Added support for previous exceptions in the LineFormatter exception serialization + * Added Monolog\Logger::getLevels() to get all available levels + * Fixed ChromePHPHandler so it avoids sending headers larger than Chrome can handle + +### 1.4.1 (2013-04-01) + + * Fixed exception formatting in the LineFormatter to be more minimalistic + * Fixed RavenHandler's handling of context/extra data, requires Raven client >0.1.0 + * Fixed log rotation in RotatingFileHandler to work with long running scripts spanning multiple days + * Fixed WebProcessor array access so it checks for data presence + * Fixed Buffer, Group and FingersCrossed handlers to make use of their processors + +### 1.4.0 (2013-02-13) + + * Added RedisHandler to log to Redis via the Predis library or the phpredis extension + * Added ZendMonitorHandler to log to the Zend Server monitor + * Added the possibility to pass arrays of handlers and processors directly in the Logger constructor + * Added `$useSSL` option to the PushoverHandler which is enabled by default + * Fixed ChromePHPHandler and FirePHPHandler issue when multiple instances are used simultaneously + * Fixed header injection capability in the NativeMailHandler + +### 1.3.1 (2013-01-11) + + * Fixed LogstashFormatter to be usable with stream handlers + * Fixed GelfMessageFormatter levels on Windows + +### 1.3.0 (2013-01-08) + + * Added PSR-3 compliance, the `Monolog\Logger` class is now an instance of `Psr\Log\LoggerInterface` + * Added PsrLogMessageProcessor that you can selectively enable for full PSR-3 compliance + * Added LogstashFormatter (combine with SocketHandler or StreamHandler to send logs to Logstash) + * Added PushoverHandler to send mobile notifications + * Added CouchDBHandler and DoctrineCouchDBHandler + * Added RavenHandler to send data to Sentry servers + * Added support for the new MongoClient class in MongoDBHandler + * Added microsecond precision to log records' timestamps + * Added `$flushOnOverflow` param to BufferHandler to flush by batches instead of losing + the oldest entries + * Fixed normalization of objects with cyclic references + +### 1.2.1 (2012-08-29) + + * Added new $logopts arg to SyslogHandler to provide custom openlog options + * Fixed fatal error in SyslogHandler + +### 1.2.0 (2012-08-18) + + * Added AmqpHandler (for use with AMQP servers) + * Added CubeHandler + * Added NativeMailerHandler::addHeader() to send custom headers in mails + * Added the possibility to specify more than one recipient in NativeMailerHandler + * Added the possibility to specify float timeouts in SocketHandler + * Added NOTICE and EMERGENCY levels to conform with RFC 5424 + * Fixed the log records to use the php default timezone instead of UTC + * Fixed BufferHandler not being flushed properly on PHP fatal errors + * Fixed normalization of exotic resource types + * Fixed the default format of the SyslogHandler to avoid duplicating datetimes in syslog + +### 1.1.0 (2012-04-23) + + * Added Monolog\Logger::isHandling() to check if a handler will + handle the given log level + * Added ChromePHPHandler + * Added MongoDBHandler + * Added GelfHandler (for use with Graylog2 servers) + * Added SocketHandler (for use with syslog-ng for example) + * Added NormalizerFormatter + * Added the possibility to change the activation strategy of the FingersCrossedHandler + * Added possibility to show microseconds in logs + * Added `server` and `referer` to WebProcessor output + +### 1.0.2 (2011-10-24) + + * Fixed bug in IE with large response headers and FirePHPHandler + +### 1.0.1 (2011-08-25) + + * Added MemoryPeakUsageProcessor and MemoryUsageProcessor + * Added Monolog\Logger::getName() to get a logger's channel name + +### 1.0.0 (2011-07-06) + + * Added IntrospectionProcessor to get info from where the logger was called + * Fixed WebProcessor in CLI + +### 1.0.0-RC1 (2011-07-01) + + * Initial release diff --git a/vendor/monolog/monolog/LICENSE b/vendor/monolog/monolog/LICENSE new file mode 100644 index 00000000..35727045 --- /dev/null +++ b/vendor/monolog/monolog/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2011-2014 Jordi Boggiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/monolog/monolog/README.mdown b/vendor/monolog/monolog/README.mdown new file mode 100644 index 00000000..add476a8 --- /dev/null +++ b/vendor/monolog/monolog/README.mdown @@ -0,0 +1,283 @@ +Monolog - Logging for PHP 5.3+ [![Build Status](https://secure.travis-ci.org/Seldaek/monolog.png)](http://travis-ci.org/Seldaek/monolog) +============================== + +[![Total Downloads](https://poser.pugx.org/monolog/monolog/downloads.png)](https://packagist.org/packages/monolog/monolog) +[![Latest Stable Version](https://poser.pugx.org/monolog/monolog/v/stable.png)](https://packagist.org/packages/monolog/monolog) +[![Reference Status](https://www.versioneye.com/php/monolog:monolog/reference_badge.svg)](https://www.versioneye.com/php/monolog:monolog/references) + + +Monolog sends your logs to files, sockets, inboxes, databases and various +web services. See the complete list of handlers below. Special handlers +allow you to build advanced logging strategies. + +This library implements the [PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) +interface that you can type-hint against in your own libraries to keep +a maximum of interoperability. You can also use it in your applications to +make sure you can always use another compatible logger at a later time. +As of 1.11.0 Monolog public APIs will also accept PSR-3 log levels. +Internally Monolog still uses its own level scheme since it predates PSR-3. + +Usage +----- + +Install the latest version with `composer require monolog/monolog` + +```php +<?php + +use Monolog\Logger; +use Monolog\Handler\StreamHandler; + +// create a log channel +$log = new Logger('name'); +$log->pushHandler(new StreamHandler('path/to/your.log', Logger::WARNING)); + +// add records to the log +$log->addWarning('Foo'); +$log->addError('Bar'); +``` + +Core Concepts +------------- + +Every `Logger` instance has a channel (name) and a stack of handlers. Whenever +you add a record to the logger, it traverses the handler stack. Each handler +decides whether it fully handled the record, and if so, the propagation of the +record ends there. + +This allows for flexible logging setups, for example having a `StreamHandler` at +the bottom of the stack that will log anything to disk, and on top of that add +a `MailHandler` that will send emails only when an error message is logged. +Handlers also have a `$bubble` property which defines whether they block the +record or not if they handled it. In this example, setting the `MailHandler`'s +`$bubble` argument to false means that records handled by the `MailHandler` will +not propagate to the `StreamHandler` anymore. + +You can create many `Logger`s, each defining a channel (e.g.: db, request, +router, ..) and each of them combining various handlers, which can be shared +or not. The channel is reflected in the logs and allows you to easily see or +filter records. + +Each Handler also has a Formatter, a default one with settings that make sense +will be created if you don't set one. The formatters normalize and format +incoming records so that they can be used by the handlers to output useful +information. + +Custom severity levels are not available. Only the eight +[RFC 5424](http://tools.ietf.org/html/rfc5424) levels (debug, info, notice, +warning, error, critical, alert, emergency) are present for basic filtering +purposes, but for sorting and other use cases that would require +flexibility, you should add Processors to the Logger that can add extra +information (tags, user ip, ..) to the records before they are handled. + +Log Levels +---------- + +Monolog supports the logging levels described by [RFC 5424](http://tools.ietf.org/html/rfc5424). + +- **DEBUG** (100): Detailed debug information. + +- **INFO** (200): Interesting events. Examples: User logs in, SQL logs. + +- **NOTICE** (250): Normal but significant events. + +- **WARNING** (300): Exceptional occurrences that are not errors. Examples: + Use of deprecated APIs, poor use of an API, undesirable things that are not + necessarily wrong. + +- **ERROR** (400): Runtime errors that do not require immediate action but + should typically be logged and monitored. + +- **CRITICAL** (500): Critical conditions. Example: Application component + unavailable, unexpected exception. + +- **ALERT** (550): Action must be taken immediately. Example: Entire website + down, database unavailable, etc. This should trigger the SMS alerts and wake + you up. + +- **EMERGENCY** (600): Emergency: system is unusable. + +Docs +==== + +**See the `doc` directory for more detailed documentation. +The following is only a list of all parts that come with Monolog.** + +Handlers +-------- + +### Log to files and syslog + +- _StreamHandler_: Logs records into any PHP stream, use this for log files. +- _RotatingFileHandler_: Logs records to a file and creates one logfile per day. + It will also delete files older than `$maxFiles`. You should use + [logrotate](http://linuxcommand.org/man_pages/logrotate8.html) for high profile + setups though, this is just meant as a quick and dirty solution. +- _SyslogHandler_: Logs records to the syslog. +- _ErrorLogHandler_: Logs records to PHP's + [`error_log()`](http://docs.php.net/manual/en/function.error-log.php) function. + +### Send alerts and emails + +- _NativeMailerHandler_: Sends emails using PHP's + [`mail()`](http://php.net/manual/en/function.mail.php) function. +- _SwiftMailerHandler_: Sends emails using a [`Swift_Mailer`](http://swiftmailer.org/) instance. +- _PushoverHandler_: Sends mobile notifications via the [Pushover](https://www.pushover.net/) API. +- _HipChatHandler_: Logs records to a [HipChat](http://hipchat.com) chat room using its API. +- _FlowdockHandler_: Logs records to a [Flowdock](https://www.flowdock.com/) account. +- _SlackHandler_: Logs records to a [Slack](https://www.slack.com/) account. +- _MandrillHandler_: Sends emails via the Mandrill API using a [`Swift_Message`](http://swiftmailer.org/) instance. +- _FleepHookHandler_: Logs records to a [Fleep](https://fleep.io/) conversation using Webhooks. + +### Log specific servers and networked logging + +- _SocketHandler_: Logs records to [sockets](http://php.net/fsockopen), use this + for UNIX and TCP sockets. See an [example](https://github.com/Seldaek/monolog/blob/master/doc/sockets.md). +- _AmqpHandler_: Logs records to an [amqp](http://www.amqp.org/) compatible + server. Requires the [php-amqp](http://pecl.php.net/package/amqp) extension (1.0+). +- _GelfHandler_: Logs records to a [Graylog2](http://www.graylog2.org) server. +- _CubeHandler_: Logs records to a [Cube](http://square.github.com/cube/) server. +- _RavenHandler_: Logs records to a [Sentry](http://getsentry.com/) server using + [raven](https://packagist.org/packages/raven/raven). +- _ZendMonitorHandler_: Logs records to the Zend Monitor present in Zend Server. +- _NewRelicHandler_: Logs records to a [NewRelic](http://newrelic.com/) application. +- _LogglyHandler_: Logs records to a [Loggly](http://www.loggly.com/) account. +- _RollbarHandler_: Logs records to a [Rollbar](https://rollbar.com/) account. +- _SyslogUdpHandler_: Logs records to a remote [Syslogd](http://www.rsyslog.com/) server. +- _LogEntriesHandler_: Logs records to a [LogEntries](http://logentries.com/) account. + +### Logging in development + +- _FirePHPHandler_: Handler for [FirePHP](http://www.firephp.org/), providing + inline `console` messages within [FireBug](http://getfirebug.com/). +- _ChromePHPHandler_: Handler for [ChromePHP](http://www.chromephp.com/), providing + inline `console` messages within Chrome. +- _BrowserConsoleHandler_: Handler to send logs to browser's Javascript `console` with + no browser extension required. Most browsers supporting `console` API are supported. + +### Log to databases + +- _RedisHandler_: Logs records to a [redis](http://redis.io) server. +- _MongoDBHandler_: Handler to write records in MongoDB via a + [Mongo](http://pecl.php.net/package/mongo) extension connection. +- _CouchDBHandler_: Logs records to a CouchDB server. +- _DoctrineCouchDBHandler_: Logs records to a CouchDB server via the Doctrine CouchDB ODM. +- _ElasticSearchHandler_: Logs records to an Elastic Search server. +- _DynamoDbHandler_: Logs records to a DynamoDB table with the [AWS SDK](https://github.com/aws/aws-sdk-php). + +### Wrappers / Special Handlers + +- _FingersCrossedHandler_: A very interesting wrapper. It takes a logger as + parameter and will accumulate log records of all levels until a record + exceeds the defined severity level. At which point it delivers all records, + including those of lower severity, to the handler it wraps. This means that + until an error actually happens you will not see anything in your logs, but + when it happens you will have the full information, including debug and info + records. This provides you with all the information you need, but only when + you need it. +- _WhatFailureGroupHandler_: This handler extends the _GroupHandler_ ignoring + exceptions raised by each child handler. This allows you to ignore issues + where a remote tcp connection may have died but you do not want your entire + application to crash and may wish to continue to log to other handlers. +- _BufferHandler_: This handler will buffer all the log records it receives + until `close()` is called at which point it will call `handleBatch()` on the + handler it wraps with all the log messages at once. This is very useful to + send an email with all records at once for example instead of having one mail + for every log record. +- _GroupHandler_: This handler groups other handlers. Every record received is + sent to all the handlers it is configured with. +- _FilterHandler_: This handler only lets records of the given levels through + to the wrapped handler. +- _SamplingHandler_: Wraps around another handler and lets you sample records + if you only want to store some of them. +- _NullHandler_: Any record it can handle will be thrown away. This can be used + to put on top of an existing handler stack to disable it temporarily. +- _PsrHandler_: Can be used to forward log records to an existing PSR-3 logger +- _TestHandler_: Used for testing, it records everything that is sent to it and + has accessors to read out the information. + +Formatters +---------- + +- _LineFormatter_: Formats a log record into a one-line string. +- _HtmlFormatter_: Used to format log records into a human readable html table, mainly suitable for emails. +- _NormalizerFormatter_: Normalizes objects/resources down to strings so a record can easily be serialized/encoded. +- _ScalarFormatter_: Used to format log records into an associative array of scalar values. +- _JsonFormatter_: Encodes a log record into json. +- _WildfireFormatter_: Used to format log records into the Wildfire/FirePHP protocol, only useful for the FirePHPHandler. +- _ChromePHPFormatter_: Used to format log records into the ChromePHP format, only useful for the ChromePHPHandler. +- _GelfMessageFormatter_: Used to format log records into Gelf message instances, only useful for the GelfHandler. +- _LogstashFormatter_: Used to format log records into [logstash](http://logstash.net/) event json, useful for any handler listed under inputs [here](http://logstash.net/docs/latest). +- _ElasticaFormatter_: Used to format log records into an Elastica\Document object, only useful for the ElasticSearchHandler. +- _LogglyFormatter_: Used to format log records into Loggly messages, only useful for the LogglyHandler. +- _FlowdockFormatter_: Used to format log records into Flowdock messages, only useful for the FlowdockHandler. +- _MongoDBFormatter_: Converts \DateTime instances to \MongoDate and objects recursively to arrays, only useful with the MongoDBHandler. + +Processors +---------- + +- _IntrospectionProcessor_: Adds the line/file/class/method from which the log call originated. +- _WebProcessor_: Adds the current request URI, request method and client IP to a log record. +- _MemoryUsageProcessor_: Adds the current memory usage to a log record. +- _MemoryPeakUsageProcessor_: Adds the peak memory usage to a log record. +- _ProcessIdProcessor_: Adds the process id to a log record. +- _UidProcessor_: Adds a unique identifier to a log record. +- _GitProcessor_: Adds the current git branch and commit to a log record. +- _TagProcessor_: Adds an array of predefined tags to a log record. + +Utilities +--------- + +- _Registry_: The `Monolog\Registry` class lets you configure global loggers that you + can then statically access from anywhere. It is not really a best practice but can + help in some older codebases or for ease of use. +- _ErrorHandler_: The `Monolog\ErrorHandler` class allows you to easily register + a Logger instance as an exception handler, error handler or fatal error handler. +- _ErrorLevelActivationStrategy_: Activates a FingersCrossedHandler when a certain log + level is reached. +- _ChannelLevelActivationStrategy_: Activates a FingersCrossedHandler when a certain + log level is reached, depending on which channel received the log record. + +About +===== + +Requirements +------------ + +- Monolog works with PHP 5.3 or above, and is also tested to work with HHVM. + +Submitting bugs and feature requests +------------------------------------ + +Bugs and feature request are tracked on [GitHub](https://github.com/Seldaek/monolog/issues) + +Frameworks Integration +---------------------- + +- Frameworks and libraries using [PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) + can be used very easily with Monolog since it implements the interface. +- [Symfony2](http://symfony.com) comes out of the box with Monolog. +- [Silex](http://silex.sensiolabs.org/) comes out of the box with Monolog. +- [Laravel 4](http://laravel.com/) comes out of the box with Monolog. +- [PPI](http://www.ppi.io/) comes out of the box with Monolog. +- [CakePHP](http://cakephp.org/) is usable with Monolog via the [cakephp-monolog](https://github.com/jadb/cakephp-monolog) plugin. +- [Slim](http://www.slimframework.com/) is usable with Monolog via the [Slim-Monolog](https://github.com/Flynsarmy/Slim-Monolog) log writer. +- [XOOPS 2.6](http://xoops.org/) comes out of the box with Monolog. +- [Aura.Web_Project](https://github.com/auraphp/Aura.Web_Project) comes out of the box with Monolog. + +Author +------ + +Jordi Boggiano - <j.boggiano@seld.be> - <http://twitter.com/seldaek><br /> +See also the list of [contributors](https://github.com/Seldaek/monolog/contributors) which participated in this project. + +License +------- + +Monolog is licensed under the MIT License - see the `LICENSE` file for details + +Acknowledgements +---------------- + +This library is heavily inspired by Python's [Logbook](http://packages.python.org/Logbook/) +library, although most concepts have been adjusted to fit to the PHP world. diff --git a/vendor/monolog/monolog/composer.json b/vendor/monolog/monolog/composer.json new file mode 100644 index 00000000..43704236 --- /dev/null +++ b/vendor/monolog/monolog/composer.json @@ -0,0 +1,50 @@ +{ + "name": "monolog/monolog", + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "keywords": ["log", "logging", "psr-3"], + "homepage": "http://github.com/Seldaek/monolog", + "type": "library", + "license": "MIT", + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "require": { + "php": ">=5.3.0", + "psr/log": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0", + "graylog2/gelf-php": "~1.0", + "raven/raven": "~0.5", + "ruflin/elastica": "0.90.*", + "doctrine/couchdb": "~1.0@dev", + "aws/aws-sdk-php": "~2.4, >2.4.8", + "videlalvaro/php-amqplib": "~2.4" + }, + "suggest": { + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "raven/raven": "Allow sending log messages to a Sentry server", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server", + "videlalvaro/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-mongo": "Allow sending log messages to a MongoDB server", + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "rollbar/rollbar": "Allow sending log messages to Rollbar" + }, + "autoload": { + "psr-4": {"Monolog\\": "src/Monolog"} + }, + "provide": { + "psr/log-implementation": "1.0.0" + }, + "extra": { + "branch-alias": { + "dev-master": "1.12.x-dev" + } + } +} diff --git a/vendor/monolog/monolog/doc/extending.md b/vendor/monolog/monolog/doc/extending.md new file mode 100644 index 00000000..bb39ddcf --- /dev/null +++ b/vendor/monolog/monolog/doc/extending.md @@ -0,0 +1,76 @@ +Extending Monolog +================= + +Monolog is fully extensible, allowing you to adapt your logger to your needs. + +Writing your own handler +------------------------ + +Monolog provides many built-in handlers. But if the one you need does not +exist, you can write it and use it in your logger. The only requirement is +to implement `Monolog\Handler\HandlerInterface`. + +Let's write a PDOHandler to log records to a database. We will extend the +abstract class provided by Monolog to keep things DRY. + +```php +<?php + +use Monolog\Logger; +use Monolog\Handler\AbstractProcessingHandler; + +class PDOHandler extends AbstractProcessingHandler +{ + private $initialized = false; + private $pdo; + private $statement; + + public function __construct(PDO $pdo, $level = Logger::DEBUG, $bubble = true) + { + $this->pdo = $pdo; + parent::__construct($level, $bubble); + } + + protected function write(array $record) + { + if (!$this->initialized) { + $this->initialize(); + } + + $this->statement->execute(array( + 'channel' => $record['channel'], + 'level' => $record['level'], + 'message' => $record['formatted'], + 'time' => $record['datetime']->format('U'), + )); + } + + private function initialize() + { + $this->pdo->exec( + 'CREATE TABLE IF NOT EXISTS monolog ' + .'(channel VARCHAR(255), level INTEGER, message LONGTEXT, time INTEGER UNSIGNED)' + ); + $this->statement = $this->pdo->prepare( + 'INSERT INTO monolog (channel, level, message, time) VALUES (:channel, :level, :message, :time)' + ); + + $this->initialized = true; + } +} +``` + +You can now use this handler in your logger: + +```php +<?php + +$logger->pushHandler(new PDOHandler(new PDO('sqlite:logs.sqlite'))); + +// You can now use your logger +$logger->addInfo('My logger is now ready'); +``` + +The `Monolog\Handler\AbstractProcessingHandler` class provides most of the +logic needed for the handler, including the use of processors and the formatting +of the record (which is why we use ``$record['formatted']`` instead of ``$record['message']``). diff --git a/vendor/monolog/monolog/doc/sockets.md b/vendor/monolog/monolog/doc/sockets.md new file mode 100644 index 00000000..fad30a9f --- /dev/null +++ b/vendor/monolog/monolog/doc/sockets.md @@ -0,0 +1,37 @@ +Sockets Handler +=============== + +This handler allows you to write your logs to sockets using [fsockopen](http://php.net/fsockopen) +or [pfsockopen](http://php.net/pfsockopen). + +Persistent sockets are mainly useful in web environments where you gain some performance not closing/opening +the connections between requests. + +Basic Example +------------- + +```php +<?php + +use Monolog\Logger; +use Monolog\Handler\SocketHandler; + +// Create the logger +$logger = new Logger('my_logger'); + +// Create the handler +$handler = new SocketHandler('unix:///var/log/httpd_app_log.socket'); +$handler->setPersistent(true); + +// Now add the handler +$logger->pushHandler($handler, Logger::DEBUG); + +// You can now use your logger +$logger->addInfo('My logger is now ready'); + +``` + +In this example, using syslog-ng, you should see the log on the log server: + + cweb1 [2012-02-26 00:12:03] my_logger.INFO: My logger is now ready [] [] + diff --git a/vendor/monolog/monolog/doc/usage.md b/vendor/monolog/monolog/doc/usage.md new file mode 100644 index 00000000..7585fa2a --- /dev/null +++ b/vendor/monolog/monolog/doc/usage.md @@ -0,0 +1,162 @@ +Using Monolog +============= + +Installation +------------ + +Monolog is available on Packagist ([monolog/monolog](http://packagist.org/packages/monolog/monolog)) +and as such installable via [Composer](http://getcomposer.org/). + +```bash +php composer.phar require monolog/monolog +``` + +If you do not use Composer, you can grab the code from GitHub, and use any +PSR-0 compatible autoloader (e.g. the [Symfony2 ClassLoader component](https://github.com/symfony/ClassLoader)) +to load Monolog classes. + +Configuring a logger +-------------------- + +Here is a basic setup to log to a file and to firephp on the DEBUG level: + +```php +<?php + +use Monolog\Logger; +use Monolog\Handler\StreamHandler; +use Monolog\Handler\FirePHPHandler; + +// Create the logger +$logger = new Logger('my_logger'); +// Now add some handlers +$logger->pushHandler(new StreamHandler(__DIR__.'/my_app.log', Logger::DEBUG)); +$logger->pushHandler(new FirePHPHandler()); + +// You can now use your logger +$logger->addInfo('My logger is now ready'); +``` + +Let's explain it. The first step is to create the logger instance which will +be used in your code. The argument is a channel name, which is useful when +you use several loggers (see below for more details about it). + +The logger itself does not know how to handle a record. It delegates it to +some handlers. The code above registers two handlers in the stack to allow +handling records in two different ways. + +Note that the FirePHPHandler is called first as it is added on top of the +stack. This allows you to temporarily add a logger with bubbling disabled if +you want to override other configured loggers. + +Adding extra data in the records +-------------------------------- + +Monolog provides two different ways to add extra informations along the simple +textual message. + +### Using the logging context + +The first way is the context, allowing to pass an array of data along the +record: + +```php +<?php + +$logger->addInfo('Adding a new user', array('username' => 'Seldaek')); +``` + +Simple handlers (like the StreamHandler for instance) will simply format +the array to a string but richer handlers can take advantage of the context +(FirePHP is able to display arrays in pretty way for instance). + +### Using processors + +The second way is to add extra data for all records by using a processor. +Processors can be any callable. They will get the record as parameter and +must return it after having eventually changed the `extra` part of it. Let's +write a processor adding some dummy data in the record: + +```php +<?php + +$logger->pushProcessor(function ($record) { + $record['extra']['dummy'] = 'Hello world!'; + + return $record; +}); +``` + +Monolog provides some built-in processors that can be used in your project. +Look at the [README file](https://github.com/Seldaek/monolog/blob/master/README.mdown) for the list. + +> Tip: processors can also be registered on a specific handler instead of + the logger to apply only for this handler. + +Leveraging channels +------------------- + +Channels are a great way to identify to which part of the application a record +is related. This is useful in big applications (and is leveraged by +MonologBundle in Symfony2). + +Picture two loggers sharing a handler that writes to a single log file. +Channels would allow you to identify the logger that issued every record. +You can easily grep through the log files filtering this or that channel. + +```php +<?php + +use Monolog\Logger; +use Monolog\Handler\StreamHandler; +use Monolog\Handler\FirePHPHandler; + +// Create some handlers +$stream = new StreamHandler(__DIR__.'/my_app.log', Logger::DEBUG); +$firephp = new FirePHPHandler(); + +// Create the main logger of the app +$logger = new Logger('my_logger'); +$logger->pushHandler($stream); +$logger->pushHandler($firephp); + +// Create a logger for the security-related stuff with a different channel +$securityLogger = new Logger('security'); +$securityLogger->pushHandler($stream); +$securityLogger->pushHandler($firephp); +``` + +Customizing log format +---------------------- + +In Monolog it's easy to customize the format of the logs written into files, +sockets, mails, databases and other handlers. Most of the handlers use the + +```php +$record['formatted'] +``` + +value to be automatically put into the log device. This value depends on the +formatter settings. You can choose between predefined formatter classes or +write your own (e.g. a multiline text file for human-readable output). + +To configure a predefined formatter class, just set it as the handler's field: + +```php +// the default date format is "Y-m-d H:i:s" +$dateFormat = "Y n j, g:i a"; +// the default output format is "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n" +$output = "%datetime% > %level_name% > %message% %context% %extra%\n"; +// finally, create a formatter +$formatter = new LineFormatter($output, $dateFormat); + +// Create a handler +$stream = new StreamHandler(__DIR__.'/my_app.log', Logger::DEBUG); +$stream->setFormatter($formatter); +// bind it to a logger object +$securityLogger = new Logger('security'); +$securityLogger->pushHandler($stream); +``` + +You may also reuse the same formatter between multiple handlers and share those +handlers between multiple loggers. diff --git a/vendor/monolog/monolog/phpunit.xml.dist b/vendor/monolog/monolog/phpunit.xml.dist new file mode 100644 index 00000000..17545707 --- /dev/null +++ b/vendor/monolog/monolog/phpunit.xml.dist @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<phpunit bootstrap="tests/bootstrap.php" colors="true"> + <testsuites> + <testsuite name="Monolog Test Suite"> + <directory>tests/Monolog/</directory> + </testsuite> + </testsuites> + + <filter> + <whitelist> + <directory suffix=".php">src/Monolog/</directory> + </whitelist> + </filter> +</phpunit> diff --git a/vendor/monolog/monolog/src/Monolog/ErrorHandler.php b/vendor/monolog/monolog/src/Monolog/ErrorHandler.php new file mode 100644 index 00000000..c8923354 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/ErrorHandler.php @@ -0,0 +1,208 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog; + +use Psr\Log\LoggerInterface; +use Psr\Log\LogLevel; + +/** + * Monolog error handler + * + * A facility to enable logging of runtime errors, exceptions and fatal errors. + * + * Quick setup: <code>ErrorHandler::register($logger);</code> + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class ErrorHandler +{ + private $logger; + + private $previousExceptionHandler; + private $uncaughtExceptionLevel; + + private $previousErrorHandler; + private $errorLevelMap; + + private $fatalLevel; + private $reservedMemory; + private static $fatalErrors = array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR); + + public function __construct(LoggerInterface $logger) + { + $this->logger = $logger; + } + + /** + * Registers a new ErrorHandler for a given Logger + * + * By default it will handle errors, exceptions and fatal errors + * + * @param LoggerInterface $logger + * @param array|false $errorLevelMap an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling + * @param int|false $exceptionLevel a LogLevel::* constant, or false to disable exception handling + * @param int|false $fatalLevel a LogLevel::* constant, or false to disable fatal error handling + * @return ErrorHandler + */ + public static function register(LoggerInterface $logger, $errorLevelMap = array(), $exceptionLevel = null, $fatalLevel = null) + { + $handler = new static($logger); + if ($errorLevelMap !== false) { + $handler->registerErrorHandler($errorLevelMap); + } + if ($exceptionLevel !== false) { + $handler->registerExceptionHandler($exceptionLevel); + } + if ($fatalLevel !== false) { + $handler->registerFatalHandler($fatalLevel); + } + + return $handler; + } + + public function registerExceptionHandler($level = null, $callPrevious = true) + { + $prev = set_exception_handler(array($this, 'handleException')); + $this->uncaughtExceptionLevel = $level; + if ($callPrevious && $prev) { + $this->previousExceptionHandler = $prev; + } + } + + public function registerErrorHandler(array $levelMap = array(), $callPrevious = true, $errorTypes = -1) + { + $prev = set_error_handler(array($this, 'handleError'), $errorTypes); + $this->errorLevelMap = array_replace($this->defaultErrorLevelMap(), $levelMap); + if ($callPrevious) { + $this->previousErrorHandler = $prev ?: true; + } + } + + public function registerFatalHandler($level = null, $reservedMemorySize = 20) + { + register_shutdown_function(array($this, 'handleFatalError')); + + $this->reservedMemory = str_repeat(' ', 1024 * $reservedMemorySize); + $this->fatalLevel = $level; + } + + protected function defaultErrorLevelMap() + { + return array( + E_ERROR => LogLevel::CRITICAL, + E_WARNING => LogLevel::WARNING, + E_PARSE => LogLevel::ALERT, + E_NOTICE => LogLevel::NOTICE, + E_CORE_ERROR => LogLevel::CRITICAL, + E_CORE_WARNING => LogLevel::WARNING, + E_COMPILE_ERROR => LogLevel::ALERT, + E_COMPILE_WARNING => LogLevel::WARNING, + E_USER_ERROR => LogLevel::ERROR, + E_USER_WARNING => LogLevel::WARNING, + E_USER_NOTICE => LogLevel::NOTICE, + E_STRICT => LogLevel::NOTICE, + E_RECOVERABLE_ERROR => LogLevel::ERROR, + E_DEPRECATED => LogLevel::NOTICE, + E_USER_DEPRECATED => LogLevel::NOTICE, + ); + } + + /** + * @private + */ + public function handleException(\Exception $e) + { + $this->logger->log( + $this->uncaughtExceptionLevel === null ? LogLevel::ERROR : $this->uncaughtExceptionLevel, + sprintf('Uncaught Exception %s: "%s" at %s line %s', get_class($e), $e->getMessage(), $e->getFile(), $e->getLine()), + array('exception' => $e) + ); + + if ($this->previousExceptionHandler) { + call_user_func($this->previousExceptionHandler, $e); + } + } + + /** + * @private + */ + public function handleError($code, $message, $file = '', $line = 0, $context = array()) + { + if (!(error_reporting() & $code)) { + return; + } + + $level = isset($this->errorLevelMap[$code]) ? $this->errorLevelMap[$code] : LogLevel::CRITICAL; + $this->logger->log($level, self::codeToString($code).': '.$message, array('code' => $code, 'message' => $message, 'file' => $file, 'line' => $line)); + + if ($this->previousErrorHandler === true) { + return false; + } elseif ($this->previousErrorHandler) { + return call_user_func($this->previousErrorHandler, $code, $message, $file, $line, $context); + } + } + + /** + * @private + */ + public function handleFatalError() + { + $this->reservedMemory = null; + + $lastError = error_get_last(); + if ($lastError && in_array($lastError['type'], self::$fatalErrors)) { + $this->logger->log( + $this->fatalLevel === null ? LogLevel::ALERT : $this->fatalLevel, + 'Fatal Error ('.self::codeToString($lastError['type']).'): '.$lastError['message'], + array('code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line']) + ); + } + } + + private static function codeToString($code) + { + switch ($code) { + case E_ERROR: + return 'E_ERROR'; + case E_WARNING: + return 'E_WARNING'; + case E_PARSE: + return 'E_PARSE'; + case E_NOTICE: + return 'E_NOTICE'; + case E_CORE_ERROR: + return 'E_CORE_ERROR'; + case E_CORE_WARNING: + return 'E_CORE_WARNING'; + case E_COMPILE_ERROR: + return 'E_COMPILE_ERROR'; + case E_COMPILE_WARNING: + return 'E_COMPILE_WARNING'; + case E_USER_ERROR: + return 'E_USER_ERROR'; + case E_USER_WARNING: + return 'E_USER_WARNING'; + case E_USER_NOTICE: + return 'E_USER_NOTICE'; + case E_STRICT: + return 'E_STRICT'; + case E_RECOVERABLE_ERROR: + return 'E_RECOVERABLE_ERROR'; + case E_DEPRECATED: + return 'E_DEPRECATED'; + case E_USER_DEPRECATED: + return 'E_USER_DEPRECATED'; + } + + return 'Unknown PHP error'; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php new file mode 100644 index 00000000..56d3e278 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php @@ -0,0 +1,79 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +use Monolog\Logger; + +/** + * Formats a log message according to the ChromePHP array format + * + * @author Christophe Coevoet <stof@notk.org> + */ +class ChromePHPFormatter implements FormatterInterface +{ + /** + * Translates Monolog log levels to Wildfire levels. + */ + private $logLevels = array( + Logger::DEBUG => 'log', + Logger::INFO => 'info', + Logger::NOTICE => 'info', + Logger::WARNING => 'warn', + Logger::ERROR => 'error', + Logger::CRITICAL => 'error', + Logger::ALERT => 'error', + Logger::EMERGENCY => 'error', + ); + + /** + * {@inheritdoc} + */ + public function format(array $record) + { + // Retrieve the line and file if set and remove them from the formatted extra + $backtrace = 'unknown'; + if (isset($record['extra']['file']) && isset($record['extra']['line'])) { + $backtrace = $record['extra']['file'].' : '.$record['extra']['line']; + unset($record['extra']['file']); + unset($record['extra']['line']); + } + + $message = array('message' => $record['message']); + if ($record['context']) { + $message['context'] = $record['context']; + } + if ($record['extra']) { + $message['extra'] = $record['extra']; + } + if (count($message) === 1) { + $message = reset($message); + } + + return array( + $record['channel'], + $message, + $backtrace, + $this->logLevels[$record['level']], + ); + } + + public function formatBatch(array $records) + { + $formatted = array(); + + foreach ($records as $record) { + $formatted[] = $this->format($record); + } + + return $formatted; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php new file mode 100644 index 00000000..b0b0cf06 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php @@ -0,0 +1,87 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +use Elastica\Document; + +/** + * Format a log message into an Elastica Document + * + * @author Jelle Vink <jelle.vink@gmail.com> + */ +class ElasticaFormatter extends NormalizerFormatter +{ + /** + * @var string Elastic search index name + */ + protected $index; + + /** + * @var string Elastic search document type + */ + protected $type; + + /** + * @param string $index Elastic Search index name + * @param string $type Elastic Search document type + */ + public function __construct($index, $type) + { + parent::__construct(\DateTime::ISO8601); + $this->index = $index; + $this->type = $type; + } + + /** + * {@inheritdoc} + */ + public function format(array $record) + { + $record = parent::format($record); + + return $this->getDocument($record); + } + + /** + * Getter index + * @return string + */ + public function getIndex() + { + return $this->index; + } + + /** + * Getter type + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * Convert a log message into an Elastica Document + * + * @param array $record Log message + * @return Document + */ + protected function getDocument($record) + { + $document = new Document(); + $document->setData($record); + $document->setType($this->type); + $document->setIndex($this->index); + + return $document; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php new file mode 100644 index 00000000..af63d011 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php @@ -0,0 +1,104 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +/** + * formats the record to be used in the FlowdockHandler + * + * @author Dominik Liebler <liebler.dominik@gmail.com> + */ +class FlowdockFormatter implements FormatterInterface +{ + /** + * @var string + */ + private $source; + + /** + * @var string + */ + private $sourceEmail; + + /** + * @param string $source + * @param string $sourceEmail + */ + public function __construct($source, $sourceEmail) + { + $this->source = $source; + $this->sourceEmail = $sourceEmail; + } + + /** + * {@inheritdoc} + */ + public function format(array $record) + { + $tags = array( + '#logs', + '#' . strtolower($record['level_name']), + '#' . $record['channel'], + ); + + foreach ($record['extra'] as $value) { + $tags[] = '#' . $value; + } + + $subject = sprintf( + 'in %s: %s - %s', + $this->source, + $record['level_name'], + $this->getShortMessage($record['message']) + ); + + $record['flowdock'] = array( + 'source' => $this->source, + 'from_address' => $this->sourceEmail, + 'subject' => $subject, + 'content' => $record['message'], + 'tags' => $tags, + 'project' => $this->source, + ); + + return $record; + } + + /** + * {@inheritdoc} + */ + public function formatBatch(array $records) + { + $formatted = array(); + + foreach ($records as $record) { + $formatted[] = $this->format($record); + } + + return $formatted; + } + + /** + * @param string $message + * + * @return string + */ + public function getShortMessage($message) + { + $maxLength = 45; + + if (strlen($message) > $maxLength) { + $message = substr($message, 0, $maxLength - 4) . ' ...'; + } + + return $message; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php b/vendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php new file mode 100644 index 00000000..b5de7511 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php @@ -0,0 +1,36 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +/** + * Interface for formatters + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +interface FormatterInterface +{ + /** + * Formats a log record. + * + * @param array $record A record to format + * @return mixed The formatted record + */ + public function format(array $record); + + /** + * Formats a set of log records. + * + * @param array $records A set of records to format + * @return mixed The formatted set of records + */ + public function formatBatch(array $records); +} diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php new file mode 100644 index 00000000..8d01c64c --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php @@ -0,0 +1,101 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +use Monolog\Logger; +use Gelf\Message; + +/** + * Serializes a log message to GELF + * @see http://www.graylog2.org/about/gelf + * + * @author Matt Lehner <mlehner@gmail.com> + */ +class GelfMessageFormatter extends NormalizerFormatter +{ + /** + * @var string the name of the system for the Gelf log message + */ + protected $systemName; + + /** + * @var string a prefix for 'extra' fields from the Monolog record (optional) + */ + protected $extraPrefix; + + /** + * @var string a prefix for 'context' fields from the Monolog record (optional) + */ + protected $contextPrefix; + + /** + * Translates Monolog log levels to Graylog2 log priorities. + */ + private $logLevels = array( + Logger::DEBUG => 7, + Logger::INFO => 6, + Logger::NOTICE => 5, + Logger::WARNING => 4, + Logger::ERROR => 3, + Logger::CRITICAL => 2, + Logger::ALERT => 1, + Logger::EMERGENCY => 0, + ); + + public function __construct($systemName = null, $extraPrefix = null, $contextPrefix = 'ctxt_') + { + parent::__construct('U.u'); + + $this->systemName = $systemName ?: gethostname(); + + $this->extraPrefix = $extraPrefix; + $this->contextPrefix = $contextPrefix; + } + + /** + * {@inheritdoc} + */ + public function format(array $record) + { + $record = parent::format($record); + $message = new Message(); + $message + ->setTimestamp($record['datetime']) + ->setShortMessage((string) $record['message']) + ->setFacility($record['channel']) + ->setHost($this->systemName) + ->setLine(isset($record['extra']['line']) ? $record['extra']['line'] : null) + ->setFile(isset($record['extra']['file']) ? $record['extra']['file'] : null) + ->setLevel($this->logLevels[$record['level']]); + + // Do not duplicate these values in the additional fields + unset($record['extra']['line']); + unset($record['extra']['file']); + + foreach ($record['extra'] as $key => $val) { + $message->setAdditional($this->extraPrefix . $key, is_scalar($val) ? $val : $this->toJson($val)); + } + + foreach ($record['context'] as $key => $val) { + $message->setAdditional($this->contextPrefix . $key, is_scalar($val) ? $val : $this->toJson($val)); + } + + if (null === $message->getFile() && isset($record['context']['exception']['file'])) { + if (preg_match("/^(.+):([0-9]+)$/", $record['context']['exception']['file'], $matches)) { + $message->setFile($matches[1]); + $message->setLine($matches[2]); + } + } + + return $message; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php new file mode 100644 index 00000000..255d2887 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php @@ -0,0 +1,140 @@ +<?php +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +use Monolog\Logger; + +/** + * Formats incoming records into an HTML table + * + * This is especially useful for html email logging + * + * @author Tiago Brito <tlfbrito@gmail.com> + */ +class HtmlFormatter extends NormalizerFormatter +{ + /** + * Translates Monolog log levels to html color priorities. + */ + private $logLevels = array( + Logger::DEBUG => '#cccccc', + Logger::INFO => '#468847', + Logger::NOTICE => '#3a87ad', + Logger::WARNING => '#c09853', + Logger::ERROR => '#f0ad4e', + Logger::CRITICAL => '#FF7708', + Logger::ALERT => '#C12A19', + Logger::EMERGENCY => '#000000', + ); + + /** + * @param string $dateFormat The format of the timestamp: one supported by DateTime::format + */ + public function __construct($dateFormat = null) + { + parent::__construct($dateFormat); + } + + /** + * Creates an HTML table row + * + * @param string $th Row header content + * @param string $td Row standard cell content + * @param bool $escapeTd false if td content must not be html escaped + * @return string + */ + private function addRow($th, $td = ' ', $escapeTd = true) + { + $th = htmlspecialchars($th, ENT_NOQUOTES, 'UTF-8'); + if ($escapeTd) { + $td = '<pre>'.htmlspecialchars($td, ENT_NOQUOTES, 'UTF-8').'</pre>'; + } + + return "<tr style=\"padding: 4px;spacing: 0;text-align: left;\">\n<th style=\"background: #cccccc\" width=\"100px\">$th:</th>\n<td style=\"padding: 4px;spacing: 0;text-align: left;background: #eeeeee\">".$td."</td>\n</tr>"; + } + + /** + * Create a HTML h1 tag + * + * @param string $title Text to be in the h1 + * @param integer $level Error level + * @return string + */ + private function addTitle($title, $level) + { + $title = htmlspecialchars($title, ENT_NOQUOTES, 'UTF-8'); + + return '<h1 style="background: '.$this->logLevels[$level].';color: #ffffff;padding: 5px;" class="monolog-output">'.$title.'</h1>'; + } + /** + * Formats a log record. + * + * @param array $record A record to format + * @return mixed The formatted record + */ + public function format(array $record) + { + $output = $this->addTitle($record['level_name'], $record['level']); + $output .= '<table cellspacing="1" width="100%" class="monolog-output">'; + + $output .= $this->addRow('Message', (string) $record['message']); + $output .= $this->addRow('Time', $record['datetime']->format($this->dateFormat)); + $output .= $this->addRow('Channel', $record['channel']); + if ($record['context']) { + $embeddedTable = '<table cellspacing="1" width="100%">'; + foreach ($record['context'] as $key => $value) { + $embeddedTable .= $this->addRow($key, $this->convertToString($value)); + } + $embeddedTable .= '</table>'; + $output .= $this->addRow('Context', $embeddedTable, false); + } + if ($record['extra']) { + $embeddedTable = '<table cellspacing="1" width="100%">'; + foreach ($record['extra'] as $key => $value) { + $embeddedTable .= $this->addRow($key, $this->convertToString($value)); + } + $embeddedTable .= '</table>'; + $output .= $this->addRow('Extra', $embeddedTable, false); + } + + return $output.'</table>'; + } + + /** + * Formats a set of log records. + * + * @param array $records A set of records to format + * @return mixed The formatted set of records + */ + public function formatBatch(array $records) + { + $message = ''; + foreach ($records as $record) { + $message .= $this->format($record); + } + + return $message; + } + + protected function convertToString($data) + { + if (null === $data || is_scalar($data)) { + return (string) $data; + } + + $data = $this->normalize($data); + if (version_compare(PHP_VERSION, '5.4.0', '>=')) { + return json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + } + + return str_replace('\\/', '/', json_encode($data)); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php new file mode 100644 index 00000000..7963dbf1 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php @@ -0,0 +1,116 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +/** + * Encodes whatever record data is passed to it as json + * + * This can be useful to log to databases or remote APIs + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class JsonFormatter implements FormatterInterface +{ + const BATCH_MODE_JSON = 1; + const BATCH_MODE_NEWLINES = 2; + + protected $batchMode; + protected $appendNewline; + + /** + * @param int $batchMode + */ + public function __construct($batchMode = self::BATCH_MODE_JSON, $appendNewline = true) + { + $this->batchMode = $batchMode; + $this->appendNewline = $appendNewline; + } + + /** + * The batch mode option configures the formatting style for + * multiple records. By default, multiple records will be + * formatted as a JSON-encoded array. However, for + * compatibility with some API endpoints, alternive styles + * are available. + * + * @return int + */ + public function getBatchMode() + { + return $this->batchMode; + } + + /** + * True if newlines are appended to every formatted record + * + * @return bool + */ + public function isAppendingNewlines() + { + return $this->appendNewline; + } + + /** + * {@inheritdoc} + */ + public function format(array $record) + { + return json_encode($record) . ($this->appendNewline ? "\n" : ''); + } + + /** + * {@inheritdoc} + */ + public function formatBatch(array $records) + { + switch ($this->batchMode) { + case static::BATCH_MODE_NEWLINES: + return $this->formatBatchNewlines($records); + + case static::BATCH_MODE_JSON: + default: + return $this->formatBatchJson($records); + } + } + + /** + * Return a JSON-encoded array of records. + * + * @param array $records + * @return string + */ + protected function formatBatchJson(array $records) + { + return json_encode($records); + } + + /** + * Use new lines to separate records instead of a + * JSON-encoded array. + * + * @param array $records + * @return string + */ + protected function formatBatchNewlines(array $records) + { + $instance = $this; + + $oldNewline = $this->appendNewline; + $this->appendNewline = false; + array_walk($records, function (&$value, $key) use ($instance) { + $value = $instance->format($value); + }); + $this->appendNewline = $oldNewline; + + return implode("\n", $records); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php new file mode 100644 index 00000000..6983d1a5 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php @@ -0,0 +1,159 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +use Exception; + +/** + * Formats incoming records into a one-line string + * + * This is especially useful for logging to files + * + * @author Jordi Boggiano <j.boggiano@seld.be> + * @author Christophe Coevoet <stof@notk.org> + */ +class LineFormatter extends NormalizerFormatter +{ + const SIMPLE_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"; + + protected $format; + protected $allowInlineLineBreaks; + protected $ignoreEmptyContextAndExtra; + protected $includeStacktraces; + + /** + * @param string $format The format of the message + * @param string $dateFormat The format of the timestamp: one supported by DateTime::format + * @param bool $allowInlineLineBreaks Whether to allow inline line breaks in log entries + * @param bool $ignoreEmptyContextAndExtra + */ + public function __construct($format = null, $dateFormat = null, $allowInlineLineBreaks = false, $ignoreEmptyContextAndExtra = false) + { + $this->format = $format ?: static::SIMPLE_FORMAT; + $this->allowInlineLineBreaks = $allowInlineLineBreaks; + $this->ignoreEmptyContextAndExtra = $ignoreEmptyContextAndExtra; + parent::__construct($dateFormat); + } + + public function includeStacktraces($include = true) + { + $this->includeStacktraces = $include; + if ($this->includeStacktraces) { + $this->allowInlineLineBreaks = true; + } + } + + public function allowInlineLineBreaks($allow = true) + { + $this->allowInlineLineBreaks = $allow; + } + + public function ignoreEmptyContextAndExtra($ignore = true) + { + $this->ignoreEmptyContextAndExtra = $ignore; + } + + /** + * {@inheritdoc} + */ + public function format(array $record) + { + $vars = parent::format($record); + + $output = $this->format; + + foreach ($vars['extra'] as $var => $val) { + if (false !== strpos($output, '%extra.'.$var.'%')) { + $output = str_replace('%extra.'.$var.'%', $this->stringify($val), $output); + unset($vars['extra'][$var]); + } + } + + if ($this->ignoreEmptyContextAndExtra) { + if (empty($vars['context'])) { + unset($vars['context']); + $output = str_replace('%context%', '', $output); + } + + if (empty($vars['extra'])) { + unset($vars['extra']); + $output = str_replace('%extra%', '', $output); + } + } + + foreach ($vars as $var => $val) { + if (false !== strpos($output, '%'.$var.'%')) { + $output = str_replace('%'.$var.'%', $this->stringify($val), $output); + } + } + + return $output; + } + + public function formatBatch(array $records) + { + $message = ''; + foreach ($records as $record) { + $message .= $this->format($record); + } + + return $message; + } + + public function stringify($value) + { + return $this->replaceNewlines($this->convertToString($value)); + } + + protected function normalizeException(Exception $e) + { + $previousText = ''; + if ($previous = $e->getPrevious()) { + do { + $previousText .= ', '.get_class($previous).'(code: '.$previous->getCode().'): '.$previous->getMessage().' at '.$previous->getFile().':'.$previous->getLine(); + } while ($previous = $previous->getPrevious()); + } + + $str = '[object] ('.get_class($e).'(code: '.$e->getCode().'): '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine().$previousText.')'; + if ($this->includeStacktraces) { + $str .= "\n[stacktrace]\n".$e->getTraceAsString(); + } + + return $str; + } + + protected function convertToString($data) + { + if (null === $data || is_bool($data)) { + return var_export($data, true); + } + + if (is_scalar($data)) { + return (string) $data; + } + + if (version_compare(PHP_VERSION, '5.4.0', '>=')) { + return $this->toJson($data, true); + } + + return str_replace('\\/', '/', @json_encode($data)); + } + + protected function replaceNewlines($str) + { + if ($this->allowInlineLineBreaks) { + return $str; + } + + return strtr($str, array("\r\n" => ' ', "\r" => ' ', "\n" => ' ')); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php new file mode 100644 index 00000000..f02bceb0 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php @@ -0,0 +1,47 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +/** + * Encodes message information into JSON in a format compatible with Loggly. + * + * @author Adam Pancutt <adam@pancutt.com> + */ +class LogglyFormatter extends JsonFormatter +{ + /** + * Overrides the default batch mode to new lines for compatibility with the + * Loggly bulk API. + * + * @param integer $batchMode + */ + public function __construct($batchMode = self::BATCH_MODE_NEWLINES, $appendNewline = false) + { + parent::__construct($batchMode, $appendNewline); + } + + /** + * Appends the 'timestamp' parameter for indexing by Loggly. + * + * @see https://www.loggly.com/docs/automated-parsing/#json + * @see \Monolog\Formatter\JsonFormatter::format() + */ + public function format(array $record) + { + if (isset($record["datetime"]) && ($record["datetime"] instanceof \DateTime)) { + $record["timestamp"] = $record["datetime"]->format("Y-m-d\TH:i:s.uO"); + // TODO 2.0 unset the 'datetime' parameter, retained for BC + } + + return parent::format($record); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php new file mode 100644 index 00000000..7a7b3b3c --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php @@ -0,0 +1,165 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +/** + * Serializes a log message to Logstash Event Format + * + * @see http://logstash.net/ + * @see https://github.com/logstash/logstash/blob/master/lib/logstash/event.rb + * + * @author Tim Mower <timothy.mower@gmail.com> + */ +class LogstashFormatter extends NormalizerFormatter +{ + const V0 = 0; + const V1 = 1; + + /** + * @var string the name of the system for the Logstash log message, used to fill the @source field + */ + protected $systemName; + + /** + * @var string an application name for the Logstash log message, used to fill the @type field + */ + protected $applicationName; + + /** + * @var string a prefix for 'extra' fields from the Monolog record (optional) + */ + protected $extraPrefix; + + /** + * @var string a prefix for 'context' fields from the Monolog record (optional) + */ + protected $contextPrefix; + + /** + * @var integer logstash format version to use + */ + protected $version; + + /** + * @param string $applicationName the application that sends the data, used as the "type" field of logstash + * @param string $systemName the system/machine name, used as the "source" field of logstash, defaults to the hostname of the machine + * @param string $extraPrefix prefix for extra keys inside logstash "fields" + * @param string $contextPrefix prefix for context keys inside logstash "fields", defaults to ctxt_ + */ + public function __construct($applicationName, $systemName = null, $extraPrefix = null, $contextPrefix = 'ctxt_', $version = self::V0) + { + // logstash requires a ISO 8601 format date with optional millisecond precision. + parent::__construct('Y-m-d\TH:i:s.uP'); + + $this->systemName = $systemName ?: gethostname(); + $this->applicationName = $applicationName; + $this->extraPrefix = $extraPrefix; + $this->contextPrefix = $contextPrefix; + $this->version = $version; + } + + /** + * {@inheritdoc} + */ + public function format(array $record) + { + $record = parent::format($record); + + if ($this->version === self::V1) { + $message = $this->formatV1($record); + } else { + $message = $this->formatV0($record); + } + + return $this->toJson($message) . "\n"; + } + + protected function formatV0(array $record) + { + if (empty($record['datetime'])) { + $record['datetime'] = gmdate('c'); + } + $message = array( + '@timestamp' => $record['datetime'], + '@source' => $this->systemName, + '@fields' => array() + ); + if (isset($record['message'])) { + $message['@message'] = $record['message']; + } + if (isset($record['channel'])) { + $message['@tags'] = array($record['channel']); + $message['@fields']['channel'] = $record['channel']; + } + if (isset($record['level'])) { + $message['@fields']['level'] = $record['level']; + } + if ($this->applicationName) { + $message['@type'] = $this->applicationName; + } + if (isset($record['extra']['server'])) { + $message['@source_host'] = $record['extra']['server']; + } + if (isset($record['extra']['url'])) { + $message['@source_path'] = $record['extra']['url']; + } + if (!empty($record['extra'])) { + foreach ($record['extra'] as $key => $val) { + $message['@fields'][$this->extraPrefix . $key] = $val; + } + } + if (!empty($record['context'])) { + foreach ($record['context'] as $key => $val) { + $message['@fields'][$this->contextPrefix . $key] = $val; + } + } + + return $message; + } + + protected function formatV1(array $record) + { + if (empty($record['datetime'])) { + $record['datetime'] = gmdate('c'); + } + $message = array( + '@timestamp' => $record['datetime'], + '@version' => 1, + 'host' => $this->systemName, + ); + if (isset($record['message'])) { + $message['message'] = $record['message']; + } + if (isset($record['channel'])) { + $message['type'] = $record['channel']; + $message['channel'] = $record['channel']; + } + if (isset($record['level_name'])) { + $message['level'] = $record['level_name']; + } + if ($this->applicationName) { + $message['type'] = $this->applicationName; + } + if (!empty($record['extra'])) { + foreach ($record['extra'] as $key => $val) { + $message[$this->extraPrefix . $key] = $val; + } + } + if (!empty($record['context'])) { + foreach ($record['context'] as $key => $val) { + $message[$this->contextPrefix . $key] = $val; + } + } + + return $message; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php new file mode 100644 index 00000000..eb067bb7 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php @@ -0,0 +1,105 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +/** + * Formats a record for use with the MongoDBHandler. + * + * @author Florian Plattner <me@florianplattner.de> + */ +class MongoDBFormatter implements FormatterInterface +{ + private $exceptionTraceAsString; + private $maxNestingLevel; + + /** + * @param int $maxNestingLevel 0 means infinite nesting, the $record itself is level 1, $record['context'] is 2 + * @param bool $exceptionTraceAsString set to false to log exception traces as a sub documents instead of strings + */ + public function __construct($maxNestingLevel = 3, $exceptionTraceAsString = true) + { + $this->maxNestingLevel = max($maxNestingLevel, 0); + $this->exceptionTraceAsString = (bool) $exceptionTraceAsString; + } + + /** + * {@inheritDoc} + */ + public function format(array $record) + { + return $this->formatArray($record); + } + + /** + * {@inheritDoc} + */ + public function formatBatch(array $records) + { + foreach ($records as $key => $record) { + $records[$key] = $this->format($record); + } + + return $records; + } + + protected function formatArray(array $record, $nestingLevel = 0) + { + if ($this->maxNestingLevel == 0 || $nestingLevel <= $this->maxNestingLevel) { + foreach ($record as $name => $value) { + if ($value instanceof \DateTime) { + $record[$name] = $this->formatDate($value, $nestingLevel + 1); + } elseif ($value instanceof \Exception) { + $record[$name] = $this->formatException($value, $nestingLevel + 1); + } elseif (is_array($value)) { + $record[$name] = $this->formatArray($value, $nestingLevel + 1); + } elseif (is_object($value)) { + $record[$name] = $this->formatObject($value, $nestingLevel + 1); + } + } + } else { + $record = '[...]'; + } + + return $record; + } + + protected function formatObject($value, $nestingLevel) + { + $objectVars = get_object_vars($value); + $objectVars['class'] = get_class($value); + + return $this->formatArray($objectVars, $nestingLevel); + } + + protected function formatException(\Exception $exception, $nestingLevel) + { + $formattedException = array( + 'class' => get_class($exception), + 'message' => $exception->getMessage(), + 'code' => $exception->getCode(), + 'file' => $exception->getFile() . ':' . $exception->getLine(), + ); + + if ($this->exceptionTraceAsString === true) { + $formattedException['trace'] = $exception->getTraceAsString(); + } else { + $formattedException['trace'] = $exception->getTrace(); + } + + return $this->formatArray($formattedException, $nestingLevel); + } + + protected function formatDate(\DateTime $value, $nestingLevel) + { + return new \MongoDate($value->getTimestamp()); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php new file mode 100644 index 00000000..beafea64 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php @@ -0,0 +1,141 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +use Exception; + +/** + * Normalizes incoming records to remove objects/resources so it's easier to dump to various targets + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class NormalizerFormatter implements FormatterInterface +{ + const SIMPLE_DATE = "Y-m-d H:i:s"; + + protected $dateFormat; + + /** + * @param string $dateFormat The format of the timestamp: one supported by DateTime::format + */ + public function __construct($dateFormat = null) + { + $this->dateFormat = $dateFormat ?: static::SIMPLE_DATE; + if (!function_exists('json_encode')) { + throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s NormalizerFormatter'); + } + } + + /** + * {@inheritdoc} + */ + public function format(array $record) + { + return $this->normalize($record); + } + + /** + * {@inheritdoc} + */ + public function formatBatch(array $records) + { + foreach ($records as $key => $record) { + $records[$key] = $this->format($record); + } + + return $records; + } + + protected function normalize($data) + { + if (null === $data || is_scalar($data)) { + return $data; + } + + if (is_array($data) || $data instanceof \Traversable) { + $normalized = array(); + + $count = 1; + foreach ($data as $key => $value) { + if ($count++ >= 1000) { + $normalized['...'] = 'Over 1000 items, aborting normalization'; + break; + } + $normalized[$key] = $this->normalize($value); + } + + return $normalized; + } + + if ($data instanceof \DateTime) { + return $data->format($this->dateFormat); + } + + if (is_object($data)) { + if ($data instanceof Exception) { + return $this->normalizeException($data); + } + + return sprintf("[object] (%s: %s)", get_class($data), $this->toJson($data, true)); + } + + if (is_resource($data)) { + return '[resource]'; + } + + return '[unknown('.gettype($data).')]'; + } + + protected function normalizeException(Exception $e) + { + $data = array( + 'class' => get_class($e), + 'message' => $e->getMessage(), + 'code' => $e->getCode(), + 'file' => $e->getFile().':'.$e->getLine(), + ); + + $trace = $e->getTrace(); + foreach ($trace as $frame) { + if (isset($frame['file'])) { + $data['trace'][] = $frame['file'].':'.$frame['line']; + } else { + // We should again normalize the frames, because it might contain invalid items + $data['trace'][] = $this->toJson($this->normalize($frame), true); + } + } + + if ($previous = $e->getPrevious()) { + $data['previous'] = $this->normalizeException($previous); + } + + return $data; + } + + protected function toJson($data, $ignoreErrors = false) + { + // suppress json_encode errors since it's twitchy with some inputs + if ($ignoreErrors) { + if (version_compare(PHP_VERSION, '5.4.0', '>=')) { + return @json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + } + + return @json_encode($data); + } + + if (version_compare(PHP_VERSION, '5.4.0', '>=')) { + return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + } + + return json_encode($data); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php new file mode 100644 index 00000000..5d345d53 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php @@ -0,0 +1,48 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +/** + * Formats data into an associative array of scalar values. + * Objects and arrays will be JSON encoded. + * + * @author Andrew Lawson <adlawson@gmail.com> + */ +class ScalarFormatter extends NormalizerFormatter +{ + /** + * {@inheritdoc} + */ + public function format(array $record) + { + foreach ($record as $key => $value) { + $record[$key] = $this->normalizeValue($value); + } + + return $record; + } + + /** + * @param mixed $value + * @return mixed + */ + protected function normalizeValue($value) + { + $normalized = $this->normalize($value); + + if (is_array($normalized) || is_object($normalized)) { + return $this->toJson($normalized, true); + } + + return $normalized; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php new file mode 100644 index 00000000..654710a8 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php @@ -0,0 +1,113 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +use Monolog\Logger; + +/** + * Serializes a log message according to Wildfire's header requirements + * + * @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com> + * @author Christophe Coevoet <stof@notk.org> + * @author Kirill chEbba Chebunin <iam@chebba.org> + */ +class WildfireFormatter extends NormalizerFormatter +{ + const TABLE = 'table'; + + /** + * Translates Monolog log levels to Wildfire levels. + */ + private $logLevels = array( + Logger::DEBUG => 'LOG', + Logger::INFO => 'INFO', + Logger::NOTICE => 'INFO', + Logger::WARNING => 'WARN', + Logger::ERROR => 'ERROR', + Logger::CRITICAL => 'ERROR', + Logger::ALERT => 'ERROR', + Logger::EMERGENCY => 'ERROR', + ); + + /** + * {@inheritdoc} + */ + public function format(array $record) + { + // Retrieve the line and file if set and remove them from the formatted extra + $file = $line = ''; + if (isset($record['extra']['file'])) { + $file = $record['extra']['file']; + unset($record['extra']['file']); + } + if (isset($record['extra']['line'])) { + $line = $record['extra']['line']; + unset($record['extra']['line']); + } + + $record = $this->normalize($record); + $message = array('message' => $record['message']); + $handleError = false; + if ($record['context']) { + $message['context'] = $record['context']; + $handleError = true; + } + if ($record['extra']) { + $message['extra'] = $record['extra']; + $handleError = true; + } + if (count($message) === 1) { + $message = reset($message); + } + + if (isset($record['context'][self::TABLE])) { + $type = 'TABLE'; + $label = $record['channel'] .': '. $record['message']; + $message = $record['context'][self::TABLE]; + } else { + $type = $this->logLevels[$record['level']]; + $label = $record['channel']; + } + + // Create JSON object describing the appearance of the message in the console + $json = $this->toJson(array( + array( + 'Type' => $type, + 'File' => $file, + 'Line' => $line, + 'Label' => $label, + ), + $message, + ), $handleError); + + // The message itself is a serialization of the above JSON object + it's length + return sprintf( + '%s|%s|', + strlen($json), + $json + ); + } + + public function formatBatch(array $records) + { + throw new \BadMethodCallException('Batch formatting does not make sense for the WildfireFormatter'); + } + + protected function normalize($data) + { + if (is_object($data) && !$data instanceof \DateTime) { + return $data; + } + + return parent::normalize($data); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php new file mode 100644 index 00000000..69ede49a --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php @@ -0,0 +1,184 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\Formatter\FormatterInterface; +use Monolog\Formatter\LineFormatter; + +/** + * Base Handler class providing the Handler structure + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +abstract class AbstractHandler implements HandlerInterface +{ + protected $level = Logger::DEBUG; + protected $bubble = true; + + /** + * @var FormatterInterface + */ + protected $formatter; + protected $processors = array(); + + /** + * @param integer $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct($level = Logger::DEBUG, $bubble = true) + { + $this->setLevel($level); + $this->bubble = $bubble; + } + + /** + * {@inheritdoc} + */ + public function isHandling(array $record) + { + return $record['level'] >= $this->level; + } + + /** + * {@inheritdoc} + */ + public function handleBatch(array $records) + { + foreach ($records as $record) { + $this->handle($record); + } + } + + /** + * Closes the handler. + * + * This will be called automatically when the object is destroyed + */ + public function close() + { + } + + /** + * {@inheritdoc} + */ + public function pushProcessor($callback) + { + if (!is_callable($callback)) { + throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), '.var_export($callback, true).' given'); + } + array_unshift($this->processors, $callback); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function popProcessor() + { + if (!$this->processors) { + throw new \LogicException('You tried to pop from an empty processor stack.'); + } + + return array_shift($this->processors); + } + + /** + * {@inheritdoc} + */ + public function setFormatter(FormatterInterface $formatter) + { + $this->formatter = $formatter; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getFormatter() + { + if (!$this->formatter) { + $this->formatter = $this->getDefaultFormatter(); + } + + return $this->formatter; + } + + /** + * Sets minimum logging level at which this handler will be triggered. + * + * @param integer $level + * @return self + */ + public function setLevel($level) + { + $this->level = Logger::toMonologLevel($level); + + return $this; + } + + /** + * Gets minimum logging level at which this handler will be triggered. + * + * @return integer + */ + public function getLevel() + { + return $this->level; + } + + /** + * Sets the bubbling behavior. + * + * @param Boolean $bubble true means that this handler allows bubbling. + * false means that bubbling is not permitted. + * @return self + */ + public function setBubble($bubble) + { + $this->bubble = $bubble; + + return $this; + } + + /** + * Gets the bubbling behavior. + * + * @return Boolean true means that this handler allows bubbling. + * false means that bubbling is not permitted. + */ + public function getBubble() + { + return $this->bubble; + } + + public function __destruct() + { + try { + $this->close(); + } catch (\Exception $e) { + // do nothing + } + } + + /** + * Gets the default formatter. + * + * @return FormatterInterface + */ + protected function getDefaultFormatter() + { + return new LineFormatter(); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php new file mode 100644 index 00000000..6f18f72e --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php @@ -0,0 +1,66 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +/** + * Base Handler class providing the Handler structure + * + * Classes extending it should (in most cases) only implement write($record) + * + * @author Jordi Boggiano <j.boggiano@seld.be> + * @author Christophe Coevoet <stof@notk.org> + */ +abstract class AbstractProcessingHandler extends AbstractHandler +{ + /** + * {@inheritdoc} + */ + public function handle(array $record) + { + if (!$this->isHandling($record)) { + return false; + } + + $record = $this->processRecord($record); + + $record['formatted'] = $this->getFormatter()->format($record); + + $this->write($record); + + return false === $this->bubble; + } + + /** + * Writes the record down to the log of the implementing handler + * + * @param array $record + * @return void + */ + abstract protected function write(array $record); + + /** + * Processes a record. + * + * @param array $record + * @return array + */ + protected function processRecord(array $record) + { + if ($this->processors) { + foreach ($this->processors as $processor) { + $record = call_user_func($processor, $record); + } + } + + return $record; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php new file mode 100644 index 00000000..3eb83bd4 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php @@ -0,0 +1,92 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\Formatter\LineFormatter; + +/** + * Common syslog functionality + */ +abstract class AbstractSyslogHandler extends AbstractProcessingHandler +{ + protected $facility; + + /** + * Translates Monolog log levels to syslog log priorities. + */ + protected $logLevels = array( + Logger::DEBUG => LOG_DEBUG, + Logger::INFO => LOG_INFO, + Logger::NOTICE => LOG_NOTICE, + Logger::WARNING => LOG_WARNING, + Logger::ERROR => LOG_ERR, + Logger::CRITICAL => LOG_CRIT, + Logger::ALERT => LOG_ALERT, + Logger::EMERGENCY => LOG_EMERG, + ); + + /** + * List of valid log facility names. + */ + protected $facilities = array( + 'auth' => LOG_AUTH, + 'authpriv' => LOG_AUTHPRIV, + 'cron' => LOG_CRON, + 'daemon' => LOG_DAEMON, + 'kern' => LOG_KERN, + 'lpr' => LOG_LPR, + 'mail' => LOG_MAIL, + 'news' => LOG_NEWS, + 'syslog' => LOG_SYSLOG, + 'user' => LOG_USER, + 'uucp' => LOG_UUCP, + ); + + /** + * @param mixed $facility + * @param integer $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct($facility = LOG_USER, $level = Logger::DEBUG, $bubble = true) + { + parent::__construct($level, $bubble); + + if (!defined('PHP_WINDOWS_VERSION_BUILD')) { + $this->facilities['local0'] = LOG_LOCAL0; + $this->facilities['local1'] = LOG_LOCAL1; + $this->facilities['local2'] = LOG_LOCAL2; + $this->facilities['local3'] = LOG_LOCAL3; + $this->facilities['local4'] = LOG_LOCAL4; + $this->facilities['local5'] = LOG_LOCAL5; + $this->facilities['local6'] = LOG_LOCAL6; + $this->facilities['local7'] = LOG_LOCAL7; + } + + // convert textual description of facility to syslog constant + if (array_key_exists(strtolower($facility), $this->facilities)) { + $facility = $this->facilities[strtolower($facility)]; + } elseif (!in_array($facility, array_values($this->facilities), true)) { + throw new \UnexpectedValueException('Unknown facility value "'.$facility.'" given'); + } + + $this->facility = $facility; + } + + /** + * {@inheritdoc} + */ + protected function getDefaultFormatter() + { + return new LineFormatter('%channel%.%level_name%: %message% %context% %extra%'); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php new file mode 100644 index 00000000..a28ba02a --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php @@ -0,0 +1,98 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\Formatter\JsonFormatter; +use PhpAmqpLib\Message\AMQPMessage; +use PhpAmqpLib\Channel\AMQPChannel; +use AMQPExchange; + +class AmqpHandler extends AbstractProcessingHandler +{ + /** + * @var AMQPExchange|AMQPChannel $exchange + */ + protected $exchange; + + /** + * @var string + */ + protected $exchangeName; + + /** + * @param AMQPExchange|AMQPChannel $exchange AMQPExchange (php AMQP ext) or PHP AMQP lib channel, ready for use + * @param string $exchangeName + * @param int $level + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct($exchange, $exchangeName = 'log', $level = Logger::DEBUG, $bubble = true) + { + if ($exchange instanceof AMQPExchange) { + $exchange->setName($exchangeName); + } elseif ($exchange instanceof AMQPChannel) { + $this->exchangeName = $exchangeName; + } else { + throw new \InvalidArgumentException('PhpAmqpLib\Channel\AMQPChannel or AMQPExchange instance required'); + } + $this->exchange = $exchange; + + parent::__construct($level, $bubble); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record) + { + $data = $record["formatted"]; + + $routingKey = sprintf( + '%s.%s', + // TODO 2.0 remove substr call + substr($record['level_name'], 0, 4), + $record['channel'] + ); + + if ($this->exchange instanceof AMQPExchange) { + $this->exchange->publish( + $data, + strtolower($routingKey), + 0, + array( + 'delivery_mode' => 2, + 'Content-type' => 'application/json' + ) + ); + } else { + $this->exchange->basic_publish( + new AMQPMessage( + (string) $data, + array( + 'delivery_mode' => 2, + 'content_type' => 'application/json' + ) + ), + $this->exchangeName, + strtolower($routingKey) + ); + } + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php new file mode 100644 index 00000000..43190b92 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php @@ -0,0 +1,184 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\LineFormatter; + +/** + * Handler sending logs to browser's javascript console with no browser extension required + * + * @author Olivier Poitrey <rs@dailymotion.com> + */ +class BrowserConsoleHandler extends AbstractProcessingHandler +{ + protected static $initialized = false; + protected static $records = array(); + + /** + * {@inheritDoc} + * + * Formatted output may contain some formatting markers to be transfered to `console.log` using the %c format. + * + * Example of formatted string: + * + * You can do [[blue text]]{color: blue} or [[green background]]{background-color: green; color: white} + * + */ + protected function getDefaultFormatter() + { + return new LineFormatter('[[%channel%]]{macro: autolabel} [[%level_name%]]{font-weight: bold} %message%'); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record) + { + // Accumulate records + self::$records[] = $record; + + // Register shutdown handler if not already done + if (PHP_SAPI !== 'cli' && !self::$initialized) { + self::$initialized = true; + register_shutdown_function(array('Monolog\Handler\BrowserConsoleHandler', 'send')); + } + } + + /** + * Convert records to javascript console commands and send it to the browser. + * This method is automatically called on PHP shutdown if output is HTML. + */ + public static function send() + { + // Check content type + foreach (headers_list() as $header) { + if (stripos($header, 'content-type:') === 0) { + if (stripos($header, 'text/html') === false) { + // This handler only works with HTML outputs + return; + } + break; + } + } + + if (count(self::$records)) { + echo '<script>' . self::generateScript() . '</script>'; + self::reset(); + } + } + + /** + * Forget all logged records + */ + public static function reset() + { + self::$records = array(); + } + + private static function generateScript() + { + $script = array(); + foreach (self::$records as $record) { + $context = self::dump('Context', $record['context']); + $extra = self::dump('Extra', $record['extra']); + + if (empty($context) && empty($extra)) { + $script[] = self::call_array('log', self::handleStyles($record['formatted'])); + } else { + $script = array_merge($script, + array(self::call_array('groupCollapsed', self::handleStyles($record['formatted']))), + $context, + $extra, + array(self::call('groupEnd')) + ); + } + } + + return "(function (c) {if (c && c.groupCollapsed) {\n" . implode("\n", $script) . "\n}})(console);"; + } + + private static function handleStyles($formatted) + { + $args = array(self::quote('font-weight: normal')); + $format = '%c' . $formatted; + preg_match_all('/\[\[(.*?)\]\]\{([^}]*)\}/s', $format, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); + + foreach (array_reverse($matches) as $match) { + $args[] = self::quote(self::handleCustomStyles($match[2][0], $match[1][0])); + $args[] = '"font-weight: normal"'; + + $pos = $match[0][1]; + $format = substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . substr($format, $pos + strlen($match[0][0])); + } + + array_unshift($args, self::quote($format)); + + return $args; + } + + private static function handleCustomStyles($style, $string) + { + static $colors = array('blue', 'green', 'red', 'magenta', 'orange', 'black', 'grey'); + static $labels = array(); + + return preg_replace_callback('/macro\s*:(.*?)(?:;|$)/', function ($m) use ($string, &$colors, &$labels) { + if (trim($m[1]) === 'autolabel') { + // Format the string as a label with consistent auto assigned background color + if (!isset($labels[$string])) { + $labels[$string] = $colors[count($labels) % count($colors)]; + } + $color = $labels[$string]; + + return "background-color: $color; color: white; border-radius: 3px; padding: 0 2px 0 2px"; + } + + return $m[1]; + }, $style); + } + + private static function dump($title, array $dict) + { + $script = array(); + $dict = array_filter($dict); + if (empty($dict)) { + return $script; + } + $script[] = self::call('log', self::quote('%c%s'), self::quote('font-weight: bold'), self::quote($title)); + foreach ($dict as $key => $value) { + $value = json_encode($value); + if (empty($value)) { + $value = self::quote(''); + } + $script[] = self::call('log', self::quote('%s: %o'), self::quote($key), $value); + } + + return $script; + } + + private static function quote($arg) + { + return '"' . addcslashes($arg, "\"\n") . '"'; + } + + private static function call() + { + $args = func_get_args(); + $method = array_shift($args); + + return self::call_array($method, $args); + } + + private static function call_array($method, array $args) + { + return 'c.' . $method . '(' . implode(', ', $args) . ');'; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php new file mode 100644 index 00000000..6d8136f7 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php @@ -0,0 +1,117 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; + +/** + * Buffers all records until closing the handler and then pass them as batch. + * + * This is useful for a MailHandler to send only one mail per request instead of + * sending one per log message. + * + * @author Christophe Coevoet <stof@notk.org> + */ +class BufferHandler extends AbstractHandler +{ + protected $handler; + protected $bufferSize = 0; + protected $bufferLimit; + protected $flushOnOverflow; + protected $buffer = array(); + protected $initialized = false; + + /** + * @param HandlerInterface $handler Handler. + * @param integer $bufferLimit How many entries should be buffered at most, beyond that the oldest items are removed from the buffer. + * @param integer $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param Boolean $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded + */ + public function __construct(HandlerInterface $handler, $bufferLimit = 0, $level = Logger::DEBUG, $bubble = true, $flushOnOverflow = false) + { + parent::__construct($level, $bubble); + $this->handler = $handler; + $this->bufferLimit = (int) $bufferLimit; + $this->flushOnOverflow = $flushOnOverflow; + } + + /** + * {@inheritdoc} + */ + public function handle(array $record) + { + if ($record['level'] < $this->level) { + return false; + } + + if (!$this->initialized) { + // __destructor() doesn't get called on Fatal errors + register_shutdown_function(array($this, 'close')); + $this->initialized = true; + } + + if ($this->bufferLimit > 0 && $this->bufferSize === $this->bufferLimit) { + if ($this->flushOnOverflow) { + $this->flush(); + } else { + array_shift($this->buffer); + $this->bufferSize--; + } + } + + if ($this->processors) { + foreach ($this->processors as $processor) { + $record = call_user_func($processor, $record); + } + } + + $this->buffer[] = $record; + $this->bufferSize++; + + return false === $this->bubble; + } + + public function flush() + { + if ($this->bufferSize === 0) { + return; + } + + $this->handler->handleBatch($this->buffer); + $this->clear(); + } + + public function __destruct() + { + // suppress the parent behavior since we already have register_shutdown_function() + // to call close(), and the reference contained there will prevent this from being + // GC'd until the end of the request + } + + /** + * {@inheritdoc} + */ + public function close() + { + $this->flush(); + } + + /** + * Clears the buffer without flushing any messages down to the wrapped handler. + */ + public function clear() + { + $this->bufferSize = 0; + $this->buffer = array(); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php new file mode 100644 index 00000000..bc659349 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php @@ -0,0 +1,204 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\ChromePHPFormatter; +use Monolog\Logger; + +/** + * Handler sending logs to the ChromePHP extension (http://www.chromephp.com/) + * + * @author Christophe Coevoet <stof@notk.org> + */ +class ChromePHPHandler extends AbstractProcessingHandler +{ + /** + * Version of the extension + */ + const VERSION = '4.0'; + + /** + * Header name + */ + const HEADER_NAME = 'X-ChromeLogger-Data'; + + protected static $initialized = false; + + /** + * Tracks whether we sent too much data + * + * Chrome limits the headers to 256KB, so when we sent 240KB we stop sending + * + * @var Boolean + */ + protected static $overflowed = false; + + protected static $json = array( + 'version' => self::VERSION, + 'columns' => array('label', 'log', 'backtrace', 'type'), + 'rows' => array(), + ); + + protected static $sendHeaders = true; + + /** + * @param integer $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct($level = Logger::DEBUG, $bubble = true) + { + parent::__construct($level, $bubble); + if (!function_exists('json_encode')) { + throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s ChromePHPHandler'); + } + } + + /** + * {@inheritdoc} + */ + public function handleBatch(array $records) + { + $messages = array(); + + foreach ($records as $record) { + if ($record['level'] < $this->level) { + continue; + } + $messages[] = $this->processRecord($record); + } + + if (!empty($messages)) { + $messages = $this->getFormatter()->formatBatch($messages); + self::$json['rows'] = array_merge(self::$json['rows'], $messages); + $this->send(); + } + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new ChromePHPFormatter(); + } + + /** + * Creates & sends header for a record + * + * @see sendHeader() + * @see send() + * @param array $record + */ + protected function write(array $record) + { + self::$json['rows'][] = $record['formatted']; + + $this->send(); + } + + /** + * Sends the log header + * + * @see sendHeader() + */ + protected function send() + { + if (self::$overflowed || !self::$sendHeaders) { + return; + } + + if (!self::$initialized) { + self::$initialized = true; + + self::$sendHeaders = $this->headersAccepted(); + if (!self::$sendHeaders) { + return; + } + + self::$json['request_uri'] = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''; + } + + $json = @json_encode(self::$json); + $data = base64_encode(utf8_encode($json)); + if (strlen($data) > 240*1024) { + self::$overflowed = true; + + $record = array( + 'message' => 'Incomplete logs, chrome header size limit reached', + 'context' => array(), + 'level' => Logger::WARNING, + 'level_name' => Logger::getLevelName(Logger::WARNING), + 'channel' => 'monolog', + 'datetime' => new \DateTime(), + 'extra' => array(), + ); + self::$json['rows'][count(self::$json['rows']) - 1] = $this->getFormatter()->format($record); + $json = @json_encode(self::$json); + $data = base64_encode(utf8_encode($json)); + } + + if (trim($data) !== '') { + $this->sendHeader(self::HEADER_NAME, $data); + } + } + + /** + * Send header string to the client + * + * @param string $header + * @param string $content + */ + protected function sendHeader($header, $content) + { + if (!headers_sent() && self::$sendHeaders) { + header(sprintf('%s: %s', $header, $content)); + } + } + + /** + * Verifies if the headers are accepted by the current user agent + * + * @return Boolean + */ + protected function headersAccepted() + { + if (empty($_SERVER['HTTP_USER_AGENT'])) { + return false; + } + + return preg_match('{\bChrome/\d+[\.\d+]*\b}', $_SERVER['HTTP_USER_AGENT']); + } + + /** + * BC getter for the sendHeaders property that has been made static + */ + public function __get($property) + { + if ('sendHeaders' !== $property) { + throw new \InvalidArgumentException('Undefined property '.$property); + } + + return static::$sendHeaders; + } + + /** + * BC setter for the sendHeaders property that has been made static + */ + public function __set($property, $value) + { + if ('sendHeaders' !== $property) { + throw new \InvalidArgumentException('Undefined property '.$property); + } + + static::$sendHeaders = $value; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php new file mode 100644 index 00000000..b3687c3d --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php @@ -0,0 +1,72 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\JsonFormatter; +use Monolog\Logger; + +/** + * CouchDB handler + * + * @author Markus Bachmann <markus.bachmann@bachi.biz> + */ +class CouchDBHandler extends AbstractProcessingHandler +{ + private $options; + + public function __construct(array $options = array(), $level = Logger::DEBUG, $bubble = true) + { + $this->options = array_merge(array( + 'host' => 'localhost', + 'port' => 5984, + 'dbname' => 'logger', + 'username' => null, + 'password' => null, + ), $options); + + parent::__construct($level, $bubble); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record) + { + $basicAuth = null; + if ($this->options['username']) { + $basicAuth = sprintf('%s:%s@', $this->options['username'], $this->options['password']); + } + + $url = 'http://'.$basicAuth.$this->options['host'].':'.$this->options['port'].'/'.$this->options['dbname']; + $context = stream_context_create(array( + 'http' => array( + 'method' => 'POST', + 'content' => $record['formatted'], + 'ignore_errors' => true, + 'max_redirects' => 0, + 'header' => 'Content-type: application/json', + ) + )); + + if (false === @file_get_contents($url, null, $context)) { + throw new \RuntimeException(sprintf('Could not connect to %s', $url)); + } + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php new file mode 100644 index 00000000..d968720c --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php @@ -0,0 +1,145 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; + +/** + * Logs to Cube. + * + * @link http://square.github.com/cube/ + * @author Wan Chen <kami@kamisama.me> + */ +class CubeHandler extends AbstractProcessingHandler +{ + private $udpConnection = null; + private $httpConnection = null; + private $scheme = null; + private $host = null; + private $port = null; + private $acceptedSchemes = array('http', 'udp'); + + /** + * Create a Cube handler + * + * @throws UnexpectedValueException when given url is not a valid url. + * A valid url must consists of three parts : protocol://host:port + * Only valid protocol used by Cube are http and udp + */ + public function __construct($url, $level = Logger::DEBUG, $bubble = true) + { + $urlInfos = parse_url($url); + + if (!isset($urlInfos['scheme']) || !isset($urlInfos['host']) || !isset($urlInfos['port'])) { + throw new \UnexpectedValueException('URL "'.$url.'" is not valid'); + } + + if (!in_array($urlInfos['scheme'], $this->acceptedSchemes)) { + throw new \UnexpectedValueException( + 'Invalid protocol (' . $urlInfos['scheme'] . ').' + . ' Valid options are ' . implode(', ', $this->acceptedSchemes)); + } + + $this->scheme = $urlInfos['scheme']; + $this->host = $urlInfos['host']; + $this->port = $urlInfos['port']; + + parent::__construct($level, $bubble); + } + + /** + * Establish a connection to an UDP socket + * + * @throws LogicException when unable to connect to the socket + */ + protected function connectUdp() + { + if (!extension_loaded('sockets')) { + throw new MissingExtensionException('The sockets extension is required to use udp URLs with the CubeHandler'); + } + + $this->udpConnection = socket_create(AF_INET, SOCK_DGRAM, 0); + if (!$this->udpConnection) { + throw new \LogicException('Unable to create a socket'); + } + + if (!socket_connect($this->udpConnection, $this->host, $this->port)) { + throw new \LogicException('Unable to connect to the socket at ' . $this->host . ':' . $this->port); + } + } + + /** + * Establish a connection to a http server + */ + protected function connectHttp() + { + if (!extension_loaded('curl')) { + throw new \LogicException('The curl extension is needed to use http URLs with the CubeHandler'); + } + + $this->httpConnection = curl_init('http://'.$this->host.':'.$this->port.'/1.0/event/put'); + + if (!$this->httpConnection) { + throw new \LogicException('Unable to connect to ' . $this->host . ':' . $this->port); + } + + curl_setopt($this->httpConnection, CURLOPT_CUSTOMREQUEST, "POST"); + curl_setopt($this->httpConnection, CURLOPT_RETURNTRANSFER, true); + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + $date = $record['datetime']; + + $data = array('time' => $date->format('Y-m-d\TH:i:s.uO')); + unset($record['datetime']); + + if (isset($record['context']['type'])) { + $data['type'] = $record['context']['type']; + unset($record['context']['type']); + } else { + $data['type'] = $record['channel']; + } + + $data['data'] = $record['context']; + $data['data']['level'] = $record['level']; + + $this->{'write'.$this->scheme}(json_encode($data)); + } + + private function writeUdp($data) + { + if (!$this->udpConnection) { + $this->connectUdp(); + } + + socket_send($this->udpConnection, $data, strlen($data), 0); + } + + private function writeHttp($data) + { + if (!$this->httpConnection) { + $this->connectHttp(); + } + + curl_setopt($this->httpConnection, CURLOPT_POSTFIELDS, '['.$data.']'); + curl_setopt($this->httpConnection, CURLOPT_HTTPHEADER, array( + 'Content-Type: application/json', + 'Content-Length: ' . strlen('['.$data.']')) + ); + + return curl_exec($this->httpConnection); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php new file mode 100644 index 00000000..b91ffec9 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php @@ -0,0 +1,45 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\Formatter\NormalizerFormatter; +use Doctrine\CouchDB\CouchDBClient; + +/** + * CouchDB handler for Doctrine CouchDB ODM + * + * @author Markus Bachmann <markus.bachmann@bachi.biz> + */ +class DoctrineCouchDBHandler extends AbstractProcessingHandler +{ + private $client; + + public function __construct(CouchDBClient $client, $level = Logger::DEBUG, $bubble = true) + { + $this->client = $client; + parent::__construct($level, $bubble); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record) + { + $this->client->postDocument($record['formatted']); + } + + protected function getDefaultFormatter() + { + return new NormalizerFormatter; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php new file mode 100644 index 00000000..e7f843c8 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php @@ -0,0 +1,89 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Aws\Common\Aws; +use Aws\DynamoDb\DynamoDbClient; +use Monolog\Formatter\ScalarFormatter; +use Monolog\Logger; + +/** + * Amazon DynamoDB handler (http://aws.amazon.com/dynamodb/) + * + * @link https://github.com/aws/aws-sdk-php/ + * @author Andrew Lawson <adlawson@gmail.com> + */ +class DynamoDbHandler extends AbstractProcessingHandler +{ + const DATE_FORMAT = 'Y-m-d\TH:i:s.uO'; + + /** + * @var DynamoDbClient + */ + protected $client; + + /** + * @var string + */ + protected $table; + + /** + * @param DynamoDbClient $client + * @param string $table + * @param integer $level + * @param boolean $bubble + */ + public function __construct(DynamoDbClient $client, $table, $level = Logger::DEBUG, $bubble = true) + { + if (!defined('Aws\Common\Aws::VERSION') || version_compare('3.0', Aws::VERSION, '<=')) { + throw new \RuntimeException('The DynamoDbHandler is only known to work with the AWS SDK 2.x releases'); + } + + $this->client = $client; + $this->table = $table; + + parent::__construct($level, $bubble); + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + $filtered = $this->filterEmptyFields($record['formatted']); + $formatted = $this->client->formatAttributes($filtered); + + $this->client->putItem(array( + 'TableName' => $this->table, + 'Item' => $formatted + )); + } + + /** + * @param array $record + * @return array + */ + protected function filterEmptyFields(array $record) + { + return array_filter($record, function ($value) { + return !empty($value) || false === $value || 0 === $value; + }); + } + + /** + * {@inheritdoc} + */ + protected function getDefaultFormatter() + { + return new ScalarFormatter(self::DATE_FORMAT); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php new file mode 100644 index 00000000..96e5d57f --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php @@ -0,0 +1,128 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\FormatterInterface; +use Monolog\Formatter\ElasticaFormatter; +use Monolog\Logger; +use Elastica\Client; +use Elastica\Exception\ExceptionInterface; + +/** + * Elastic Search handler + * + * Usage example: + * + * $client = new \Elastica\Client(); + * $options = array( + * 'index' => 'elastic_index_name', + * 'type' => 'elastic_doc_type', + * ); + * $handler = new ElasticSearchHandler($client, $options); + * $log = new Logger('application'); + * $log->pushHandler($handler); + * + * @author Jelle Vink <jelle.vink@gmail.com> + */ +class ElasticSearchHandler extends AbstractProcessingHandler +{ + /** + * @var Client + */ + protected $client; + + /** + * @var array Handler config options + */ + protected $options = array(); + + /** + * @param Client $client Elastica Client object + * @param array $options Handler configuration + * @param integer $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct(Client $client, array $options = array(), $level = Logger::DEBUG, $bubble = true) + { + parent::__construct($level, $bubble); + $this->client = $client; + $this->options = array_merge( + array( + 'index' => 'monolog', // Elastic index name + 'type' => 'record', // Elastic document type + 'ignore_error' => false, // Suppress Elastica exceptions + ), + $options + ); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record) + { + $this->bulkSend(array($record['formatted'])); + } + + /** + * {@inheritdoc} + */ + public function setFormatter(FormatterInterface $formatter) + { + if ($formatter instanceof ElasticaFormatter) { + return parent::setFormatter($formatter); + } + throw new \InvalidArgumentException('ElasticSearchHandler is only compatible with ElasticaFormatter'); + } + + /** + * Getter options + * @return array + */ + public function getOptions() + { + return $this->options; + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new ElasticaFormatter($this->options['index'], $this->options['type']); + } + + /** + * {@inheritdoc} + */ + public function handleBatch(array $records) + { + $documents = $this->getFormatter()->formatBatch($records); + $this->bulkSend($documents); + } + + /** + * Use Elasticsearch bulk API to send list of documents + * @param array $documents + * @throws \RuntimeException + */ + protected function bulkSend(array $documents) + { + try { + $this->client->addDocuments($documents); + } catch (ExceptionInterface $e) { + if (!$this->options['ignore_error']) { + throw new \RuntimeException("Error sending messages to Elasticsearch", 0, $e); + } + } + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php new file mode 100644 index 00000000..d1e1ee60 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php @@ -0,0 +1,82 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\LineFormatter; +use Monolog\Logger; + +/** + * Stores to PHP error_log() handler. + * + * @author Elan Ruusamäe <glen@delfi.ee> + */ +class ErrorLogHandler extends AbstractProcessingHandler +{ + const OPERATING_SYSTEM = 0; + const SAPI = 4; + + protected $messageType; + protected $expandNewlines; + + /** + * @param integer $messageType Says where the error should go. + * @param integer $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param Boolean $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries + */ + public function __construct($messageType = self::OPERATING_SYSTEM, $level = Logger::DEBUG, $bubble = true, $expandNewlines = false) + { + parent::__construct($level, $bubble); + + if (false === in_array($messageType, self::getAvailableTypes())) { + $message = sprintf('The given message type "%s" is not supported', print_r($messageType, true)); + throw new \InvalidArgumentException($message); + } + + $this->messageType = $messageType; + $this->expandNewlines = $expandNewlines; + } + + /** + * @return array With all available types + */ + public static function getAvailableTypes() + { + return array( + self::OPERATING_SYSTEM, + self::SAPI, + ); + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new LineFormatter('[%datetime%] %channel%.%level_name%: %message% %context% %extra%'); + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + if ($this->expandNewlines) { + $lines = preg_split('{[\r\n]+}', (string) $record['formatted']); + foreach ($lines as $line) { + error_log($line, $this->messageType); + } + } else { + error_log((string) $record['formatted'], $this->messageType); + } + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php new file mode 100644 index 00000000..dad82273 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php @@ -0,0 +1,140 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; + +/** + * Simple handler wrapper that filters records based on a list of levels + * + * It can be configured with an exact list of levels to allow, or a min/max level. + * + * @author Hennadiy Verkh + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class FilterHandler extends AbstractHandler +{ + /** + * Handler or factory callable($record, $this) + * + * @var callable|\Monolog\Handler\HandlerInterface + */ + protected $handler; + + /** + * Minimum level for logs that are passes to handler + * + * @var int[] + */ + protected $acceptedLevels; + + /** + * Whether the messages that are handled can bubble up the stack or not + * + * @var Boolean + */ + protected $bubble; + + /** + * @param callable|HandlerInterface $handler Handler or factory callable($record, $this). + * @param int|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided + * @param int $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct($handler, $minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY, $bubble = true) + { + $this->handler = $handler; + $this->bubble = $bubble; + $this->setAcceptedLevels($minLevelOrList, $maxLevel); + + if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) { + throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object"); + } + } + + /** + * @return array + */ + public function getAcceptedLevels() + { + return array_flip($this->acceptedLevels); + } + + /** + * @param int|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided + * @param int $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array + */ + public function setAcceptedLevels($minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY) + { + if (is_array($minLevelOrList)) { + $acceptedLevels = array_map('Monolog\Logger::toMonologLevel', $minLevelOrList); + } else { + $minLevelOrList = Logger::toMonologLevel($minLevelOrList); + $maxLevel = Logger::toMonologLevel($maxLevel); + $acceptedLevels = array_values(array_filter(Logger::getLevels(), function ($level) use ($minLevelOrList, $maxLevel) { + return $level >= $minLevelOrList && $level <= $maxLevel; + })); + } + $this->acceptedLevels = array_flip($acceptedLevels); + } + + /** + * {@inheritdoc} + */ + public function isHandling(array $record) + { + return isset($this->acceptedLevels[$record['level']]); + } + + /** + * {@inheritdoc} + */ + public function handle(array $record) + { + if (!$this->isHandling($record)) { + return false; + } + + // The same logic as in FingersCrossedHandler + if (!$this->handler instanceof HandlerInterface) { + $this->handler = call_user_func($this->handler, $record, $this); + if (!$this->handler instanceof HandlerInterface) { + throw new \RuntimeException("The factory callable should return a HandlerInterface"); + } + } + + if ($this->processors) { + foreach ($this->processors as $processor) { + $record = call_user_func($processor, $record); + } + } + + $this->handler->handle($record); + + return false === $this->bubble; + } + + /** + * {@inheritdoc} + */ + public function handleBatch(array $records) + { + $filtered = array(); + foreach ($records as $record) { + if ($this->isHandling($record)) { + $filtered[] = $record; + } + } + + $this->handler->handleBatch($filtered); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php b/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php new file mode 100644 index 00000000..c3e42efe --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php @@ -0,0 +1,28 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler\FingersCrossed; + +/** + * Interface for activation strategies for the FingersCrossedHandler. + * + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +interface ActivationStrategyInterface +{ + /** + * Returns whether the given record activates the handler. + * + * @param array $record + * @return Boolean + */ + public function isHandlerActivated(array $record); +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php b/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php new file mode 100644 index 00000000..e3b403f6 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php @@ -0,0 +1,59 @@ +<?php + +/* + * This file is part of the Monolog package. +* +* (c) Jordi Boggiano <j.boggiano@seld.be> +* +* For the full copyright and license information, please view the LICENSE +* file that was distributed with this source code. +*/ + +namespace Monolog\Handler\FingersCrossed; + +use Monolog\Logger; + +/** + * Channel and Error level based monolog activation strategy. Allows to trigger activation + * based on level per channel. e.g. trigger activation on level 'ERROR' by default, except + * for records of the 'sql' channel; those should trigger activation on level 'WARN'. + * + * Example: + * + * <code> + * $activationStrategy = new ChannelLevelActivationStrategy( + * Logger::CRITICAL, + * array( + * 'request' => Logger::ALERT, + * 'sensitive' => Logger::ERROR, + * ) + * ); + * $handler = new FingersCrossedHandler(new StreamHandler('php://stderr'), $activationStrategy); + * </code> + * + * @author Mike Meessen <netmikey@gmail.com> + */ +class ChannelLevelActivationStrategy implements ActivationStrategyInterface +{ + private $defaultActionLevel; + private $channelToActionLevel; + + /** + * @param int $defaultActionLevel The default action level to be used if the record's category doesn't match any + * @param array $channelToActionLevel An array that maps channel names to action levels. + */ + public function __construct($defaultActionLevel, $channelToActionLevel = array()) + { + $this->defaultActionLevel = Logger::toMonologLevel($defaultActionLevel); + $this->channelToActionLevel = array_map('Monolog\Logger::toMonologLevel', $channelToActionLevel); + } + + public function isHandlerActivated(array $record) + { + if (isset($this->channelToActionLevel[$record['channel']])) { + return $record['level'] >= $this->channelToActionLevel[$record['channel']]; + } + + return $record['level'] >= $this->defaultActionLevel; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php b/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php new file mode 100644 index 00000000..6e630852 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php @@ -0,0 +1,34 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler\FingersCrossed; + +use Monolog\Logger; + +/** + * Error level based activation strategy. + * + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +class ErrorLevelActivationStrategy implements ActivationStrategyInterface +{ + private $actionLevel; + + public function __construct($actionLevel) + { + $this->actionLevel = Logger::toMonologLevel($actionLevel); + } + + public function isHandlerActivated(array $record) + { + return $record['level'] >= $this->actionLevel; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php new file mode 100644 index 00000000..a81c9e64 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php @@ -0,0 +1,150 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy; +use Monolog\Handler\FingersCrossed\ActivationStrategyInterface; +use Monolog\Logger; + +/** + * Buffers all records until a certain level is reached + * + * The advantage of this approach is that you don't get any clutter in your log files. + * Only requests which actually trigger an error (or whatever your actionLevel is) will be + * in the logs, but they will contain all records, not only those above the level threshold. + * + * You can find the various activation strategies in the + * Monolog\Handler\FingersCrossed\ namespace. + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class FingersCrossedHandler extends AbstractHandler +{ + protected $handler; + protected $activationStrategy; + protected $buffering = true; + protected $bufferSize; + protected $buffer = array(); + protected $stopBuffering; + protected $passthruLevel; + + /** + * @param callable|HandlerInterface $handler Handler or factory callable($record, $fingersCrossedHandler). + * @param int|ActivationStrategyInterface $activationStrategy Strategy which determines when this handler takes action + * @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer. + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param Boolean $stopBuffering Whether the handler should stop buffering after being triggered (default true) + * @param int $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered + */ + public function __construct($handler, $activationStrategy = null, $bufferSize = 0, $bubble = true, $stopBuffering = true, $passthruLevel = null) + { + if (null === $activationStrategy) { + $activationStrategy = new ErrorLevelActivationStrategy(Logger::WARNING); + } + + // convert simple int activationStrategy to an object + if (!$activationStrategy instanceof ActivationStrategyInterface) { + $activationStrategy = new ErrorLevelActivationStrategy($activationStrategy); + } + + $this->handler = $handler; + $this->activationStrategy = $activationStrategy; + $this->bufferSize = $bufferSize; + $this->bubble = $bubble; + $this->stopBuffering = $stopBuffering; + $this->passthruLevel = $passthruLevel; + + if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) { + throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object"); + } + } + + /** + * {@inheritdoc} + */ + public function isHandling(array $record) + { + return true; + } + + /** + * {@inheritdoc} + */ + public function handle(array $record) + { + if ($this->processors) { + foreach ($this->processors as $processor) { + $record = call_user_func($processor, $record); + } + } + + if ($this->buffering) { + $this->buffer[] = $record; + if ($this->bufferSize > 0 && count($this->buffer) > $this->bufferSize) { + array_shift($this->buffer); + } + if ($this->activationStrategy->isHandlerActivated($record)) { + if ($this->stopBuffering) { + $this->buffering = false; + } + if (!$this->handler instanceof HandlerInterface) { + $this->handler = call_user_func($this->handler, $record, $this); + if (!$this->handler instanceof HandlerInterface) { + throw new \RuntimeException("The factory callable should return a HandlerInterface"); + } + } + $this->handler->handleBatch($this->buffer); + $this->buffer = array(); + } + } else { + $this->handler->handle($record); + } + + return false === $this->bubble; + } + + /** + * {@inheritdoc} + */ + public function close() + { + if (null !== $this->passthruLevel) { + $level = $this->passthruLevel; + $this->buffer = array_filter($this->buffer, function ($record) use ($level) { + return $record['level'] >= $level; + }); + if (count($this->buffer) > 0) { + $this->handler->handleBatch($this->buffer); + $this->buffer = array(); + } + } + } + + /** + * Resets the state of the handler. Stops forwarding records to the wrapped handler. + */ + public function reset() + { + $this->buffering = true; + } + + /** + * Clears the buffer without flushing any messages down to the wrapped handler. + * + * It also resets the handler to its initial buffering state. + */ + public function clear() + { + $this->buffer = array(); + $this->reset(); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php new file mode 100644 index 00000000..fee47950 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php @@ -0,0 +1,195 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\WildfireFormatter; + +/** + * Simple FirePHP Handler (http://www.firephp.org/), which uses the Wildfire protocol. + * + * @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com> + */ +class FirePHPHandler extends AbstractProcessingHandler +{ + /** + * WildFire JSON header message format + */ + const PROTOCOL_URI = 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2'; + + /** + * FirePHP structure for parsing messages & their presentation + */ + const STRUCTURE_URI = 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1'; + + /** + * Must reference a "known" plugin, otherwise headers won't display in FirePHP + */ + const PLUGIN_URI = 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3'; + + /** + * Header prefix for Wildfire to recognize & parse headers + */ + const HEADER_PREFIX = 'X-Wf'; + + /** + * Whether or not Wildfire vendor-specific headers have been generated & sent yet + */ + protected static $initialized = false; + + /** + * Shared static message index between potentially multiple handlers + * @var int + */ + protected static $messageIndex = 1; + + protected static $sendHeaders = true; + + /** + * Base header creation function used by init headers & record headers + * + * @param array $meta Wildfire Plugin, Protocol & Structure Indexes + * @param string $message Log message + * @return array Complete header string ready for the client as key and message as value + */ + protected function createHeader(array $meta, $message) + { + $header = sprintf('%s-%s', self::HEADER_PREFIX, join('-', $meta)); + + return array($header => $message); + } + + /** + * Creates message header from record + * + * @see createHeader() + * @param array $record + * @return string + */ + protected function createRecordHeader(array $record) + { + // Wildfire is extensible to support multiple protocols & plugins in a single request, + // but we're not taking advantage of that (yet), so we're using "1" for simplicity's sake. + return $this->createHeader( + array(1, 1, 1, self::$messageIndex++), + $record['formatted'] + ); + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new WildfireFormatter(); + } + + /** + * Wildfire initialization headers to enable message parsing + * + * @see createHeader() + * @see sendHeader() + * @return array + */ + protected function getInitHeaders() + { + // Initial payload consists of required headers for Wildfire + return array_merge( + $this->createHeader(array('Protocol', 1), self::PROTOCOL_URI), + $this->createHeader(array(1, 'Structure', 1), self::STRUCTURE_URI), + $this->createHeader(array(1, 'Plugin', 1), self::PLUGIN_URI) + ); + } + + /** + * Send header string to the client + * + * @param string $header + * @param string $content + */ + protected function sendHeader($header, $content) + { + if (!headers_sent() && self::$sendHeaders) { + header(sprintf('%s: %s', $header, $content)); + } + } + + /** + * Creates & sends header for a record, ensuring init headers have been sent prior + * + * @see sendHeader() + * @see sendInitHeaders() + * @param array $record + */ + protected function write(array $record) + { + if (!self::$sendHeaders) { + return; + } + + // WildFire-specific headers must be sent prior to any messages + if (!self::$initialized) { + self::$initialized = true; + + self::$sendHeaders = $this->headersAccepted(); + if (!self::$sendHeaders) { + return; + } + + foreach ($this->getInitHeaders() as $header => $content) { + $this->sendHeader($header, $content); + } + } + + $header = $this->createRecordHeader($record); + if (trim(current($header)) !== '') { + $this->sendHeader(key($header), current($header)); + } + } + + /** + * Verifies if the headers are accepted by the current user agent + * + * @return Boolean + */ + protected function headersAccepted() + { + if (!empty($_SERVER['HTTP_USER_AGENT']) && preg_match('{\bFirePHP/\d+\.\d+\b}', $_SERVER['HTTP_USER_AGENT'])) { + return true; + } + + return isset($_SERVER['HTTP_X_FIREPHP_VERSION']); + } + + /** + * BC getter for the sendHeaders property that has been made static + */ + public function __get($property) + { + if ('sendHeaders' !== $property) { + throw new \InvalidArgumentException('Undefined property '.$property); + } + + return static::$sendHeaders; + } + + /** + * BC setter for the sendHeaders property that has been made static + */ + public function __set($property, $value) + { + if ('sendHeaders' !== $property) { + throw new \InvalidArgumentException('Undefined property '.$property); + } + + static::$sendHeaders = $value; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php new file mode 100644 index 00000000..388692c4 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php @@ -0,0 +1,126 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\LineFormatter; +use Monolog\Logger; + +/** + * Sends logs to Fleep.io using Webhook integrations + * + * You'll need a Fleep.io account to use this handler. + * + * @see https://fleep.io/integrations/webhooks/ Fleep Webhooks Documentation + * @author Ando Roots <ando@sqroot.eu> + */ +class FleepHookHandler extends SocketHandler +{ + const FLEEP_HOST = 'fleep.io'; + + const FLEEP_HOOK_URI = '/hook/'; + + /** + * @var string Webhook token (specifies the conversation where logs are sent) + */ + protected $token; + + /** + * Construct a new Fleep.io Handler. + * + * For instructions on how to create a new web hook in your conversations + * see https://fleep.io/integrations/webhooks/ + * + * @param string $token Webhook token + * @param bool|int $level The minimum logging level at which this handler will be triggered + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * @throws MissingExtensionException + */ + public function __construct($token, $level = Logger::DEBUG, $bubble = true) + { + if (!extension_loaded('openssl')) { + throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FleepHookHandler'); + } + + $this->token = $token; + + $connectionString = 'ssl://' . self::FLEEP_HOST . ':443'; + parent::__construct($connectionString, $level, $bubble); + } + + /** + * Returns the default formatter to use with this handler + * + * Overloaded to remove empty context and extra arrays from the end of the log message. + * + * @return LineFormatter + */ + protected function getDefaultFormatter() + { + return new LineFormatter(null, null, true, true); + } + + /** + * Handles a log record + * + * @param array $record + */ + public function write(array $record) + { + parent::write($record); + $this->closeSocket(); + } + + /** + * {@inheritdoc} + * + * @param array $record + * @return string + */ + protected function generateDataStream($record) + { + $content = $this->buildContent($record); + + return $this->buildHeader($content) . $content; + } + + /** + * Builds the header of the API Call + * + * @param string $content + * @return string + */ + private function buildHeader($content) + { + $header = "POST " . self::FLEEP_HOOK_URI . $this->token . " HTTP/1.1\r\n"; + $header .= "Host: " . self::FLEEP_HOST . "\r\n"; + $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; + $header .= "Content-Length: " . strlen($content) . "\r\n"; + $header .= "\r\n"; + + return $header; + } + + /** + * Builds the body of API call + * + * @param array $record + * @return string + */ + private function buildContent($record) + { + $dataArray = array( + 'message' => $record['formatted'] + ); + + return http_build_query($dataArray); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php new file mode 100644 index 00000000..6eaaa9d4 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php @@ -0,0 +1,103 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; + +/** + * Sends notifications through the Flowdock push API + * + * This must be configured with a FlowdockFormatter instance via setFormatter() + * + * Notes: + * API token - Flowdock API token + * + * @author Dominik Liebler <liebler.dominik@gmail.com> + * @see https://www.flowdock.com/api/push + */ +class FlowdockHandler extends SocketHandler +{ + /** + * @var string + */ + protected $apiToken; + + /** + * @param string $apiToken + * @param bool|int $level The minimum logging level at which this handler will be triggered + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * + * @throws MissingExtensionException if OpenSSL is missing + */ + public function __construct($apiToken, $level = Logger::DEBUG, $bubble = true) + { + if (!extension_loaded('openssl')) { + throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FlowdockHandler'); + } + + parent::__construct('ssl://api.flowdock.com:443', $level, $bubble); + $this->apiToken = $apiToken; + } + + /** + * {@inheritdoc} + * + * @param array $record + */ + protected function write(array $record) + { + parent::write($record); + + $this->closeSocket(); + } + + /** + * {@inheritdoc} + * + * @param array $record + * @return string + */ + protected function generateDataStream($record) + { + $content = $this->buildContent($record); + + return $this->buildHeader($content) . $content; + } + + /** + * Builds the body of API call + * + * @param array $record + * @return string + */ + private function buildContent($record) + { + return json_encode($record['formatted']['flowdock']); + } + + /** + * Builds the header of the API Call + * + * @param string $content + * @return string + */ + private function buildHeader($content) + { + $header = "POST /v1/messages/team_inbox/" . $this->apiToken . " HTTP/1.1\r\n"; + $header .= "Host: api.flowdock.com\r\n"; + $header .= "Content-Type: application/json\r\n"; + $header .= "Content-Length: " . strlen($content) . "\r\n"; + $header .= "\r\n"; + + return $header; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php new file mode 100644 index 00000000..790f6364 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php @@ -0,0 +1,72 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Gelf\IMessagePublisher; +use Gelf\PublisherInterface; +use InvalidArgumentException; +use Monolog\Logger; +use Monolog\Formatter\GelfMessageFormatter; + +/** + * Handler to send messages to a Graylog2 (http://www.graylog2.org) server + * + * @author Matt Lehner <mlehner@gmail.com> + * @author Benjamin Zikarsky <benjamin@zikarsky.de> + */ +class GelfHandler extends AbstractProcessingHandler +{ + /** + * @var Publisher the publisher object that sends the message to the server + */ + protected $publisher; + + /** + * @param PublisherInterface|IMessagePublisher $publisher a publisher object + * @param integer $level The minimum logging level at which this handler will be triggered + * @param boolean $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct($publisher, $level = Logger::DEBUG, $bubble = true) + { + parent::__construct($level, $bubble); + + if (!$publisher instanceof IMessagePublisher && !$publisher instanceof PublisherInterface) { + throw new InvalidArgumentException("Invalid publisher, expected a Gelf\IMessagePublisher or Gelf\PublisherInterface instance"); + } + + $this->publisher = $publisher; + } + + /** + * {@inheritdoc} + */ + public function close() + { + $this->publisher = null; + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + $this->publisher->publish($record['formatted']); + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new GelfMessageFormatter(); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php new file mode 100644 index 00000000..99384d35 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php @@ -0,0 +1,80 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +/** + * Forwards records to multiple handlers + * + * @author Lenar Lõhmus <lenar@city.ee> + */ +class GroupHandler extends AbstractHandler +{ + protected $handlers; + + /** + * @param array $handlers Array of Handlers. + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct(array $handlers, $bubble = true) + { + foreach ($handlers as $handler) { + if (!$handler instanceof HandlerInterface) { + throw new \InvalidArgumentException('The first argument of the GroupHandler must be an array of HandlerInterface instances.'); + } + } + + $this->handlers = $handlers; + $this->bubble = $bubble; + } + + /** + * {@inheritdoc} + */ + public function isHandling(array $record) + { + foreach ($this->handlers as $handler) { + if ($handler->isHandling($record)) { + return true; + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function handle(array $record) + { + if ($this->processors) { + foreach ($this->processors as $processor) { + $record = call_user_func($processor, $record); + } + } + + foreach ($this->handlers as $handler) { + $handler->handle($record); + } + + return false === $this->bubble; + } + + /** + * {@inheritdoc} + */ + public function handleBatch(array $records) + { + foreach ($this->handlers as $handler) { + $handler->handleBatch($records); + } + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php b/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php new file mode 100644 index 00000000..d920c4ba --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php @@ -0,0 +1,90 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\FormatterInterface; + +/** + * Interface that all Monolog Handlers must implement + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +interface HandlerInterface +{ + /** + * Checks whether the given record will be handled by this handler. + * + * This is mostly done for performance reasons, to avoid calling processors for nothing. + * + * Handlers should still check the record levels within handle(), returning false in isHandling() + * is no guarantee that handle() will not be called, and isHandling() might not be called + * for a given record. + * + * @param array $record Partial log record containing only a level key + * + * @return Boolean + */ + public function isHandling(array $record); + + /** + * Handles a record. + * + * All records may be passed to this method, and the handler should discard + * those that it does not want to handle. + * + * The return value of this function controls the bubbling process of the handler stack. + * Unless the bubbling is interrupted (by returning true), the Logger class will keep on + * calling further handlers in the stack with a given log record. + * + * @param array $record The record to handle + * @return Boolean true means that this handler handled the record, and that bubbling is not permitted. + * false means the record was either not processed or that this handler allows bubbling. + */ + public function handle(array $record); + + /** + * Handles a set of records at once. + * + * @param array $records The records to handle (an array of record arrays) + */ + public function handleBatch(array $records); + + /** + * Adds a processor in the stack. + * + * @param callable $callback + * @return self + */ + public function pushProcessor($callback); + + /** + * Removes the processor on top of the stack and returns it. + * + * @return callable + */ + public function popProcessor(); + + /** + * Sets the formatter. + * + * @param FormatterInterface $formatter + * @return self + */ + public function setFormatter(FormatterInterface $formatter); + + /** + * Gets the formatter. + * + * @return FormatterInterface + */ + public function getFormatter(); +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php new file mode 100644 index 00000000..29614d31 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php @@ -0,0 +1,300 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; + +/** + * Sends notifications through the hipchat api to a hipchat room + * + * Notes: + * API token - HipChat API token + * Room - HipChat Room Id or name, where messages are sent + * Name - Name used to send the message (from) + * notify - Should the message trigger a notification in the clients + * + * @author Rafael Dohms <rafael@doh.ms> + * @see https://www.hipchat.com/docs/api + */ +class HipChatHandler extends SocketHandler +{ + /** + * The maximum allowed length for the name used in the "from" field. + */ + const MAXIMUM_NAME_LENGTH = 15; + + /** + * The maximum allowed length for the message. + */ + const MAXIMUM_MESSAGE_LENGTH = 9500; + + /** + * @var string + */ + private $token; + + /** + * @var array + */ + private $room; + + /** + * @var string + */ + private $name; + + /** + * @var boolean + */ + private $notify; + + /** + * @var string + */ + private $format; + + /** + * @param string $token HipChat API Token + * @param string $room The room that should be alerted of the message (Id or Name) + * @param string $name Name used in the "from" field + * @param bool $notify Trigger a notification in clients or not + * @param int $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param Boolean $useSSL Whether to connect via SSL. + * @param string $format The format of the messages (default to text, can be set to html if you have html in the messages) + * @param string $host The HipChat server hostname. + */ + public function __construct($token, $room, $name = 'Monolog', $notify = false, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $format = 'text', $host = 'api.hipchat.com') + { + if (!$this->validateStringLength($name, static::MAXIMUM_NAME_LENGTH)) { + throw new \InvalidArgumentException('The supplied name is too long. HipChat\'s v1 API supports names up to 15 UTF-8 characters.'); + } + + $connectionString = $useSSL ? 'ssl://'.$host.':443' : $host.':80'; + parent::__construct($connectionString, $level, $bubble); + + $this->token = $token; + $this->name = $name; + $this->notify = $notify; + $this->room = $room; + $this->format = $format; + } + + /** + * {@inheritdoc} + * + * @param array $record + * @return string + */ + protected function generateDataStream($record) + { + $content = $this->buildContent($record); + + return $this->buildHeader($content) . $content; + } + + /** + * Builds the body of API call + * + * @param array $record + * @return string + */ + private function buildContent($record) + { + $dataArray = array( + 'from' => $this->name, + 'room_id' => $this->room, + 'notify' => $this->notify, + 'message' => $record['formatted'], + 'message_format' => $this->format, + 'color' => $this->getAlertColor($record['level']), + ); + + return http_build_query($dataArray); + } + + /** + * Builds the header of the API Call + * + * @param string $content + * @return string + */ + private function buildHeader($content) + { + $header = "POST /v1/rooms/message?format=json&auth_token=".$this->token." HTTP/1.1\r\n"; + $header .= "Host: api.hipchat.com\r\n"; + $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; + $header .= "Content-Length: " . strlen($content) . "\r\n"; + $header .= "\r\n"; + + return $header; + } + + /** + * Assigns a color to each level of log records. + * + * @param integer $level + * @return string + */ + protected function getAlertColor($level) + { + switch (true) { + case $level >= Logger::ERROR: + return 'red'; + case $level >= Logger::WARNING: + return 'yellow'; + case $level >= Logger::INFO: + return 'green'; + case $level == Logger::DEBUG: + return 'gray'; + default: + return 'yellow'; + } + } + + /** + * {@inheritdoc} + * + * @param array $record + */ + protected function write(array $record) + { + parent::write($record); + $this->closeSocket(); + } + + /** + * {@inheritdoc} + */ + public function handleBatch(array $records) + { + if (count($records) == 0) { + return true; + } + + $batchRecords = $this->combineRecords($records); + + $handled = false; + foreach ($batchRecords as $batchRecord) { + if ($this->isHandling($batchRecord)) { + $this->write($batchRecord); + $handled = true; + } + } + + if (!$handled) { + return false; + } + + return false === $this->bubble; + } + + /** + * Combines multiple records into one. Error level of the combined record + * will be the highest level from the given records. Datetime will be taken + * from the first record. + * + * @param $records + * @return array + */ + private function combineRecords($records) + { + $batchRecord = null; + $batchRecords = array(); + $messages = array(); + $formattedMessages = array(); + $level = 0; + $levelName = null; + $datetime = null; + + foreach ($records as $record) { + $record = $this->processRecord($record); + + if ($record['level'] > $level) { + $level = $record['level']; + $levelName = $record['level_name']; + } + + if (null === $datetime) { + $datetime = $record['datetime']; + } + + $messages[] = $record['message']; + $messgeStr = implode(PHP_EOL, $messages); + $formattedMessages[] = $this->getFormatter()->format($record); + $formattedMessageStr = implode('', $formattedMessages); + + $batchRecord = array( + 'message' => $messgeStr, + 'formatted' => $formattedMessageStr, + 'context' => array(), + 'extra' => array(), + ); + + if (!$this->validateStringLength($batchRecord['formatted'], static::MAXIMUM_MESSAGE_LENGTH)) { + // Pop the last message and implode the remainging messages + $lastMessage = array_pop($messages); + $lastFormattedMessage = array_pop($formattedMessages); + $batchRecord['message'] = implode(PHP_EOL, $messages); + $batchRecord['formatted'] = implode('', $formattedMessages); + + $batchRecords[] = $batchRecord; + $messages = array($lastMessage); + $formattedMessages = array($lastFormattedMessage); + + $batchRecord = null; + } + } + + if (null !== $batchRecord) { + $batchRecords[] = $batchRecord; + } + + // Set the max level and datetime for all records + foreach ($batchRecords as &$batchRecord) { + $batchRecord = array_merge( + $batchRecord, + array( + 'level' => $level, + 'level_name' => $levelName, + 'datetime' => $datetime + ) + ); + } + + return $batchRecords; + } + + /** + * Validates the length of a string. + * + * If the `mb_strlen()` function is available, it will use that, as HipChat + * allows UTF-8 characters. Otherwise, it will fall back to `strlen()`. + * + * Note that this might cause false failures in the specific case of using + * a valid name with less than 16 characters, but 16 or more bytes, on a + * system where `mb_strlen()` is unavailable. + * + * @param string $str + * @param int $length + * + * @return bool + */ + private function validateStringLength($str, $length) + { + if (function_exists('mb_strlen')) { + return (mb_strlen($str) <= $length); + } + + return (strlen($str) <= $length); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php new file mode 100644 index 00000000..8bf388b3 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php @@ -0,0 +1,55 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; + +/** + * @author Robert Kaufmann III <rok3@rok3.me> + */ +class LogEntriesHandler extends SocketHandler +{ + /** + * @var string + */ + protected $logToken; + + /** + * @param string $token Log token supplied by LogEntries + * @param boolean $useSSL Whether or not SSL encryption should be used. + * @param int $level The minimum logging level to trigger this handler + * @param boolean $bubble Whether or not messages that are handled should bubble up the stack. + * + * @throws MissingExtensionExcpetion If SSL encryption is set to true and OpenSSL is missing + */ + public function __construct($token, $useSSL = true, $level = Logger::DEBUG, $bubble = true) + { + if ($useSSL && !extension_loaded('openssl')) { + throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for LogEntriesHandler'); + } + + $endpoint = $useSSL ? 'ssl://api.logentries.com:20000' : 'data.logentries.com:80'; + parent::__construct($endpoint, $level, $bubble); + $this->logToken = $token; + } + + /** + * {@inheritdoc} + * + * @param array $record + * @return string + */ + protected function generateDataStream($record) + { + return $this->logToken . ' ' . $record['formatted']; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php new file mode 100644 index 00000000..efd94d30 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php @@ -0,0 +1,98 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\Formatter\LogglyFormatter; + +/** + * Sends errors to Loggly. + * + * @author Przemek Sobstel <przemek@sobstel.org> + * @author Adam Pancutt <adam@pancutt.com> + */ +class LogglyHandler extends AbstractProcessingHandler +{ + const HOST = 'logs-01.loggly.com'; + const ENDPOINT_SINGLE = 'inputs'; + const ENDPOINT_BATCH = 'bulk'; + + protected $token; + + protected $tag; + + public function __construct($token, $level = Logger::DEBUG, $bubble = true) + { + if (!extension_loaded('curl')) { + throw new \LogicException('The curl extension is needed to use the LogglyHandler'); + } + + $this->token = $token; + + parent::__construct($level, $bubble); + } + + public function setTag($tag) + { + $this->tag = $tag; + } + + public function addTag($tag) + { + $this->tag = (strlen($this->tag) > 0) ? $this->tag .','. $tag : $tag; + } + + protected function write(array $record) + { + $this->send($record["formatted"], self::ENDPOINT_SINGLE); + } + + public function handleBatch(array $records) + { + $level = $this->level; + + $records = array_filter($records, function ($record) use ($level) { + return ($record['level'] >= $level); + }); + + if ($records) { + $this->send($this->getFormatter()->formatBatch($records), self::ENDPOINT_BATCH); + } + } + + protected function send($data, $endpoint) + { + $url = sprintf("https://%s/%s/%s/", self::HOST, $endpoint, $this->token); + + $headers = array('Content-Type: application/json'); + + if ($this->tag) { + $headers[] = "X-LOGGLY-TAG: {$this->tag}"; + } + + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + curl_exec($ch); + curl_close($ch); + } + + protected function getDefaultFormatter() + { + return new LogglyFormatter(); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php new file mode 100644 index 00000000..86292727 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php @@ -0,0 +1,55 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +/** + * Base class for all mail handlers + * + * @author Gyula Sallai + */ +abstract class MailHandler extends AbstractProcessingHandler +{ + /** + * {@inheritdoc} + */ + public function handleBatch(array $records) + { + $messages = array(); + + foreach ($records as $record) { + if ($record['level'] < $this->level) { + continue; + } + $messages[] = $this->processRecord($record); + } + + if (!empty($messages)) { + $this->send((string) $this->getFormatter()->formatBatch($messages), $messages); + } + } + + /** + * Send a mail with the given content + * + * @param string $content + * @param array $records the array of log records that formed this content + */ + abstract protected function send($content, array $records); + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + $this->send((string) $record['formatted'], array($record)); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php new file mode 100644 index 00000000..60a2901e --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php @@ -0,0 +1,69 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; + +/** + * MandrillHandler uses cURL to send the emails to the Mandrill API + * + * @author Adam Nicholson <adamnicholson10@gmail.com> + */ +class MandrillHandler extends MailHandler +{ + protected $client; + protected $message; + + /** + * @param string $apiKey A valid Mandrill API key + * @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced + * @param integer $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct($apiKey, $message, $level = Logger::ERROR, $bubble = true) + { + parent::__construct($level, $bubble); + + if (!$message instanceof \Swift_Message && is_callable($message)) { + $message = call_user_func($message); + } + if (!$message instanceof \Swift_Message) { + throw new \InvalidArgumentException('You must provide either a Swift_Message instance or a callable returning it'); + } + $this->message = $message; + $this->apiKey = $apiKey; + } + + /** + * {@inheritdoc} + */ + protected function send($content, array $records) + { + $message = clone $this->message; + $message->setBody($content); + $message->setDate(time()); + + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL, 'https://mandrillapp.com/api/1.0/messages/send-raw.json'); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array( + 'key' => $this->apiKey, + 'raw_message' => (string) $message, + 'async' => false, + ))); + + curl_exec($ch); + curl_close($ch); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php b/vendor/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php new file mode 100644 index 00000000..4724a7e2 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +/** + * Exception can be thrown if an extension for an handler is missing + * + * @author Christian Bergau <cbergau86@gmail.com> + */ +class MissingExtensionException extends \Exception +{ +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php new file mode 100644 index 00000000..6c431f2b --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php @@ -0,0 +1,55 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\Formatter\NormalizerFormatter; + +/** + * Logs to a MongoDB database. + * + * usage example: + * + * $log = new Logger('application'); + * $mongodb = new MongoDBHandler(new \Mongo("mongodb://localhost:27017"), "logs", "prod"); + * $log->pushHandler($mongodb); + * + * @author Thomas Tourlourat <thomas@tourlourat.com> + */ +class MongoDBHandler extends AbstractProcessingHandler +{ + protected $mongoCollection; + + public function __construct($mongo, $database, $collection, $level = Logger::DEBUG, $bubble = true) + { + if (!($mongo instanceof \MongoClient || $mongo instanceof \Mongo)) { + throw new \InvalidArgumentException('MongoClient or Mongo instance required'); + } + + $this->mongoCollection = $mongo->selectCollection($database, $collection); + + parent::__construct($level, $bubble); + } + + protected function write(array $record) + { + $this->mongoCollection->save($record["formatted"]); + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new NormalizerFormatter(); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php new file mode 100644 index 00000000..0fe6b642 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php @@ -0,0 +1,155 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; + +/** + * NativeMailerHandler uses the mail() function to send the emails + * + * @author Christophe Coevoet <stof@notk.org> + * @author Mark Garrett <mark@moderndeveloperllc.com> + */ +class NativeMailerHandler extends MailHandler +{ + /** + * The email addresses to which the message will be sent + * @var array + */ + protected $to; + + /** + * The subject of the email + * @var string + */ + protected $subject; + + /** + * Optional headers for the message + * @var array + */ + protected $headers = array(); + + /** + * The wordwrap length for the message + * @var integer + */ + protected $maxColumnWidth; + + /** + * The Content-type for the message + * @var string + */ + protected $contentType = 'text/plain'; + + /** + * The encoding for the message + * @var string + */ + protected $encoding = 'utf-8'; + + /** + * @param string|array $to The receiver of the mail + * @param string $subject The subject of the mail + * @param string $from The sender of the mail + * @param integer $level The minimum logging level at which this handler will be triggered + * @param boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param int $maxColumnWidth The maximum column width that the message lines will have + */ + public function __construct($to, $subject, $from, $level = Logger::ERROR, $bubble = true, $maxColumnWidth = 70) + { + parent::__construct($level, $bubble); + $this->to = is_array($to) ? $to : array($to); + $this->subject = $subject; + $this->addHeader(sprintf('From: %s', $from)); + $this->maxColumnWidth = $maxColumnWidth; + } + + /** + * Add headers to the message + * + * @param string|array $headers Custom added headers + * @return null + */ + public function addHeader($headers) + { + foreach ((array) $headers as $header) { + if (strpos($header, "\n") !== false || strpos($header, "\r") !== false) { + throw new \InvalidArgumentException('Headers can not contain newline characters for security reasons'); + } + $this->headers[] = $header; + } + } + + /** + * {@inheritdoc} + */ + protected function send($content, array $records) + { + $content = wordwrap($content, $this->maxColumnWidth); + $headers = ltrim(implode("\r\n", $this->headers) . "\r\n", "\r\n"); + $headers .= 'Content-type: ' . $this->getContentType() . '; charset=' . $this->getEncoding() . "\r\n"; + if ($this->getContentType() == 'text/html' && false === strpos($headers, 'MIME-Version:')) { + $headers .= 'MIME-Version: 1.0' . "\r\n"; + } + foreach ($this->to as $to) { + mail($to, $this->subject, $content, $headers); + } + } + + /** + * @return string $contentType + */ + public function getContentType() + { + return $this->contentType; + } + + /** + * @return string $encoding + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * @param string $contentType The content type of the email - Defaults to text/plain. Use text/html for HTML + * messages. + * @return self + */ + public function setContentType($contentType) + { + if (strpos($contentType, "\n") !== false || strpos($contentType, "\r") !== false) { + throw new \InvalidArgumentException('The content type can not contain newline characters to prevent email header injection'); + } + + $this->contentType = $contentType; + + return $this; + } + + /** + * @param string $encoding + * @return self + */ + public function setEncoding($encoding) + { + if (strpos($encoding, "\n") !== false || strpos($encoding, "\r") !== false) { + throw new \InvalidArgumentException('The content type can not contain newline characters to prevent email header injection'); + } + + $this->encoding = $encoding; + + return $this; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php new file mode 100644 index 00000000..9807410d --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php @@ -0,0 +1,174 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; + +/** + * Class to record a log on a NewRelic application + * + * @see https://docs.newrelic.com/docs/agents/php-agent + */ +class NewRelicHandler extends AbstractProcessingHandler +{ + /** + * Name of the New Relic application that will receive logs from this handler. + * + * @var string + */ + protected $appName; + + /** + * Name of the current transaction + * + * @var string + */ + protected $transactionName; + + /** + * Some context and extra data is passed into the handler as arrays of values. Do we send them as is + * (useful if we are using the API), or explode them for display on the NewRelic RPM website? + * + * @var boolean + */ + protected $explodeArrays; + + /** + * {@inheritDoc} + * + * @param string $appName + * @param boolean $explodeArrays + * @param string $transactionName + */ + public function __construct( + $level = Logger::ERROR, + $bubble = true, + $appName = null, + $explodeArrays = false, + $transactionName = null + ) { + parent::__construct($level, $bubble); + + $this->appName = $appName; + $this->explodeArrays = $explodeArrays; + $this->transactionName = $transactionName; + } + + /** + * {@inheritDoc} + */ + protected function write(array $record) + { + if (!$this->isNewRelicEnabled()) { + throw new MissingExtensionException('The newrelic PHP extension is required to use the NewRelicHandler'); + } + + if ($appName = $this->getAppName($record['context'])) { + $this->setNewRelicAppName($appName); + } + + if ($transactionName = $this->getTransactionName($record['context'])) { + $this->setNewRelicTransactionName($transactionName); + unset($record['context']['transaction_name']); + } + + if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Exception) { + newrelic_notice_error($record['message'], $record['context']['exception']); + unset($record['context']['exception']); + } else { + newrelic_notice_error($record['message']); + } + + foreach ($record['context'] as $key => $parameter) { + if (is_array($parameter) && $this->explodeArrays) { + foreach ($parameter as $paramKey => $paramValue) { + newrelic_add_custom_parameter('context_' . $key . '_' . $paramKey, $paramValue); + } + } else { + newrelic_add_custom_parameter('context_' . $key, $parameter); + } + } + + foreach ($record['extra'] as $key => $parameter) { + if (is_array($parameter) && $this->explodeArrays) { + foreach ($parameter as $paramKey => $paramValue) { + newrelic_add_custom_parameter('extra_' . $key . '_' . $paramKey, $paramValue); + } + } else { + newrelic_add_custom_parameter('extra_' . $key, $parameter); + } + } + } + + /** + * Checks whether the NewRelic extension is enabled in the system. + * + * @return bool + */ + protected function isNewRelicEnabled() + { + return extension_loaded('newrelic'); + } + + /** + * Returns the appname where this log should be sent. Each log can override the default appname, set in this + * handler's constructor, by providing the appname in it's context. + * + * @param array $context + * @return null|string + */ + protected function getAppName(array $context) + { + if (isset($context['appname'])) { + return $context['appname']; + } + + return $this->appName; + } + + /** + * Returns the name of the current transaction. Each log can override the default transaction name, set in this + * handler's constructor, by providing the transaction_name in it's context + * + * @param array $context + * + * @return null|string + */ + protected function getTransactionName(array $context) + { + if (isset($context['transaction_name'])) { + return $context['transaction_name']; + } + + return $this->transactionName; + } + + /** + * Sets the NewRelic application that should receive this log. + * + * @param string $appName + */ + protected function setNewRelicAppName($appName) + { + newrelic_set_appname($appName); + } + + /** + * Overwrites the name of the current transaction + * + * @param $transactionName + */ + protected function setNewRelicTransactionName($transactionName) + { + newrelic_name_transaction($transactionName); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php new file mode 100644 index 00000000..3754e45d --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php @@ -0,0 +1,45 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; + +/** + * Blackhole + * + * Any record it can handle will be thrown away. This can be used + * to put on top of an existing stack to override it temporarily. + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class NullHandler extends AbstractHandler +{ + /** + * @param integer $level The minimum logging level at which this handler will be triggered + */ + public function __construct($level = Logger::DEBUG) + { + parent::__construct($level, false); + } + + /** + * {@inheritdoc} + */ + public function handle(array $record) + { + if ($record['level'] < $this->level) { + return false; + } + + return true; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php new file mode 100644 index 00000000..1ae85845 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php @@ -0,0 +1,56 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Psr\Log\LoggerInterface; + +/** + * Proxies log messages to an existing PSR-3 compliant logger. + * + * @author Michael Moussa <michael.moussa@gmail.com> + */ +class PsrHandler extends AbstractHandler +{ + /** + * PSR-3 compliant logger + * + * @var LoggerInterface + */ + protected $logger; + + /** + * @param LoggerInterface $logger The underlying PSR-3 compliant logger to which messages will be proxied + * @param int $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct(LoggerInterface $logger, $level = Logger::DEBUG, $bubble = true) + { + parent::__construct($level, $bubble); + + $this->logger = $logger; + } + + /** + * {@inheritDoc} + */ + public function handle(array $record) + { + if (!$this->isHandling($record)) { + return false; + } + + $this->logger->log(strtolower($record['level_name']), $record['message'], $record['context']); + + return false === $this->bubble; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php new file mode 100644 index 00000000..cd2fcfa3 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php @@ -0,0 +1,172 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; + +/** + * Sends notifications through the pushover api to mobile phones + * + * @author Sebastian Göttschkes <sebastian.goettschkes@googlemail.com> + * @see https://www.pushover.net/api + */ +class PushoverHandler extends SocketHandler +{ + private $token; + private $users; + private $title; + private $user; + private $retry; + private $expire; + + private $highPriorityLevel; + private $emergencyLevel; + + /** + * All parameters that can be sent to Pushover + * @see https://pushover.net/api + * @var array + */ + private $parameterNames = array( + 'token' => true, + 'user' => true, + 'message' => true, + 'device' => true, + 'title' => true, + 'url' => true, + 'url_title' => true, + 'priority' => true, + 'timestamp' => true, + 'sound' => true, + 'retry' => true, + 'expire' => true, + 'callback' => true, + ); + + /** + * Sounds the api supports by default + * @see https://pushover.net/api#sounds + * @var array + */ + private $sounds = array( + 'pushover', 'bike', 'bugle', 'cashregister', 'classical', 'cosmic', 'falling', 'gamelan', 'incoming', + 'intermission', 'magic', 'mechanical', 'pianobar', 'siren', 'spacealarm', 'tugboat', 'alien', 'climb', + 'persistent', 'echo', 'updown', 'none', + ); + + /** + * @param string $token Pushover api token + * @param string|array $users Pushover user id or array of ids the message will be sent to + * @param string $title Title sent to the Pushover API + * @param integer $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param Boolean $useSSL Whether to connect via SSL. Required when pushing messages to users that are not + * the pushover.net app owner. OpenSSL is required for this option. + * @param integer $highPriorityLevel The minimum logging level at which this handler will start + * sending "high priority" requests to the Pushover API + * @param integer $emergencyLevel The minimum logging level at which this handler will start + * sending "emergency" requests to the Pushover API + * @param integer $retry The retry parameter specifies how often (in seconds) the Pushover servers will send the same notification to the user. + * @param integer $expire The expire parameter specifies how many seconds your notification will continue to be retried for (every retry seconds). + */ + public function __construct($token, $users, $title = null, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $highPriorityLevel = Logger::CRITICAL, $emergencyLevel = Logger::EMERGENCY, $retry = 30, $expire = 25200) + { + $connectionString = $useSSL ? 'ssl://api.pushover.net:443' : 'api.pushover.net:80'; + parent::__construct($connectionString, $level, $bubble); + + $this->token = $token; + $this->users = (array) $users; + $this->title = $title ?: gethostname(); + $this->highPriorityLevel = Logger::toMonologLevel($highPriorityLevel); + $this->emergencyLevel = Logger::toMonologLevel($emergencyLevel); + $this->retry = $retry; + $this->expire = $expire; + } + + protected function generateDataStream($record) + { + $content = $this->buildContent($record); + + return $this->buildHeader($content) . $content; + } + + private function buildContent($record) + { + // Pushover has a limit of 512 characters on title and message combined. + $maxMessageLength = 512 - strlen($this->title); + $message = substr($record['message'], 0, $maxMessageLength); + $timestamp = $record['datetime']->getTimestamp(); + + $dataArray = array( + 'token' => $this->token, + 'user' => $this->user, + 'message' => $message, + 'title' => $this->title, + 'timestamp' => $timestamp + ); + + if (isset($record['level']) && $record['level'] >= $this->emergencyLevel) { + $dataArray['priority'] = 2; + $dataArray['retry'] = $this->retry; + $dataArray['expire'] = $this->expire; + } elseif (isset($record['level']) && $record['level'] >= $this->highPriorityLevel) { + $dataArray['priority'] = 1; + } + + // First determine the available parameters + $context = array_intersect_key($record['context'], $this->parameterNames); + $extra = array_intersect_key($record['extra'], $this->parameterNames); + + // Least important info should be merged with subsequent info + $dataArray = array_merge($extra, $context, $dataArray); + + // Only pass sounds that are supported by the API + if (isset($dataArray['sound']) && !in_array($dataArray['sound'], $this->sounds)) { + unset($dataArray['sound']); + } + + return http_build_query($dataArray); + } + + private function buildHeader($content) + { + $header = "POST /1/messages.json HTTP/1.1\r\n"; + $header .= "Host: api.pushover.net\r\n"; + $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; + $header .= "Content-Length: " . strlen($content) . "\r\n"; + $header .= "\r\n"; + + return $header; + } + + protected function write(array $record) + { + foreach ($this->users as $user) { + $this->user = $user; + + parent::write($record); + $this->closeSocket(); + } + + $this->user = null; + } + + public function setHighPriorityLevel($value) + { + $this->highPriorityLevel = $value; + } + + public function setEmergencyLevel($value) + { + $this->emergencyLevel = $value; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php new file mode 100644 index 00000000..f5743cd6 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php @@ -0,0 +1,181 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\LineFormatter; +use Monolog\Formatter\FormatterInterface; +use Monolog\Logger; +use Raven_Client; + +/** + * Handler to send messages to a Sentry (https://github.com/getsentry/sentry) server + * using raven-php (https://github.com/getsentry/raven-php) + * + * @author Marc Abramowitz <marc@marc-abramowitz.com> + */ +class RavenHandler extends AbstractProcessingHandler +{ + /** + * Translates Monolog log levels to Raven log levels. + */ + private $logLevels = array( + Logger::DEBUG => Raven_Client::DEBUG, + Logger::INFO => Raven_Client::INFO, + Logger::NOTICE => Raven_Client::INFO, + Logger::WARNING => Raven_Client::WARNING, + Logger::ERROR => Raven_Client::ERROR, + Logger::CRITICAL => Raven_Client::FATAL, + Logger::ALERT => Raven_Client::FATAL, + Logger::EMERGENCY => Raven_Client::FATAL, + ); + + /** + * @var Raven_Client the client object that sends the message to the server + */ + protected $ravenClient; + + /** + * @var LineFormatter The formatter to use for the logs generated via handleBatch() + */ + protected $batchFormatter; + + /** + * @param Raven_Client $ravenClient + * @param integer $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct(Raven_Client $ravenClient, $level = Logger::DEBUG, $bubble = true) + { + parent::__construct($level, $bubble); + + $this->ravenClient = $ravenClient; + } + + /** + * {@inheritdoc} + */ + public function handleBatch(array $records) + { + $level = $this->level; + + // filter records based on their level + $records = array_filter($records, function ($record) use ($level) { + return $record['level'] >= $level; + }); + + if (!$records) { + return; + } + + // the record with the highest severity is the "main" one + $record = array_reduce($records, function ($highest, $record) { + if ($record['level'] >= $highest['level']) { + return $record; + } + + return $highest; + }); + + // the other ones are added as a context item + $logs = array(); + foreach ($records as $r) { + $logs[] = $this->processRecord($r); + } + + if ($logs) { + $record['context']['logs'] = (string) $this->getBatchFormatter()->formatBatch($logs); + } + + $this->handle($record); + } + + /** + * Sets the formatter for the logs generated by handleBatch(). + * + * @param FormatterInterface $formatter + */ + public function setBatchFormatter(FormatterInterface $formatter) + { + $this->batchFormatter = $formatter; + } + + /** + * Gets the formatter for the logs generated by handleBatch(). + * + * @return FormatterInterface + */ + public function getBatchFormatter() + { + if (!$this->batchFormatter) { + $this->batchFormatter = $this->getDefaultBatchFormatter(); + } + + return $this->batchFormatter; + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + $options = array(); + $options['level'] = $this->logLevels[$record['level']]; + $options['tags'] = array(); + if (!empty($record['extra']['tags'])) { + $options['tags'] = array_merge($options['tags'], $record['extra']['tags']); + unset($record['extra']['tags']); + } + if (!empty($record['context']['tags'])) { + $options['tags'] = array_merge($options['tags'], $record['context']['tags']); + unset($record['context']['tags']); + } + if (!empty($record['context']['logger'])) { + $options['logger'] = $record['context']['logger']; + unset($record['context']['logger']); + } else { + $options['logger'] = $record['channel']; + } + if (!empty($record['context'])) { + $options['extra']['context'] = $record['context']; + } + if (!empty($record['extra'])) { + $options['extra']['extra'] = $record['extra']; + } + + if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Exception) { + $options['extra']['message'] = $record['formatted']; + $this->ravenClient->captureException($record['context']['exception'], $options); + + return; + } + + $this->ravenClient->captureMessage($record['formatted'], array(), $options); + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new LineFormatter('[%channel%] %message%'); + } + + /** + * Gets the default formatter for the logs generated by handleBatch(). + * + * @return FormatterInterface + */ + protected function getDefaultBatchFormatter() + { + return new LineFormatter(); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php new file mode 100644 index 00000000..3fc7f34b --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php @@ -0,0 +1,58 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\Formatter\LineFormatter; + +/** + * Logs to a Redis key using rpush + * + * usage example: + * + * $log = new Logger('application'); + * $redis = new RedisHandler(new Predis\Client("tcp://localhost:6379"), "logs", "prod"); + * $log->pushHandler($redis); + * + * @author Thomas Tourlourat <thomas@tourlourat.com> + */ +class RedisHandler extends AbstractProcessingHandler +{ + private $redisClient; + private $redisKey; + + # redis instance, key to use + public function __construct($redis, $key, $level = Logger::DEBUG, $bubble = true) + { + if (!(($redis instanceof \Predis\Client) || ($redis instanceof \Redis))) { + throw new \InvalidArgumentException('Predis\Client or Redis instance required'); + } + + $this->redisClient = $redis; + $this->redisKey = $key; + + parent::__construct($level, $bubble); + } + + protected function write(array $record) + { + $this->redisClient->rpush($this->redisKey, $record["formatted"]); + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new LineFormatter(); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php new file mode 100644 index 00000000..81abf086 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php @@ -0,0 +1,73 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use RollbarNotifier; +use Exception; +use Monolog\Logger; + +/** + * Sends errors to Rollbar + * + * @author Paul Statezny <paulstatezny@gmail.com> + */ +class RollbarHandler extends AbstractProcessingHandler +{ + /** + * Rollbar notifier + * + * @var RollbarNotifier + */ + protected $rollbarNotifier; + + /** + * @param RollbarNotifier $rollbarNotifier RollbarNotifier object constructed with valid token + * @param integer $level The minimum logging level at which this handler will be triggered + * @param boolean $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct(RollbarNotifier $rollbarNotifier, $level = Logger::ERROR, $bubble = true) + { + $this->rollbarNotifier = $rollbarNotifier; + + parent::__construct($level, $bubble); + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + if (isset($record['context']['exception']) && $record['context']['exception'] instanceof Exception) { + $this->rollbarNotifier->report_exception($record['context']['exception']); + } else { + $extraData = array( + 'level' => $record['level'], + 'channel' => $record['channel'], + 'datetime' => $record['datetime']->format('U'), + ); + + $this->rollbarNotifier->report_message( + $record['message'], + $record['level_name'], + array_merge($record['context'], $record['extra'], $extraData) + ); + } + } + + /** + * {@inheritdoc} + */ + public function close() + { + $this->rollbarNotifier->flush(); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php new file mode 100644 index 00000000..4168c32f --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php @@ -0,0 +1,153 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; + +/** + * Stores logs to files that are rotated every day and a limited number of files are kept. + * + * This rotation is only intended to be used as a workaround. Using logrotate to + * handle the rotation is strongly encouraged when you can use it. + * + * @author Christophe Coevoet <stof@notk.org> + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class RotatingFileHandler extends StreamHandler +{ + protected $filename; + protected $maxFiles; + protected $mustRotate; + protected $nextRotation; + protected $filenameFormat; + protected $dateFormat; + + /** + * @param string $filename + * @param integer $maxFiles The maximal amount of files to keep (0 means unlimited) + * @param integer $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write) + * @param Boolean $useLocking Try to lock log file before doing any writes + */ + public function __construct($filename, $maxFiles = 0, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false) + { + $this->filename = $filename; + $this->maxFiles = (int) $maxFiles; + $this->nextRotation = new \DateTime('tomorrow'); + $this->filenameFormat = '{filename}-{date}'; + $this->dateFormat = 'Y-m-d'; + + parent::__construct($this->getTimedFilename(), $level, $bubble, $filePermission, $useLocking); + } + + /** + * {@inheritdoc} + */ + public function close() + { + parent::close(); + + if (true === $this->mustRotate) { + $this->rotate(); + } + } + + public function setFilenameFormat($filenameFormat, $dateFormat) + { + $this->filenameFormat = $filenameFormat; + $this->dateFormat = $dateFormat; + $this->url = $this->getTimedFilename(); + $this->close(); + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + // on the first record written, if the log is new, we should rotate (once per day) + if (null === $this->mustRotate) { + $this->mustRotate = !file_exists($this->url); + } + + if ($this->nextRotation < $record['datetime']) { + $this->mustRotate = true; + $this->close(); + } + + parent::write($record); + } + + /** + * Rotates the files. + */ + protected function rotate() + { + // update filename + $this->url = $this->getTimedFilename(); + $this->nextRotation = new \DateTime('tomorrow'); + + // skip GC of old logs if files are unlimited + if (0 === $this->maxFiles) { + return; + } + + $logFiles = glob($this->getGlobPattern()); + if ($this->maxFiles >= count($logFiles)) { + // no files to remove + return; + } + + // Sorting the files by name to remove the older ones + usort($logFiles, function ($a, $b) { + return strcmp($b, $a); + }); + + foreach (array_slice($logFiles, $this->maxFiles) as $file) { + if (is_writable($file)) { + unlink($file); + } + } + } + + protected function getTimedFilename() + { + $fileInfo = pathinfo($this->filename); + $timedFilename = str_replace( + array('{filename}', '{date}'), + array($fileInfo['filename'], date($this->dateFormat)), + $fileInfo['dirname'] . '/' . $this->filenameFormat + ); + + if (!empty($fileInfo['extension'])) { + $timedFilename .= '.'.$fileInfo['extension']; + } + + return $timedFilename; + } + + protected function getGlobPattern() + { + $fileInfo = pathinfo($this->filename); + $glob = str_replace( + array('{filename}', '{date}'), + array($fileInfo['filename'], '*'), + $fileInfo['dirname'] . '/' . $this->filenameFormat + ); + if (!empty($fileInfo['extension'])) { + $glob .= '.'.$fileInfo['extension']; + } + + return $glob; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php new file mode 100644 index 00000000..487e26f6 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php @@ -0,0 +1,83 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + + +/** + * Sampling handler + * + * A sampled event stream can be useful for logging high frequency events in + * a production environment where you only need an idea of what is happening + * and are not concerned with capturing every occurrence. Since the decision to + * handle or not handle a particular event is determined randomly, the + * resulting sampled log is not guaranteed to contain 1/N of the events that + * occurred in the application, but based on the Law of large numbers, it will + * tend to be close to this ratio with a large number of attempts. + * + * @author Bryan Davis <bd808@wikimedia.org> + * @author Kunal Mehta <legoktm@gmail.com> + */ +class SamplingHandler extends AbstractHandler +{ + /** + * @var callable|HandlerInterface $handler + */ + protected $handler; + + /** + * @var int $factor + */ + protected $factor; + + /** + * @param callable|HandlerInterface $handler Handler or factory callable($record, $fingersCrossedHandler). + * @param int $factor Sample factor + */ + public function __construct($handler, $factor) + { + parent::__construct(); + $this->handler = $handler; + $this->factor = $factor; + + if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) { + throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object"); + } + } + + public function isHandling(array $record) + { + return $this->handler->isHandling($record); + } + + public function handle(array $record) + { + if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) { + // The same logic as in FingersCrossedHandler + if (!$this->handler instanceof HandlerInterface) { + $this->handler = call_user_func($this->handler, $record, $this); + if (!$this->handler instanceof HandlerInterface) { + throw new \RuntimeException("The factory callable should return a HandlerInterface"); + } + } + + if ($this->processors) { + foreach ($this->processors as $processor) { + $record = call_user_func($processor, $record); + } + } + + $this->handler->handle($record); + } + + return false === $this->bubble; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php new file mode 100644 index 00000000..e3c8e11b --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php @@ -0,0 +1,234 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\Formatter\LineFormatter; + +/** + * Sends notifications through Slack API + * + * @author Greg Kedzierski <greg@gregkedzierski.com> + * @see https://api.slack.com/ + */ +class SlackHandler extends SocketHandler +{ + /** + * Slack API token + * @var string + */ + private $token; + + /** + * Slack channel (encoded ID or name) + * @var string + */ + private $channel; + + /** + * Name of a bot + * @var string + */ + private $username; + + /** + * Emoji icon name + * @var string + */ + private $iconEmoji; + + /** + * Whether the message should be added to Slack as attachment (plain text otherwise) + * @var bool + */ + private $useAttachment; + + /** + * Whether the the message that is added to Slack as attachment is in a short style (or not) + * @var bool + */ + private $useShortAttachment; + + /** + * Whether the attachment should include extra data (or not) + * @var bool + */ + private $includeExtra; + + /** + * @var LineFormatter + */ + private $lineFormatter; + + /** + * @param string $token Slack API token + * @param string $channel Slack channel (encoded ID or name) + * @param string $username Name of a bot + * @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise) + * @param string|null $iconEmoji The emoji name to use (or null) + * @param int $level The minimum logging level at which this handler will be triggered + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct($token, $channel, $username = 'Monolog', $useAttachment = true, $iconEmoji = null, $level = Logger::CRITICAL, $bubble = true, $useShortAttachment = false, $includeExtra = false) + { + if (!extension_loaded('openssl')) { + throw new MissingExtensionException('The OpenSSL PHP extension is required to use the SlackHandler'); + } + + parent::__construct('ssl://slack.com:443', $level, $bubble); + + $this->token = $token; + $this->channel = $channel; + $this->username = $username; + $this->iconEmoji = trim($iconEmoji, ':'); + $this->useAttachment = $useAttachment; + $this->useShortAttachment = $useShortAttachment; + $this->includeExtra = $includeExtra; + if ($this->includeExtra) { + $this->lineFormatter = new LineFormatter; + } + } + + /** + * {@inheritdoc} + * + * @param array $record + * @return string + */ + protected function generateDataStream($record) + { + $content = $this->buildContent($record); + + return $this->buildHeader($content) . $content; + } + + /** + * Builds the body of API call + * + * @param array $record + * @return string + */ + private function buildContent($record) + { + $dataArray = array( + 'token' => $this->token, + 'channel' => $this->channel, + 'username' => $this->username, + 'text' => '', + 'attachments' => array() + ); + + if ($this->useAttachment) { + $attachment = array( + 'fallback' => $record['message'], + 'color' => $this->getAttachmentColor($record['level']) + ); + + if ($this->useShortAttachment) { + $attachment['fields'] = array( + array( + 'title' => $record['level_name'], + 'value' => $record['message'], + 'short' => false + ) + ); + } else { + $attachment['fields'] = array( + array( + 'title' => 'Message', + 'value' => $record['message'], + 'short' => false + ), + array( + 'title' => 'Level', + 'value' => $record['level_name'], + 'short' => true + ) + ); + } + + if ($this->includeExtra) { + $extra = ''; + foreach ($record['extra'] as $var => $val) { + $extra .= $var.': '.$this->lineFormatter->stringify($val)." | "; + } + + $extra = rtrim($extra, " |"); + + $attachment['fields'][] = array( + 'title' => "Extra", + 'value' => $extra, + 'short' => false + ); + } + + $dataArray['attachments'] = json_encode(array($attachment)); + } else { + $dataArray['text'] = $record['message']; + } + + if ($this->iconEmoji) { + $dataArray['icon_emoji'] = ":{$this->iconEmoji}:"; + } + + return http_build_query($dataArray); + } + + /** + * Builds the header of the API Call + * + * @param string $content + * @return string + */ + private function buildHeader($content) + { + $header = "POST /api/chat.postMessage HTTP/1.1\r\n"; + $header .= "Host: slack.com\r\n"; + $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; + $header .= "Content-Length: " . strlen($content) . "\r\n"; + $header .= "\r\n"; + + return $header; + } + + /** + * {@inheritdoc} + * + * @param array $record + */ + protected function write(array $record) + { + parent::write($record); + $this->closeSocket(); + } + + /** + * Returned a Slack message attachment color associated with + * provided level. + * + * @param int $level + * @return string + */ + protected function getAttachmentColor($level) + { + switch (true) { + case $level >= Logger::ERROR: + return 'danger'; + case $level >= Logger::WARNING: + return 'warning'; + case $level >= Logger::INFO: + return 'good'; + default: + return '#e3e4e6'; + } + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php new file mode 100644 index 00000000..ee486f69 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php @@ -0,0 +1,284 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; + +/** + * Stores to any socket - uses fsockopen() or pfsockopen(). + * + * @author Pablo de Leon Belloc <pablolb@gmail.com> + * @see http://php.net/manual/en/function.fsockopen.php + */ +class SocketHandler extends AbstractProcessingHandler +{ + private $connectionString; + private $connectionTimeout; + private $resource; + private $timeout = 0; + private $persistent = false; + private $errno; + private $errstr; + + /** + * @param string $connectionString Socket connection string + * @param integer $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct($connectionString, $level = Logger::DEBUG, $bubble = true) + { + parent::__construct($level, $bubble); + $this->connectionString = $connectionString; + $this->connectionTimeout = (float) ini_get('default_socket_timeout'); + } + + /** + * Connect (if necessary) and write to the socket + * + * @param array $record + * + * @throws \UnexpectedValueException + * @throws \RuntimeException + */ + protected function write(array $record) + { + $this->connectIfNotConnected(); + $data = $this->generateDataStream($record); + $this->writeToSocket($data); + } + + /** + * We will not close a PersistentSocket instance so it can be reused in other requests. + */ + public function close() + { + if (!$this->isPersistent()) { + $this->closeSocket(); + } + } + + /** + * Close socket, if open + */ + public function closeSocket() + { + if (is_resource($this->resource)) { + fclose($this->resource); + $this->resource = null; + } + } + + /** + * Set socket connection to nbe persistent. It only has effect before the connection is initiated. + * + * @param type $boolean + */ + public function setPersistent($boolean) + { + $this->persistent = (boolean) $boolean; + } + + /** + * Set connection timeout. Only has effect before we connect. + * + * @param float $seconds + * + * @see http://php.net/manual/en/function.fsockopen.php + */ + public function setConnectionTimeout($seconds) + { + $this->validateTimeout($seconds); + $this->connectionTimeout = (float) $seconds; + } + + /** + * Set write timeout. Only has effect before we connect. + * + * @param float $seconds + * + * @see http://php.net/manual/en/function.stream-set-timeout.php + */ + public function setTimeout($seconds) + { + $this->validateTimeout($seconds); + $this->timeout = (float) $seconds; + } + + /** + * Get current connection string + * + * @return string + */ + public function getConnectionString() + { + return $this->connectionString; + } + + /** + * Get persistent setting + * + * @return boolean + */ + public function isPersistent() + { + return $this->persistent; + } + + /** + * Get current connection timeout setting + * + * @return float + */ + public function getConnectionTimeout() + { + return $this->connectionTimeout; + } + + /** + * Get current in-transfer timeout + * + * @return float + */ + public function getTimeout() + { + return $this->timeout; + } + + /** + * Check to see if the socket is currently available. + * + * UDP might appear to be connected but might fail when writing. See http://php.net/fsockopen for details. + * + * @return boolean + */ + public function isConnected() + { + return is_resource($this->resource) + && !feof($this->resource); // on TCP - other party can close connection. + } + + /** + * Wrapper to allow mocking + */ + protected function pfsockopen() + { + return @pfsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout); + } + + /** + * Wrapper to allow mocking + */ + protected function fsockopen() + { + return @fsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout); + } + + /** + * Wrapper to allow mocking + * + * @see http://php.net/manual/en/function.stream-set-timeout.php + */ + protected function streamSetTimeout() + { + $seconds = floor($this->timeout); + $microseconds = round(($this->timeout - $seconds)*1e6); + + return stream_set_timeout($this->resource, $seconds, $microseconds); + } + + /** + * Wrapper to allow mocking + */ + protected function fwrite($data) + { + return @fwrite($this->resource, $data); + } + + /** + * Wrapper to allow mocking + */ + protected function streamGetMetadata() + { + return stream_get_meta_data($this->resource); + } + + private function validateTimeout($value) + { + $ok = filter_var($value, FILTER_VALIDATE_FLOAT); + if ($ok === false || $value < 0) { + throw new \InvalidArgumentException("Timeout must be 0 or a positive float (got $value)"); + } + } + + private function connectIfNotConnected() + { + if ($this->isConnected()) { + return; + } + $this->connect(); + } + + protected function generateDataStream($record) + { + return (string) $record['formatted']; + } + + private function connect() + { + $this->createSocketResource(); + $this->setSocketTimeout(); + } + + private function createSocketResource() + { + if ($this->isPersistent()) { + $resource = $this->pfsockopen(); + } else { + $resource = $this->fsockopen(); + } + if (!$resource) { + throw new \UnexpectedValueException("Failed connecting to $this->connectionString ($this->errno: $this->errstr)"); + } + $this->resource = $resource; + } + + private function setSocketTimeout() + { + if (!$this->streamSetTimeout()) { + throw new \UnexpectedValueException("Failed setting timeout with stream_set_timeout()"); + } + } + + private function writeToSocket($data) + { + $length = strlen($data); + $sent = 0; + while ($this->isConnected() && $sent < $length) { + if (0 == $sent) { + $chunk = $this->fwrite($data); + } else { + $chunk = $this->fwrite(substr($data, $sent)); + } + if ($chunk === false) { + throw new \RuntimeException("Could not write to socket"); + } + $sent += $chunk; + $socketInfo = $this->streamGetMetadata(); + if ($socketInfo['timed_out']) { + throw new \RuntimeException("Write timed-out"); + } + } + if (!$this->isConnected() && $sent < $length) { + throw new \RuntimeException("End-of-file reached, probably we got disconnected (sent $sent of $length)"); + } + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php new file mode 100644 index 00000000..7965db74 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php @@ -0,0 +1,104 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; + +/** + * Stores to any stream resource + * + * Can be used to store into php://stderr, remote and local files, etc. + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class StreamHandler extends AbstractProcessingHandler +{ + protected $stream; + protected $url; + private $errorMessage; + protected $filePermission; + protected $useLocking; + + /** + * @param resource|string $stream + * @param integer $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write) + * @param Boolean $useLocking Try to lock log file before doing any writes + * + * @throws \InvalidArgumentException If stream is not a resource or string + */ + public function __construct($stream, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false) + { + parent::__construct($level, $bubble); + if (is_resource($stream)) { + $this->stream = $stream; + } elseif (is_string($stream)) { + $this->url = $stream; + } else { + throw new \InvalidArgumentException('A stream must either be a resource or a string.'); + } + + $this->filePermission = $filePermission; + $this->useLocking = $useLocking; + } + + /** + * {@inheritdoc} + */ + public function close() + { + if (is_resource($this->stream)) { + fclose($this->stream); + } + $this->stream = null; + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + if (!is_resource($this->stream)) { + if (!$this->url) { + throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().'); + } + $this->errorMessage = null; + set_error_handler(array($this, 'customErrorHandler')); + $this->stream = fopen($this->url, 'a'); + if ($this->filePermission !== null) { + @chmod($this->url, $this->filePermission); + } + restore_error_handler(); + if (!is_resource($this->stream)) { + $this->stream = null; + throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: '.$this->errorMessage, $this->url)); + } + } + + if ($this->useLocking) { + // ignoring errors here, there's not much we can do about them + flock($this->stream, LOCK_EX); + } + + fwrite($this->stream, (string) $record['formatted']); + + if ($this->useLocking) { + flock($this->stream, LOCK_UN); + } + } + + private function customErrorHandler($code, $msg) + { + $this->errorMessage = preg_replace('{^fopen\(.*?\): }', '', $msg); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php new file mode 100644 index 00000000..af321db2 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php @@ -0,0 +1,56 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; + +/** + * SwiftMailerHandler uses Swift_Mailer to send the emails + * + * @author Gyula Sallai + */ +class SwiftMailerHandler extends MailHandler +{ + protected $mailer; + protected $message; + + /** + * @param \Swift_Mailer $mailer The mailer to use + * @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced + * @param integer $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct(\Swift_Mailer $mailer, $message, $level = Logger::ERROR, $bubble = true) + { + parent::__construct($level, $bubble); + $this->mailer = $mailer; + if (!$message instanceof \Swift_Message && is_callable($message)) { + $message = call_user_func($message); + } + if (!$message instanceof \Swift_Message) { + throw new \InvalidArgumentException('You must provide either a Swift_Message instance or a callable returning it'); + } + $this->message = $message; + } + + /** + * {@inheritdoc} + */ + protected function send($content, array $records) + { + $message = clone $this->message; + $message->setBody($content); + $message->setDate(time()); + + $this->mailer->send($message); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php new file mode 100644 index 00000000..47c73e12 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php @@ -0,0 +1,67 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; + +/** + * Logs to syslog service. + * + * usage example: + * + * $log = new Logger('application'); + * $syslog = new SyslogHandler('myfacility', 'local6'); + * $formatter = new LineFormatter("%channel%.%level_name%: %message% %extra%"); + * $syslog->setFormatter($formatter); + * $log->pushHandler($syslog); + * + * @author Sven Paulus <sven@karlsruhe.org> + */ +class SyslogHandler extends AbstractSyslogHandler +{ + protected $ident; + protected $logopts; + + /** + * @param string $ident + * @param mixed $facility + * @param integer $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param int $logopts Option flags for the openlog() call, defaults to LOG_PID + */ + public function __construct($ident, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true, $logopts = LOG_PID) + { + parent::__construct($facility, $level, $bubble); + + $this->ident = $ident; + $this->logopts = $logopts; + } + + /** + * {@inheritdoc} + */ + public function close() + { + closelog(); + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + if (!openlog($this->ident, $this->logopts, $this->facility)) { + throw new \LogicException('Can\'t open syslog for ident "'.$this->ident.'" and facility "'.$this->facility.'"'); + } + syslog($this->logLevels[$record['level']], (string) $record['formatted']); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php b/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php new file mode 100644 index 00000000..dcf3f1f9 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php @@ -0,0 +1,46 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler\SyslogUdp; + +class UdpSocket +{ + const DATAGRAM_MAX_LENGTH = 65023; + + public function __construct($ip, $port = 514) + { + $this->ip = $ip; + $this->port = $port; + $this->socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); + } + + public function write($line, $header = "") + { + $this->send($this->assembleMessage($line, $header)); + } + + public function close() + { + socket_close($this->socket); + } + + protected function send($chunk) + { + socket_sendto($this->socket, $chunk, strlen($chunk), $flags = 0, $this->ip, $this->port); + } + + protected function assembleMessage($line, $header) + { + $chunkSize = self::DATAGRAM_MAX_LENGTH - strlen($header); + + return $header . substr($line, 0, $chunkSize); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php new file mode 100644 index 00000000..aa047c07 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php @@ -0,0 +1,80 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\Handler\SyslogUdp\UdpSocket; + +/** + * A Handler for logging to a remote syslogd server. + * + * @author Jesper Skovgaard Nielsen <nulpunkt@gmail.com> + */ +class SyslogUdpHandler extends AbstractSyslogHandler +{ + /** + * @param string $host + * @param int $port + * @param mixed $facility + * @param integer $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct($host, $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true) + { + parent::__construct($facility, $level, $bubble); + + $this->socket = new UdpSocket($host, $port ?: 514); + } + + protected function write(array $record) + { + $lines = $this->splitMessageIntoLines($record['formatted']); + + $header = $this->makeCommonSyslogHeader($this->logLevels[$record['level']]); + + foreach ($lines as $line) { + $this->socket->write($line, $header); + } + } + + public function close() + { + $this->socket->close(); + } + + private function splitMessageIntoLines($message) + { + if (is_array($message)) { + $message = implode("\n", $message); + } + + return preg_split('/$\R?^/m', $message); + } + + /** + * Make common syslog header (see rfc5424) + */ + protected function makeCommonSyslogHeader($severity) + { + $priority = $severity + $this->facility; + + return "<$priority>1 "; + } + + /** + * Inject your own socket, mainly used for testing + */ + public function setSocket($socket) + { + $this->socket = $socket; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php new file mode 100644 index 00000000..085d9e17 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php @@ -0,0 +1,140 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; + +/** + * Used for testing purposes. + * + * It records all records and gives you access to them for verification. + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class TestHandler extends AbstractProcessingHandler +{ + protected $records = array(); + protected $recordsByLevel = array(); + + public function getRecords() + { + return $this->records; + } + + public function hasEmergency($record) + { + return $this->hasRecord($record, Logger::EMERGENCY); + } + + public function hasAlert($record) + { + return $this->hasRecord($record, Logger::ALERT); + } + + public function hasCritical($record) + { + return $this->hasRecord($record, Logger::CRITICAL); + } + + public function hasError($record) + { + return $this->hasRecord($record, Logger::ERROR); + } + + public function hasWarning($record) + { + return $this->hasRecord($record, Logger::WARNING); + } + + public function hasNotice($record) + { + return $this->hasRecord($record, Logger::NOTICE); + } + + public function hasInfo($record) + { + return $this->hasRecord($record, Logger::INFO); + } + + public function hasDebug($record) + { + return $this->hasRecord($record, Logger::DEBUG); + } + + public function hasEmergencyRecords() + { + return isset($this->recordsByLevel[Logger::EMERGENCY]); + } + + public function hasAlertRecords() + { + return isset($this->recordsByLevel[Logger::ALERT]); + } + + public function hasCriticalRecords() + { + return isset($this->recordsByLevel[Logger::CRITICAL]); + } + + public function hasErrorRecords() + { + return isset($this->recordsByLevel[Logger::ERROR]); + } + + public function hasWarningRecords() + { + return isset($this->recordsByLevel[Logger::WARNING]); + } + + public function hasNoticeRecords() + { + return isset($this->recordsByLevel[Logger::NOTICE]); + } + + public function hasInfoRecords() + { + return isset($this->recordsByLevel[Logger::INFO]); + } + + public function hasDebugRecords() + { + return isset($this->recordsByLevel[Logger::DEBUG]); + } + + protected function hasRecord($record, $level) + { + if (!isset($this->recordsByLevel[$level])) { + return false; + } + + if (is_array($record)) { + $record = $record['message']; + } + + foreach ($this->recordsByLevel[$level] as $rec) { + if ($rec['message'] === $record) { + return true; + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + $this->recordsByLevel[$record['level']][] = $record; + $this->records[] = $record; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php new file mode 100644 index 00000000..05a88173 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php @@ -0,0 +1,57 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +/** + * Forwards records to multiple handlers suppressing failures of each handler + * and continuing through to give every handler a chance to succeed. + * + * @author Craig D'Amelio <craig@damelio.ca> + */ +class WhatFailureGroupHandler extends GroupHandler +{ + /** + * {@inheritdoc} + */ + public function handle(array $record) + { + if ($this->processors) { + foreach ($this->processors as $processor) { + $record = call_user_func($processor, $record); + } + } + + foreach ($this->handlers as $handler) { + try { + $handler->handle($record); + } catch (\Exception $e) { + // What failure? + } + } + + return false === $this->bubble; + } + + /** + * {@inheritdoc} + */ + public function handleBatch(array $records) + { + foreach ($this->handlers as $handler) { + try { + $handler->handleBatch($records); + } catch (\Exception $e) { + // What failure? + } + } + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php new file mode 100644 index 00000000..f22cf218 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php @@ -0,0 +1,95 @@ +<?php +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\NormalizerFormatter; +use Monolog\Logger; + +/** + * Handler sending logs to Zend Monitor + * + * @author Christian Bergau <cbergau86@gmail.com> + */ +class ZendMonitorHandler extends AbstractProcessingHandler +{ + /** + * Monolog level / ZendMonitor Custom Event priority map + * + * @var array + */ + protected $levelMap = array( + Logger::DEBUG => 1, + Logger::INFO => 2, + Logger::NOTICE => 3, + Logger::WARNING => 4, + Logger::ERROR => 5, + Logger::CRITICAL => 6, + Logger::ALERT => 7, + Logger::EMERGENCY => 0, + ); + + /** + * Construct + * + * @param int $level + * @param bool $bubble + * @throws MissingExtensionException + */ + public function __construct($level = Logger::DEBUG, $bubble = true) + { + if (!function_exists('zend_monitor_custom_event')) { + throw new MissingExtensionException('You must have Zend Server installed in order to use this handler'); + } + parent::__construct($level, $bubble); + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + $this->writeZendMonitorCustomEvent( + $this->levelMap[$record['level']], + $record['message'], + $record['formatted'] + ); + } + + /** + * Write a record to Zend Monitor + * + * @param int $level + * @param string $message + * @param array $formatted + */ + protected function writeZendMonitorCustomEvent($level, $message, $formatted) + { + zend_monitor_custom_event($level, $message, $formatted); + } + + /** + * {@inheritdoc} + */ + public function getDefaultFormatter() + { + return new NormalizerFormatter(); + } + + /** + * Get the level map + * + * @return array + */ + public function getLevelMap() + { + return $this->levelMap; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Logger.php b/vendor/monolog/monolog/src/Monolog/Logger.php new file mode 100644 index 00000000..4a38de7f --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Logger.php @@ -0,0 +1,615 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog; + +use Monolog\Handler\HandlerInterface; +use Monolog\Handler\StreamHandler; +use Psr\Log\LoggerInterface; +use Psr\Log\InvalidArgumentException; + +/** + * Monolog log channel + * + * It contains a stack of Handlers and a stack of Processors, + * and uses them to store records that are added to it. + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class Logger implements LoggerInterface +{ + /** + * Detailed debug information + */ + const DEBUG = 100; + + /** + * Interesting events + * + * Examples: User logs in, SQL logs. + */ + const INFO = 200; + + /** + * Uncommon events + */ + const NOTICE = 250; + + /** + * Exceptional occurrences that are not errors + * + * Examples: Use of deprecated APIs, poor use of an API, + * undesirable things that are not necessarily wrong. + */ + const WARNING = 300; + + /** + * Runtime errors + */ + const ERROR = 400; + + /** + * Critical conditions + * + * Example: Application component unavailable, unexpected exception. + */ + const CRITICAL = 500; + + /** + * Action must be taken immediately + * + * Example: Entire website down, database unavailable, etc. + * This should trigger the SMS alerts and wake you up. + */ + const ALERT = 550; + + /** + * Urgent alert. + */ + const EMERGENCY = 600; + + /** + * Monolog API version + * + * This is only bumped when API breaks are done and should + * follow the major version of the library + * + * @var int + */ + const API = 1; + + /** + * Logging levels from syslog protocol defined in RFC 5424 + * + * @var array $levels Logging levels + */ + protected static $levels = array( + 100 => 'DEBUG', + 200 => 'INFO', + 250 => 'NOTICE', + 300 => 'WARNING', + 400 => 'ERROR', + 500 => 'CRITICAL', + 550 => 'ALERT', + 600 => 'EMERGENCY', + ); + + /** + * @var \DateTimeZone + */ + protected static $timezone; + + /** + * @var string + */ + protected $name; + + /** + * The handler stack + * + * @var HandlerInterface[] + */ + protected $handlers; + + /** + * Processors that will process all log records + * + * To process records of a single handler instead, add the processor on that specific handler + * + * @var callable[] + */ + protected $processors; + + /** + * @param string $name The logging channel + * @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc. + * @param callable[] $processors Optional array of processors + */ + public function __construct($name, array $handlers = array(), array $processors = array()) + { + $this->name = $name; + $this->handlers = $handlers; + $this->processors = $processors; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Pushes a handler on to the stack. + * + * @param HandlerInterface $handler + */ + public function pushHandler(HandlerInterface $handler) + { + array_unshift($this->handlers, $handler); + } + + /** + * Pops a handler from the stack + * + * @return HandlerInterface + */ + public function popHandler() + { + if (!$this->handlers) { + throw new \LogicException('You tried to pop from an empty handler stack.'); + } + + return array_shift($this->handlers); + } + + /** + * @return HandlerInterface[] + */ + public function getHandlers() + { + return $this->handlers; + } + + /** + * Adds a processor on to the stack. + * + * @param callable $callback + */ + public function pushProcessor($callback) + { + if (!is_callable($callback)) { + throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), '.var_export($callback, true).' given'); + } + array_unshift($this->processors, $callback); + } + + /** + * Removes the processor on top of the stack and returns it. + * + * @return callable + */ + public function popProcessor() + { + if (!$this->processors) { + throw new \LogicException('You tried to pop from an empty processor stack.'); + } + + return array_shift($this->processors); + } + + /** + * @return callable[] + */ + public function getProcessors() + { + return $this->processors; + } + + /** + * Adds a log record. + * + * @param integer $level The logging level + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function addRecord($level, $message, array $context = array()) + { + if (!$this->handlers) { + $this->pushHandler(new StreamHandler('php://stderr', static::DEBUG)); + } + + $levelName = static::getLevelName($level); + + // check if any handler will handle this message so we can return early and save cycles + $handlerKey = null; + foreach ($this->handlers as $key => $handler) { + if ($handler->isHandling(array('level' => $level))) { + $handlerKey = $key; + break; + } + } + + if (null === $handlerKey) { + return false; + } + + if (!static::$timezone) { + static::$timezone = new \DateTimeZone(date_default_timezone_get() ?: 'UTC'); + } + + $record = array( + 'message' => (string) $message, + 'context' => $context, + 'level' => $level, + 'level_name' => $levelName, + 'channel' => $this->name, + 'datetime' => \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true)), static::$timezone)->setTimezone(static::$timezone), + 'extra' => array(), + ); + + foreach ($this->processors as $processor) { + $record = call_user_func($processor, $record); + } + while (isset($this->handlers[$handlerKey]) && + false === $this->handlers[$handlerKey]->handle($record)) { + $handlerKey++; + } + + return true; + } + + /** + * Adds a log record at the DEBUG level. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function addDebug($message, array $context = array()) + { + return $this->addRecord(static::DEBUG, $message, $context); + } + + /** + * Adds a log record at the INFO level. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function addInfo($message, array $context = array()) + { + return $this->addRecord(static::INFO, $message, $context); + } + + /** + * Adds a log record at the NOTICE level. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function addNotice($message, array $context = array()) + { + return $this->addRecord(static::NOTICE, $message, $context); + } + + /** + * Adds a log record at the WARNING level. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function addWarning($message, array $context = array()) + { + return $this->addRecord(static::WARNING, $message, $context); + } + + /** + * Adds a log record at the ERROR level. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function addError($message, array $context = array()) + { + return $this->addRecord(static::ERROR, $message, $context); + } + + /** + * Adds a log record at the CRITICAL level. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function addCritical($message, array $context = array()) + { + return $this->addRecord(static::CRITICAL, $message, $context); + } + + /** + * Adds a log record at the ALERT level. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function addAlert($message, array $context = array()) + { + return $this->addRecord(static::ALERT, $message, $context); + } + + /** + * Adds a log record at the EMERGENCY level. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function addEmergency($message, array $context = array()) + { + return $this->addRecord(static::EMERGENCY, $message, $context); + } + + /** + * Gets all supported logging levels. + * + * @return array Assoc array with human-readable level names => level codes. + */ + public static function getLevels() + { + return array_flip(static::$levels); + } + + /** + * Gets the name of the logging level. + * + * @param integer $level + * @return string + */ + public static function getLevelName($level) + { + if (!isset(static::$levels[$level])) { + throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels))); + } + + return static::$levels[$level]; + } + + /** + * Converts PSR-3 levels to Monolog ones if necessary + * + * @param string|int Level number (monolog) or name (PSR-3) + * @return int + */ + public static function toMonologLevel($level) + { + if (is_string($level) && defined(__CLASS__.'::'.strtoupper($level))) { + return constant(__CLASS__.'::'.strtoupper($level)); + } + + return $level; + } + + /** + * Checks whether the Logger has a handler that listens on the given level + * + * @param integer $level + * @return Boolean + */ + public function isHandling($level) + { + $record = array( + 'level' => $level, + ); + + foreach ($this->handlers as $handler) { + if ($handler->isHandling($record)) { + return true; + } + } + + return false; + } + + /** + * Adds a log record at an arbitrary level. + * + * This method allows for compatibility with common interfaces. + * + * @param mixed $level The log level + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function log($level, $message, array $context = array()) + { + if (is_string($level) && defined(__CLASS__.'::'.strtoupper($level))) { + $level = constant(__CLASS__.'::'.strtoupper($level)); + } + + return $this->addRecord($level, $message, $context); + } + + /** + * Adds a log record at the DEBUG level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function debug($message, array $context = array()) + { + return $this->addRecord(static::DEBUG, $message, $context); + } + + /** + * Adds a log record at the INFO level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function info($message, array $context = array()) + { + return $this->addRecord(static::INFO, $message, $context); + } + + /** + * Adds a log record at the NOTICE level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function notice($message, array $context = array()) + { + return $this->addRecord(static::NOTICE, $message, $context); + } + + /** + * Adds a log record at the WARNING level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function warn($message, array $context = array()) + { + return $this->addRecord(static::WARNING, $message, $context); + } + + /** + * Adds a log record at the WARNING level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function warning($message, array $context = array()) + { + return $this->addRecord(static::WARNING, $message, $context); + } + + /** + * Adds a log record at the ERROR level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function err($message, array $context = array()) + { + return $this->addRecord(static::ERROR, $message, $context); + } + + /** + * Adds a log record at the ERROR level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function error($message, array $context = array()) + { + return $this->addRecord(static::ERROR, $message, $context); + } + + /** + * Adds a log record at the CRITICAL level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function crit($message, array $context = array()) + { + return $this->addRecord(static::CRITICAL, $message, $context); + } + + /** + * Adds a log record at the CRITICAL level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function critical($message, array $context = array()) + { + return $this->addRecord(static::CRITICAL, $message, $context); + } + + /** + * Adds a log record at the ALERT level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function alert($message, array $context = array()) + { + return $this->addRecord(static::ALERT, $message, $context); + } + + /** + * Adds a log record at the EMERGENCY level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function emerg($message, array $context = array()) + { + return $this->addRecord(static::EMERGENCY, $message, $context); + } + + /** + * Adds a log record at the EMERGENCY level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function emergency($message, array $context = array()) + { + return $this->addRecord(static::EMERGENCY, $message, $context); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php new file mode 100644 index 00000000..1899400d --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php @@ -0,0 +1,64 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +use Monolog\Logger; + +/** + * Injects Git branch and Git commit SHA in all records + * + * @author Nick Otter + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class GitProcessor +{ + private $level; + private static $cache; + + public function __construct($level = Logger::DEBUG) + { + $this->level = Logger::toMonologLevel($level); + } + + /** + * @param array $record + * @return array + */ + public function __invoke(array $record) + { + // return if the level is not high enough + if ($record['level'] < $this->level) { + return $record; + } + + $record['extra']['git'] = self::getGitInfo(); + + return $record; + } + + private static function getGitInfo() + { + if (self::$cache) { + return self::$cache; + } + + $branches = `git branch -v --no-abbrev`; + if (preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) { + return self::$cache = array( + 'branch' => $matches[1], + 'commit' => $matches[2], + ); + } + + return self::$cache = array(); + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php new file mode 100644 index 00000000..294a295c --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php @@ -0,0 +1,82 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +use Monolog\Logger; + +/** + * Injects line/file:class/function where the log message came from + * + * Warning: This only works if the handler processes the logs directly. + * If you put the processor on a handler that is behind a FingersCrossedHandler + * for example, the processor will only be called once the trigger level is reached, + * and all the log records will have the same file/line/.. data from the call that + * triggered the FingersCrossedHandler. + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class IntrospectionProcessor +{ + private $level; + + private $skipClassesPartials; + + public function __construct($level = Logger::DEBUG, array $skipClassesPartials = array('Monolog\\')) + { + $this->level = Logger::toMonologLevel($level); + $this->skipClassesPartials = $skipClassesPartials; + } + + /** + * @param array $record + * @return array + */ + public function __invoke(array $record) + { + // return if the level is not high enough + if ($record['level'] < $this->level) { + return $record; + } + + $trace = debug_backtrace(); + + // skip first since it's always the current method + array_shift($trace); + // the call_user_func call is also skipped + array_shift($trace); + + $i = 0; + + while (isset($trace[$i]['class'])) { + foreach ($this->skipClassesPartials as $part) { + if (strpos($trace[$i]['class'], $part) !== false) { + $i++; + continue 2; + } + } + break; + } + + // we should have the call source now + $record['extra'] = array_merge( + $record['extra'], + array( + 'file' => isset($trace[$i-1]['file']) ? $trace[$i-1]['file'] : null, + 'line' => isset($trace[$i-1]['line']) ? $trace[$i-1]['line'] : null, + 'class' => isset($trace[$i]['class']) ? $trace[$i]['class'] : null, + 'function' => isset($trace[$i]['function']) ? $trace[$i]['function'] : null, + ) + ); + + return $record; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php new file mode 100644 index 00000000..552fd709 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php @@ -0,0 +1,40 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +/** + * Injects memory_get_peak_usage in all records + * + * @see Monolog\Processor\MemoryProcessor::__construct() for options + * @author Rob Jensen + */ +class MemoryPeakUsageProcessor extends MemoryProcessor +{ + /** + * @param array $record + * @return array + */ + public function __invoke(array $record) + { + $bytes = memory_get_peak_usage($this->realUsage); + $formatted = $this->formatBytes($bytes); + + $record['extra'] = array_merge( + $record['extra'], + array( + 'memory_peak_usage' => $formatted, + ) + ); + + return $record; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php new file mode 100644 index 00000000..0820def4 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php @@ -0,0 +1,63 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +/** + * Some methods that are common for all memory processors + * + * @author Rob Jensen + */ +abstract class MemoryProcessor +{ + /** + * @var boolean If true, get the real size of memory allocated from system. Else, only the memory used by emalloc() is reported. + */ + protected $realUsage; + + /** + * @var boolean If true, then format memory size to human readable string (MB, KB, B depending on size) + */ + protected $useFormatting; + + /** + * @param boolean $realUsage Set this to true to get the real size of memory allocated from system. + * @param boolean $useFormatting If true, then format memory size to human readable string (MB, KB, B depending on size) + */ + public function __construct($realUsage = true, $useFormatting = true) + { + $this->realUsage = (boolean) $realUsage; + $this->useFormatting = (boolean) $useFormatting; + } + + /** + * Formats bytes into a human readable string if $this->useFormatting is true, otherwise return $bytes as is + * + * @param int $bytes + * @return string|int Formatted string if $this->useFormatting is true, otherwise return $bytes as is + */ + protected function formatBytes($bytes) + { + $bytes = (int) $bytes; + + if (!$this->useFormatting) { + return $bytes; + } + + if ($bytes > 1024*1024) { + return round($bytes/1024/1024, 2).' MB'; + } elseif ($bytes > 1024) { + return round($bytes/1024, 2).' KB'; + } + + return $bytes . ' B'; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php new file mode 100644 index 00000000..0c4dd9ab --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php @@ -0,0 +1,40 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +/** + * Injects memory_get_usage in all records + * + * @see Monolog\Processor\MemoryProcessor::__construct() for options + * @author Rob Jensen + */ +class MemoryUsageProcessor extends MemoryProcessor +{ + /** + * @param array $record + * @return array + */ + public function __invoke(array $record) + { + $bytes = memory_get_usage($this->realUsage); + $formatted = $this->formatBytes($bytes); + + $record['extra'] = array_merge( + $record['extra'], + array( + 'memory_usage' => $formatted, + ) + ); + + return $record; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php new file mode 100644 index 00000000..9d3f5590 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php @@ -0,0 +1,31 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +/** + * Adds value of getmypid into records + * + * @author Andreas Hörnicke + */ +class ProcessIdProcessor +{ + /** + * @param array $record + * @return array + */ + public function __invoke(array $record) + { + $record['extra']['process_id'] = getmypid(); + + return $record; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php new file mode 100644 index 00000000..c2686ce5 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php @@ -0,0 +1,48 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +/** + * Processes a record's message according to PSR-3 rules + * + * It replaces {foo} with the value from $context['foo'] + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class PsrLogMessageProcessor +{ + /** + * @param array $record + * @return array + */ + public function __invoke(array $record) + { + if (false === strpos($record['message'], '{')) { + return $record; + } + + $replacements = array(); + foreach ($record['context'] as $key => $val) { + if (is_null($val) || is_scalar($val) || (is_object($val) && method_exists($val, "__toString"))) { + $replacements['{'.$key.'}'] = $val; + } elseif (is_object($val)) { + $replacements['{'.$key.'}'] = '[object '.get_class($val).']'; + } else { + $replacements['{'.$key.'}'] = '['.gettype($val).']'; + } + } + + $record['message'] = strtr($record['message'], $replacements); + + return $record; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php new file mode 100644 index 00000000..2784cef4 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php @@ -0,0 +1,34 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +/** + * Adds a tags array into record + * + * @author Martijn Riemers + */ +class TagProcessor +{ + private $tags; + + public function __construct(array $tags = array()) + { + $this->tags = $tags; + } + + public function __invoke(array $record) + { + $record['extra']['tags'] = $this->tags; + + return $record; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php new file mode 100644 index 00000000..80270d08 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php @@ -0,0 +1,38 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +/** + * Adds a unique identifier into records + * + * @author Simon Mönch <sm@webfactory.de> + */ +class UidProcessor +{ + private $uid; + + public function __construct($length = 7) + { + if (!is_int($length) || $length > 32 || $length < 1) { + throw new \InvalidArgumentException('The uid length must be an integer between 1 and 32'); + } + + $this->uid = substr(hash('md5', uniqid('', true)), 0, $length); + } + + public function __invoke(array $record) + { + $record['extra']['uid'] = $this->uid; + + return $record; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php new file mode 100644 index 00000000..21f22a6e --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php @@ -0,0 +1,105 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +/** + * Injects url/method and remote IP of the current web request in all records + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class WebProcessor +{ + /** + * @var array|\ArrayAccess + */ + protected $serverData; + + /** + * @var array + */ + protected $extraFields = array( + 'url' => 'REQUEST_URI', + 'ip' => 'REMOTE_ADDR', + 'http_method' => 'REQUEST_METHOD', + 'server' => 'SERVER_NAME', + 'referrer' => 'HTTP_REFERER', + ); + + /** + * @param array|\ArrayAccess $serverData Array or object w/ ArrayAccess that provides access to the $_SERVER data + * @param array|null $extraFields Extra field names to be added (all available by default) + */ + public function __construct($serverData = null, array $extraFields = null) + { + if (null === $serverData) { + $this->serverData = &$_SERVER; + } elseif (is_array($serverData) || $serverData instanceof \ArrayAccess) { + $this->serverData = $serverData; + } else { + throw new \UnexpectedValueException('$serverData must be an array or object implementing ArrayAccess.'); + } + + if (null !== $extraFields) { + foreach (array_keys($this->extraFields) as $fieldName) { + if (!in_array($fieldName, $extraFields)) { + unset($this->extraFields[$fieldName]); + } + } + } + } + + /** + * @param array $record + * @return array + */ + public function __invoke(array $record) + { + // skip processing if for some reason request data + // is not present (CLI or wonky SAPIs) + if (!isset($this->serverData['REQUEST_URI'])) { + return $record; + } + + $record['extra'] = $this->appendExtraFields($record['extra']); + + return $record; + } + + /** + * @param string $extraName + * @param string $serverName + * @return $this + */ + public function addExtraField($extraName, $serverName) + { + $this->extraFields[$extraName] = $serverName; + + return $this; + } + + /** + * @param array $extra + * @return array + */ + private function appendExtraFields(array $extra) + { + foreach ($this->extraFields as $extraName => $serverName) { + $extra[$extraName] = isset($this->serverData[$serverName]) ? $this->serverData[$serverName] : null; + } + + if (isset($this->serverData['UNIQUE_ID'])) { + $extra['unique_id'] = $this->serverData['UNIQUE_ID']; + } + + return $extra; + } +} diff --git a/vendor/monolog/monolog/src/Monolog/Registry.php b/vendor/monolog/monolog/src/Monolog/Registry.php new file mode 100644 index 00000000..a3eba079 --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Registry.php @@ -0,0 +1,118 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog; + +use InvalidArgumentException; + +/** + * Monolog log registry + * + * Allows to get `Logger` instances in the global scope + * via static method calls on this class. + * + * <code> + * $application = new Monolog\Logger('application'); + * $api = new Monolog\Logger('api'); + * + * Monolog\Registry::addLogger($application); + * Monolog\Registry::addLogger($api); + * + * function testLogger() + * { + * Monolog\Registry::api()->addError('Sent to $api Logger instance'); + * Monolog\Registry::application()->addError('Sent to $application Logger instance'); + * } + * </code> + * + * @author Tomas Tatarko <tomas@tatarko.sk> + */ +class Registry +{ + /** + * List of all loggers in the registry (ba named indexes) + * + * @var Logger[] + */ + private static $loggers = array(); + + /** + * Adds new logging channel to the registry + * + * @param Logger $logger Instance of the logging channel + * @param string|null $name Name of the logging channel ($logger->getName() by default) + * @param boolean $overwrite Overwrite instance in the registry if the given name already exists? + * @throws \InvalidArgumentException If $overwrite set to false and named Logger instance already exists + */ + public static function addLogger(Logger $logger, $name = null, $overwrite = false) + { + $name = $name ?: $logger->getName(); + + if (isset(self::$loggers[$name]) && !$overwrite) { + throw new InvalidArgumentException('Logger with the given name already exists'); + } + + self::$loggers[$name] = $logger; + } + + /** + * Removes instance from registry by name or instance + * + * @param string|Logger $logger Name or logger instance + */ + public static function removeLogger($logger) + { + if ($logger instanceof Logger) { + if (false !== ($idx = array_search($logger, self::$loggers, true))) { + unset(self::$loggers[$idx]); + } + } else { + unset(self::$loggers[$logger]); + } + } + + /** + * Clears the registry + */ + public static function clear() + { + self::$loggers = array(); + } + + /** + * Gets Logger instance from the registry + * + * @param string $name Name of the requested Logger instance + * @return Logger Requested instance of Logger + * @throws \InvalidArgumentException If named Logger instance is not in the registry + */ + public static function getInstance($name) + { + if (!isset(self::$loggers[$name])) { + throw new InvalidArgumentException(sprintf('Requested "%s" logger instance is not in the registry', $name)); + } + + return self::$loggers[$name]; + } + + /** + * Gets Logger instance from the registry via static method call + * + * @param string $name Name of the requested Logger instance + * @param array $arguments Arguments passed to static method call + * @return Logger Requested instance of Logger + * @throws \InvalidArgumentException If named Logger instance is not in the registry + */ + public static function __callStatic($name, $arguments) + { + return self::getInstance($name); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/ErrorHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/ErrorHandlerTest.php new file mode 100644 index 00000000..a9a3f301 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/ErrorHandlerTest.php @@ -0,0 +1,31 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog; + +use Monolog\Handler\TestHandler; + +class ErrorHandlerTest extends \PHPUnit_Framework_TestCase +{ + public function testHandleError() + { + $logger = new Logger('test', array($handler = new TestHandler)); + $errHandler = new ErrorHandler($logger); + + $errHandler->registerErrorHandler(array(E_USER_NOTICE => Logger::EMERGENCY), false); + trigger_error('Foo', E_USER_ERROR); + $this->assertCount(1, $handler->getRecords()); + $this->assertTrue($handler->hasErrorRecords()); + trigger_error('Foo', E_USER_NOTICE); + $this->assertCount(2, $handler->getRecords()); + $this->assertTrue($handler->hasEmergencyRecords()); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Formatter/ChromePHPFormatterTest.php b/vendor/monolog/monolog/tests/Monolog/Formatter/ChromePHPFormatterTest.php new file mode 100644 index 00000000..e7f7334e --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Formatter/ChromePHPFormatterTest.php @@ -0,0 +1,158 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +use Monolog\Logger; + +class ChromePHPFormatterTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Monolog\Formatter\ChromePHPFormatter::format + */ + public function testDefaultFormat() + { + $formatter = new ChromePHPFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('ip' => '127.0.0.1'), + 'message' => 'log', + ); + + $message = $formatter->format($record); + + $this->assertEquals( + array( + 'meh', + array( + 'message' => 'log', + 'context' => array('from' => 'logger'), + 'extra' => array('ip' => '127.0.0.1'), + ), + 'unknown', + 'error' + ), + $message + ); + } + + /** + * @covers Monolog\Formatter\ChromePHPFormatter::format + */ + public function testFormatWithFileAndLine() + { + $formatter = new ChromePHPFormatter(); + $record = array( + 'level' => Logger::CRITICAL, + 'level_name' => 'CRITICAL', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('ip' => '127.0.0.1', 'file' => 'test', 'line' => 14), + 'message' => 'log', + ); + + $message = $formatter->format($record); + + $this->assertEquals( + array( + 'meh', + array( + 'message' => 'log', + 'context' => array('from' => 'logger'), + 'extra' => array('ip' => '127.0.0.1'), + ), + 'test : 14', + 'error' + ), + $message + ); + } + + /** + * @covers Monolog\Formatter\ChromePHPFormatter::format + */ + public function testFormatWithoutContext() + { + $formatter = new ChromePHPFormatter(); + $record = array( + 'level' => Logger::DEBUG, + 'level_name' => 'DEBUG', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ); + + $message = $formatter->format($record); + + $this->assertEquals( + array( + 'meh', + 'log', + 'unknown', + 'log' + ), + $message + ); + } + + /** + * @covers Monolog\Formatter\ChromePHPFormatter::formatBatch + */ + public function testBatchFormatThrowException() + { + $formatter = new ChromePHPFormatter(); + $records = array( + array( + 'level' => Logger::INFO, + 'level_name' => 'INFO', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ), + array( + 'level' => Logger::WARNING, + 'level_name' => 'WARNING', + 'channel' => 'foo', + 'context' => array(), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log2', + ), + ); + + $this->assertEquals( + array( + array( + 'meh', + 'log', + 'unknown', + 'info' + ), + array( + 'foo', + 'log2', + 'unknown', + 'warn' + ), + ), + $formatter->formatBatch($records) + ); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Formatter/ElasticaFormatterTest.php b/vendor/monolog/monolog/tests/Monolog/Formatter/ElasticaFormatterTest.php new file mode 100644 index 00000000..546e5c26 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Formatter/ElasticaFormatterTest.php @@ -0,0 +1,79 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +use Monolog\Logger; + +class ElasticaFormatterTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + if (!class_exists("Elastica\Document")) { + $this->markTestSkipped("ruflin/elastica not installed"); + } + } + + /** + * @covers Monolog\Formatter\ElasticaFormatter::__construct + * @covers Monolog\Formatter\ElasticaFormatter::format + * @covers Monolog\Formatter\ElasticaFormatter::getDocument + */ + public function testFormat() + { + // test log message + $msg = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('foo' => 7, 'bar', 'class' => new \stdClass), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ); + + // expected values + $expected = $msg; + $expected['datetime'] = '1970-01-01T00:00:00+0000'; + $expected['context'] = array( + 'class' => '[object] (stdClass: {})', + 'foo' => 7, + 0 => 'bar', + ); + + // format log message + $formatter = new ElasticaFormatter('my_index', 'doc_type'); + $doc = $formatter->format($msg); + $this->assertInstanceOf('Elastica\Document', $doc); + + // Document parameters + $params = $doc->getParams(); + $this->assertEquals('my_index', $params['_index']); + $this->assertEquals('doc_type', $params['_type']); + + // Document data values + $data = $doc->getData(); + foreach (array_keys($expected) as $key) { + $this->assertEquals($expected[$key], $data[$key]); + } + } + + /** + * @covers Monolog\Formatter\ElasticaFormatter::getIndex + * @covers Monolog\Formatter\ElasticaFormatter::getType + */ + public function testGetters() + { + $formatter = new ElasticaFormatter('my_index', 'doc_type'); + $this->assertEquals('my_index', $formatter->getIndex()); + $this->assertEquals('doc_type', $formatter->getType()); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Formatter/FlowdockFormatterTest.php b/vendor/monolog/monolog/tests/Monolog/Formatter/FlowdockFormatterTest.php new file mode 100644 index 00000000..1b2fd97a --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Formatter/FlowdockFormatterTest.php @@ -0,0 +1,55 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +use Monolog\Logger; +use Monolog\TestCase; + +class FlowdockFormatterTest extends TestCase +{ + /** + * @covers Monolog\Formatter\FlowdockFormatter::format + */ + public function testFormat() + { + $formatter = new FlowdockFormatter('test_source', 'source@test.com'); + $record = $this->getRecord(); + + $expected = array( + 'source' => 'test_source', + 'from_address' => 'source@test.com', + 'subject' => 'in test_source: WARNING - test', + 'content' => 'test', + 'tags' => array('#logs', '#warning', '#test'), + 'project' => 'test_source', + ); + $formatted = $formatter->format($record); + + $this->assertEquals($expected, $formatted['flowdock']); + } + + /** + * @ covers Monolog\Formatter\FlowdockFormatter::formatBatch + */ + public function testFormatBatch() + { + $formatter = new FlowdockFormatter('test_source', 'source@test.com'); + $records = array( + $this->getRecord(Logger::WARNING), + $this->getRecord(Logger::DEBUG), + ); + $formatted = $formatter->formatBatch($records); + + $this->assertArrayHasKey('flowdock', $formatted[0]); + $this->assertArrayHasKey('flowdock', $formatted[1]); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Formatter/GelfMessageFormatterTest.php b/vendor/monolog/monolog/tests/Monolog/Formatter/GelfMessageFormatterTest.php new file mode 100644 index 00000000..3f47a09a --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Formatter/GelfMessageFormatterTest.php @@ -0,0 +1,189 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +use Monolog\Logger; + +class GelfMessageFormatterTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + if (!class_exists('\Gelf\Message')) { + $this->markTestSkipped("graylog2/gelf-php or mlehner/gelf-php is not installed"); + } + } + + /** + * @covers Monolog\Formatter\GelfMessageFormatter::format + */ + public function testDefaultFormatter() + { + $formatter = new GelfMessageFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ); + + $message = $formatter->format($record); + + $this->assertInstanceOf('Gelf\Message', $message); + $this->assertEquals(0, $message->getTimestamp()); + $this->assertEquals('log', $message->getShortMessage()); + $this->assertEquals('meh', $message->getFacility()); + $this->assertEquals(null, $message->getLine()); + $this->assertEquals(null, $message->getFile()); + $this->assertEquals($this->isLegacy() ? 3 : 'error', $message->getLevel()); + $this->assertNotEmpty($message->getHost()); + + $formatter = new GelfMessageFormatter('mysystem'); + + $message = $formatter->format($record); + + $this->assertInstanceOf('Gelf\Message', $message); + $this->assertEquals('mysystem', $message->getHost()); + } + + /** + * @covers Monolog\Formatter\GelfMessageFormatter::format + */ + public function testFormatWithFileAndLine() + { + $formatter = new GelfMessageFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('file' => 'test', 'line' => 14), + 'message' => 'log', + ); + + $message = $formatter->format($record); + + $this->assertInstanceOf('Gelf\Message', $message); + $this->assertEquals('test', $message->getFile()); + $this->assertEquals(14, $message->getLine()); + } + + /** + * @covers Monolog\Formatter\GelfMessageFormatter::format + */ + public function testFormatWithContext() + { + $formatter = new GelfMessageFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('key' => 'pair'), + 'message' => 'log' + ); + + $message = $formatter->format($record); + + $this->assertInstanceOf('Gelf\Message', $message); + + $message_array = $message->toArray(); + + $this->assertArrayHasKey('_ctxt_from', $message_array); + $this->assertEquals('logger', $message_array['_ctxt_from']); + + // Test with extraPrefix + $formatter = new GelfMessageFormatter(null, null, 'CTX'); + $message = $formatter->format($record); + + $this->assertInstanceOf('Gelf\Message', $message); + + $message_array = $message->toArray(); + + $this->assertArrayHasKey('_CTXfrom', $message_array); + $this->assertEquals('logger', $message_array['_CTXfrom']); + } + + /** + * @covers Monolog\Formatter\GelfMessageFormatter::format + */ + public function testFormatWithContextContainingException() + { + $formatter = new GelfMessageFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger', 'exception' => array( + 'class' => '\Exception', + 'file' => '/some/file/in/dir.php:56', + 'trace' => array('/some/file/1.php:23', '/some/file/2.php:3') + )), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log' + ); + + $message = $formatter->format($record); + + $this->assertInstanceOf('Gelf\Message', $message); + + $this->assertEquals("/some/file/in/dir.php", $message->getFile()); + $this->assertEquals("56", $message->getLine()); + } + + /** + * @covers Monolog\Formatter\GelfMessageFormatter::format + */ + public function testFormatWithExtra() + { + $formatter = new GelfMessageFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('key' => 'pair'), + 'message' => 'log' + ); + + $message = $formatter->format($record); + + $this->assertInstanceOf('Gelf\Message', $message); + + $message_array = $message->toArray(); + + $this->assertArrayHasKey('_key', $message_array); + $this->assertEquals('pair', $message_array['_key']); + + // Test with extraPrefix + $formatter = new GelfMessageFormatter(null, 'EXT'); + $message = $formatter->format($record); + + $this->assertInstanceOf('Gelf\Message', $message); + + $message_array = $message->toArray(); + + $this->assertArrayHasKey('_EXTkey', $message_array); + $this->assertEquals('pair', $message_array['_EXTkey']); + } + + private function isLegacy() + { + return interface_exists('\Gelf\IMessagePublisher'); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Formatter/JsonFormatterTest.php b/vendor/monolog/monolog/tests/Monolog/Formatter/JsonFormatterTest.php new file mode 100644 index 00000000..69e20077 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Formatter/JsonFormatterTest.php @@ -0,0 +1,78 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +use Monolog\Logger; +use Monolog\TestCase; + +class JsonFormatterTest extends TestCase +{ + /** + * @covers Monolog\Formatter\JsonFormatter::__construct + * @covers Monolog\Formatter\JsonFormatter::getBatchMode + * @covers Monolog\Formatter\JsonFormatter::isAppendingNewlines + */ + public function testConstruct() + { + $formatter = new JsonFormatter(); + $this->assertEquals(JsonFormatter::BATCH_MODE_JSON, $formatter->getBatchMode()); + $this->assertEquals(true, $formatter->isAppendingNewlines()); + $formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_NEWLINES, false); + $this->assertEquals(JsonFormatter::BATCH_MODE_NEWLINES, $formatter->getBatchMode()); + $this->assertEquals(false, $formatter->isAppendingNewlines()); + } + + /** + * @covers Monolog\Formatter\JsonFormatter::format + */ + public function testFormat() + { + $formatter = new JsonFormatter(); + $record = $this->getRecord(); + $this->assertEquals(json_encode($record)."\n", $formatter->format($record)); + + $formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false); + $record = $this->getRecord(); + $this->assertEquals(json_encode($record), $formatter->format($record)); + } + + /** + * @covers Monolog\Formatter\JsonFormatter::formatBatch + * @covers Monolog\Formatter\JsonFormatter::formatBatchJson + */ + public function testFormatBatch() + { + $formatter = new JsonFormatter(); + $records = array( + $this->getRecord(Logger::WARNING), + $this->getRecord(Logger::DEBUG), + ); + $this->assertEquals(json_encode($records), $formatter->formatBatch($records)); + } + + /** + * @covers Monolog\Formatter\JsonFormatter::formatBatch + * @covers Monolog\Formatter\JsonFormatter::formatBatchNewlines + */ + public function testFormatBatchNewlines() + { + $formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_NEWLINES); + $records = $expected = array( + $this->getRecord(Logger::WARNING), + $this->getRecord(Logger::DEBUG), + ); + array_walk($expected, function (&$value, $key) { + $value = json_encode($value); + }); + $this->assertEquals(implode("\n", $expected), $formatter->formatBatch($records)); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Formatter/LineFormatterTest.php b/vendor/monolog/monolog/tests/Monolog/Formatter/LineFormatterTest.php new file mode 100644 index 00000000..89e1ca2e --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Formatter/LineFormatterTest.php @@ -0,0 +1,208 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +/** + * @covers Monolog\Formatter\LineFormatter + */ +class LineFormatterTest extends \PHPUnit_Framework_TestCase +{ + public function testDefFormatWithString() + { + $formatter = new LineFormatter(null, 'Y-m-d'); + $message = $formatter->format(array( + 'level_name' => 'WARNING', + 'channel' => 'log', + 'context' => array(), + 'message' => 'foo', + 'datetime' => new \DateTime, + 'extra' => array(), + )); + $this->assertEquals('['.date('Y-m-d').'] log.WARNING: foo [] []'."\n", $message); + } + + public function testDefFormatWithArrayContext() + { + $formatter = new LineFormatter(null, 'Y-m-d'); + $message = $formatter->format(array( + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'message' => 'foo', + 'datetime' => new \DateTime, + 'extra' => array(), + 'context' => array( + 'foo' => 'bar', + 'baz' => 'qux', + 'bool' => false, + 'null' => null, + ) + )); + $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: foo {"foo":"bar","baz":"qux","bool":false,"null":null} []'."\n", $message); + } + + public function testDefFormatExtras() + { + $formatter = new LineFormatter(null, 'Y-m-d'); + $message = $formatter->format(array( + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime, + 'extra' => array('ip' => '127.0.0.1'), + 'message' => 'log', + )); + $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: log [] {"ip":"127.0.0.1"}'."\n", $message); + } + + public function testFormatExtras() + { + $formatter = new LineFormatter("[%datetime%] %channel%.%level_name%: %message% %context% %extra.file% %extra%\n", 'Y-m-d'); + $message = $formatter->format(array( + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime, + 'extra' => array('ip' => '127.0.0.1', 'file' => 'test'), + 'message' => 'log', + )); + $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: log [] test {"ip":"127.0.0.1"}'."\n", $message); + } + + public function testContextAndExtraOptionallyNotShownIfEmpty() + { + $formatter = new LineFormatter(null, 'Y-m-d', false, true); + $message = $formatter->format(array( + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime, + 'extra' => array(), + 'message' => 'log', + )); + $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: log '."\n", $message); + } + + public function testDefFormatWithObject() + { + $formatter = new LineFormatter(null, 'Y-m-d'); + $message = $formatter->format(array( + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime, + 'extra' => array('foo' => new TestFoo, 'bar' => new TestBar, 'baz' => array(), 'res' => fopen('php://memory', 'rb')), + 'message' => 'foobar', + )); + + $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: foobar [] {"foo":"[object] (Monolog\\\\Formatter\\\\TestFoo: {\\"foo\\":\\"foo\\"})","bar":"[object] (Monolog\\\\Formatter\\\\TestBar: {})","baz":[],"res":"[resource]"}'."\n", $message); + } + + public function testDefFormatWithException() + { + $formatter = new LineFormatter(null, 'Y-m-d'); + $message = $formatter->format(array( + 'level_name' => 'CRITICAL', + 'channel' => 'core', + 'context' => array('exception' => new \RuntimeException('Foo')), + 'datetime' => new \DateTime, + 'extra' => array(), + 'message' => 'foobar', + )); + + $path = str_replace('\\/', '/', json_encode(__FILE__)); + + $this->assertEquals('['.date('Y-m-d').'] core.CRITICAL: foobar {"exception":"[object] (RuntimeException(code: 0): Foo at '.substr($path, 1, -1).':'.(__LINE__-8).')"} []'."\n", $message); + } + + public function testDefFormatWithPreviousException() + { + $formatter = new LineFormatter(null, 'Y-m-d'); + $previous = new \LogicException('Wut?'); + $message = $formatter->format(array( + 'level_name' => 'CRITICAL', + 'channel' => 'core', + 'context' => array('exception' => new \RuntimeException('Foo', 0, $previous)), + 'datetime' => new \DateTime, + 'extra' => array(), + 'message' => 'foobar', + )); + + $path = str_replace('\\/', '/', json_encode(__FILE__)); + + $this->assertEquals('['.date('Y-m-d').'] core.CRITICAL: foobar {"exception":"[object] (RuntimeException(code: 0): Foo at '.substr($path, 1, -1).':'.(__LINE__-8).', LogicException(code: 0): Wut? at '.substr($path, 1, -1).':'.(__LINE__-12).')"} []'."\n", $message); + } + + public function testBatchFormat() + { + $formatter = new LineFormatter(null, 'Y-m-d'); + $message = $formatter->formatBatch(array( + array( + 'level_name' => 'CRITICAL', + 'channel' => 'test', + 'message' => 'bar', + 'context' => array(), + 'datetime' => new \DateTime, + 'extra' => array(), + ), + array( + 'level_name' => 'WARNING', + 'channel' => 'log', + 'message' => 'foo', + 'context' => array(), + 'datetime' => new \DateTime, + 'extra' => array(), + ), + )); + $this->assertEquals('['.date('Y-m-d').'] test.CRITICAL: bar [] []'."\n".'['.date('Y-m-d').'] log.WARNING: foo [] []'."\n", $message); + } + + public function testFormatShouldStripInlineLineBreaks() + { + $formatter = new LineFormatter(null, 'Y-m-d'); + $message = $formatter->format( + array( + 'message' => "foo\nbar", + 'context' => array(), + 'extra' => array(), + ) + ); + + $this->assertRegExp('/foo bar/', $message); + } + + public function testFormatShouldNotStripInlineLineBreaksWhenFlagIsSet() + { + $formatter = new LineFormatter(null, 'Y-m-d', true); + $message = $formatter->format( + array( + 'message' => "foo\nbar", + 'context' => array(), + 'extra' => array(), + ) + ); + + $this->assertRegExp('/foo\nbar/', $message); + } +} + +class TestFoo +{ + public $foo = 'foo'; +} + +class TestBar +{ + public function __toString() + { + return 'bar'; + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Formatter/LogglyFormatterTest.php b/vendor/monolog/monolog/tests/Monolog/Formatter/LogglyFormatterTest.php new file mode 100644 index 00000000..6d59b3f3 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Formatter/LogglyFormatterTest.php @@ -0,0 +1,40 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +use Monolog\TestCase; + +class LogglyFormatterTest extends TestCase +{ + /** + * @covers Monolog\Formatter\LogglyFormatter::__construct + */ + public function testConstruct() + { + $formatter = new LogglyFormatter(); + $this->assertEquals(LogglyFormatter::BATCH_MODE_NEWLINES, $formatter->getBatchMode()); + $formatter = new LogglyFormatter(LogglyFormatter::BATCH_MODE_JSON); + $this->assertEquals(LogglyFormatter::BATCH_MODE_JSON, $formatter->getBatchMode()); + } + + /** + * @covers Monolog\Formatter\LogglyFormatter::format + */ + public function testFormat() + { + $formatter = new LogglyFormatter(); + $record = $this->getRecord(); + $formatted_decoded = json_decode($formatter->format($record), true); + $this->assertArrayHasKey("timestamp", $formatted_decoded); + $this->assertEquals(new \DateTime($formatted_decoded["timestamp"]), $record["datetime"]); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Formatter/LogstashFormatterTest.php b/vendor/monolog/monolog/tests/Monolog/Formatter/LogstashFormatterTest.php new file mode 100644 index 00000000..de4a3c2c --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Formatter/LogstashFormatterTest.php @@ -0,0 +1,289 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +use Monolog\Logger; + +class LogstashFormatterTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Monolog\Formatter\LogstashFormatter::format + */ + public function testDefaultFormatter() + { + $formatter = new LogstashFormatter('test', 'hostname'); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ); + + $message = json_decode($formatter->format($record), true); + + $this->assertEquals("1970-01-01T00:00:00.000000+00:00", $message['@timestamp']); + $this->assertEquals('log', $message['@message']); + $this->assertEquals('meh', $message['@fields']['channel']); + $this->assertContains('meh', $message['@tags']); + $this->assertEquals(Logger::ERROR, $message['@fields']['level']); + $this->assertEquals('test', $message['@type']); + $this->assertEquals('hostname', $message['@source']); + + $formatter = new LogstashFormatter('mysystem'); + + $message = json_decode($formatter->format($record), true); + + $this->assertEquals('mysystem', $message['@type']); + } + + /** + * @covers Monolog\Formatter\LogstashFormatter::format + */ + public function testFormatWithFileAndLine() + { + $formatter = new LogstashFormatter('test'); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('file' => 'test', 'line' => 14), + 'message' => 'log', + ); + + $message = json_decode($formatter->format($record), true); + + $this->assertEquals('test', $message['@fields']['file']); + $this->assertEquals(14, $message['@fields']['line']); + } + + /** + * @covers Monolog\Formatter\LogstashFormatter::format + */ + public function testFormatWithContext() + { + $formatter = new LogstashFormatter('test'); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('key' => 'pair'), + 'message' => 'log' + ); + + $message = json_decode($formatter->format($record), true); + + $message_array = $message['@fields']; + + $this->assertArrayHasKey('ctxt_from', $message_array); + $this->assertEquals('logger', $message_array['ctxt_from']); + + // Test with extraPrefix + $formatter = new LogstashFormatter('test', null, null, 'CTX'); + $message = json_decode($formatter->format($record), true); + + $message_array = $message['@fields']; + + $this->assertArrayHasKey('CTXfrom', $message_array); + $this->assertEquals('logger', $message_array['CTXfrom']); + } + + /** + * @covers Monolog\Formatter\LogstashFormatter::format + */ + public function testFormatWithExtra() + { + $formatter = new LogstashFormatter('test'); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('key' => 'pair'), + 'message' => 'log' + ); + + $message = json_decode($formatter->format($record), true); + + $message_array = $message['@fields']; + + $this->assertArrayHasKey('key', $message_array); + $this->assertEquals('pair', $message_array['key']); + + // Test with extraPrefix + $formatter = new LogstashFormatter('test', null, 'EXT'); + $message = json_decode($formatter->format($record), true); + + $message_array = $message['@fields']; + + $this->assertArrayHasKey('EXTkey', $message_array); + $this->assertEquals('pair', $message_array['EXTkey']); + } + + public function testFormatWithApplicationName() + { + $formatter = new LogstashFormatter('app', 'test'); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('key' => 'pair'), + 'message' => 'log' + ); + + $message = json_decode($formatter->format($record), true); + + $this->assertArrayHasKey('@type', $message); + $this->assertEquals('app', $message['@type']); + } + + /** + * @covers Monolog\Formatter\LogstashFormatter::format + */ + public function testDefaultFormatterV1() + { + $formatter = new LogstashFormatter('test', 'hostname', null, 'ctxt_', LogstashFormatter::V1); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ); + + $message = json_decode($formatter->format($record), true); + + $this->assertEquals("1970-01-01T00:00:00.000000+00:00", $message['@timestamp']); + $this->assertEquals("1", $message['@version']); + $this->assertEquals('log', $message['message']); + $this->assertEquals('meh', $message['channel']); + $this->assertEquals('ERROR', $message['level']); + $this->assertEquals('test', $message['type']); + $this->assertEquals('hostname', $message['host']); + + $formatter = new LogstashFormatter('mysystem', null, null, 'ctxt_', LogstashFormatter::V1); + + $message = json_decode($formatter->format($record), true); + + $this->assertEquals('mysystem', $message['type']); + } + + /** + * @covers Monolog\Formatter\LogstashFormatter::format + */ + public function testFormatWithFileAndLineV1() + { + $formatter = new LogstashFormatter('test', null, null, 'ctxt_', LogstashFormatter::V1); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('file' => 'test', 'line' => 14), + 'message' => 'log', + ); + + $message = json_decode($formatter->format($record), true); + + $this->assertEquals('test', $message['file']); + $this->assertEquals(14, $message['line']); + } + + /** + * @covers Monolog\Formatter\LogstashFormatter::format + */ + public function testFormatWithContextV1() + { + $formatter = new LogstashFormatter('test', null, null, 'ctxt_', LogstashFormatter::V1); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('key' => 'pair'), + 'message' => 'log' + ); + + $message = json_decode($formatter->format($record), true); + + $this->assertArrayHasKey('ctxt_from', $message); + $this->assertEquals('logger', $message['ctxt_from']); + + // Test with extraPrefix + $formatter = new LogstashFormatter('test', null, null, 'CTX', LogstashFormatter::V1); + $message = json_decode($formatter->format($record), true); + + $this->assertArrayHasKey('CTXfrom', $message); + $this->assertEquals('logger', $message['CTXfrom']); + } + + /** + * @covers Monolog\Formatter\LogstashFormatter::format + */ + public function testFormatWithExtraV1() + { + $formatter = new LogstashFormatter('test', null, null, 'ctxt_', LogstashFormatter::V1); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('key' => 'pair'), + 'message' => 'log' + ); + + $message = json_decode($formatter->format($record), true); + + $this->assertArrayHasKey('key', $message); + $this->assertEquals('pair', $message['key']); + + // Test with extraPrefix + $formatter = new LogstashFormatter('test', null, 'EXT', 'ctxt_', LogstashFormatter::V1); + $message = json_decode($formatter->format($record), true); + + $this->assertArrayHasKey('EXTkey', $message); + $this->assertEquals('pair', $message['EXTkey']); + } + + public function testFormatWithApplicationNameV1() + { + $formatter = new LogstashFormatter('app', 'test', null, 'ctxt_', LogstashFormatter::V1); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('key' => 'pair'), + 'message' => 'log' + ); + + $message = json_decode($formatter->format($record), true); + + $this->assertArrayHasKey('type', $message); + $this->assertEquals('app', $message['type']); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Formatter/MongoDBFormatterTest.php b/vendor/monolog/monolog/tests/Monolog/Formatter/MongoDBFormatterTest.php new file mode 100644 index 00000000..1554ef46 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Formatter/MongoDBFormatterTest.php @@ -0,0 +1,253 @@ +<?php + +namespace Monolog\Formatter; + +use Monolog\Logger; + +/** + * @author Florian Plattner <me@florianplattner.de> + */ +class MongoDBFormatterTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + if (!class_exists('MongoDate')) { + $this->markTestSkipped('mongo extension not installed'); + } + } + + public function constructArgumentProvider() + { + return array( + array(1, true, 1, true), + array(0, false, 0, false), + ); + } + + /** + * @param $traceDepth + * @param $traceAsString + * @param $expectedTraceDepth + * @param $expectedTraceAsString + * + * @dataProvider constructArgumentProvider + */ + public function testConstruct($traceDepth, $traceAsString, $expectedTraceDepth, $expectedTraceAsString) + { + $formatter = new MongoDBFormatter($traceDepth, $traceAsString); + + $reflTrace = new \ReflectionProperty($formatter, 'exceptionTraceAsString'); + $reflTrace->setAccessible(true); + $this->assertEquals($expectedTraceAsString, $reflTrace->getValue($formatter)); + + $reflDepth = new\ReflectionProperty($formatter, 'maxNestingLevel'); + $reflDepth->setAccessible(true); + $this->assertEquals($expectedTraceDepth, $reflDepth->getValue($formatter)); + } + + public function testSimpleFormat() + { + $record = array( + 'message' => 'some log message', + 'context' => array(), + 'level' => Logger::WARNING, + 'level_name' => Logger::getLevelName(Logger::WARNING), + 'channel' => 'test', + 'datetime' => new \DateTime('2014-02-01 00:00:00'), + 'extra' => array(), + ); + + $formatter = new MongoDBFormatter(); + $formattedRecord = $formatter->format($record); + + $this->assertCount(7, $formattedRecord); + $this->assertEquals('some log message', $formattedRecord['message']); + $this->assertEquals(array(), $formattedRecord['context']); + $this->assertEquals(Logger::WARNING, $formattedRecord['level']); + $this->assertEquals(Logger::getLevelName(Logger::WARNING), $formattedRecord['level_name']); + $this->assertEquals('test', $formattedRecord['channel']); + $this->assertInstanceOf('\MongoDate', $formattedRecord['datetime']); + $this->assertEquals('0.00000000 1391212800', $formattedRecord['datetime']->__toString()); + $this->assertEquals(array(), $formattedRecord['extra']); + } + + public function testRecursiveFormat() + { + $someObject = new \stdClass(); + $someObject->foo = 'something'; + $someObject->bar = 'stuff'; + + $record = array( + 'message' => 'some log message', + 'context' => array( + 'stuff' => new \DateTime('2014-02-01 02:31:33'), + 'some_object' => $someObject, + 'context_string' => 'some string', + 'context_int' => 123456, + 'except' => new \Exception('exception message', 987), + ), + 'level' => Logger::WARNING, + 'level_name' => Logger::getLevelName(Logger::WARNING), + 'channel' => 'test', + 'datetime' => new \DateTime('2014-02-01 00:00:00'), + 'extra' => array(), + ); + + $formatter = new MongoDBFormatter(); + $formattedRecord = $formatter->format($record); + + $this->assertCount(5, $formattedRecord['context']); + $this->assertInstanceOf('\MongoDate', $formattedRecord['context']['stuff']); + $this->assertEquals('0.00000000 1391221893', $formattedRecord['context']['stuff']->__toString()); + $this->assertEquals( + array( + 'foo' => 'something', + 'bar' => 'stuff', + 'class' => 'stdClass', + ), + $formattedRecord['context']['some_object'] + ); + $this->assertEquals('some string', $formattedRecord['context']['context_string']); + $this->assertEquals(123456, $formattedRecord['context']['context_int']); + + $this->assertCount(5, $formattedRecord['context']['except']); + $this->assertEquals('exception message', $formattedRecord['context']['except']['message']); + $this->assertEquals(987, $formattedRecord['context']['except']['code']); + $this->assertInternalType('string', $formattedRecord['context']['except']['file']); + $this->assertInternalType('integer', $formattedRecord['context']['except']['code']); + $this->assertInternalType('string', $formattedRecord['context']['except']['trace']); + $this->assertEquals('Exception', $formattedRecord['context']['except']['class']); + } + + public function testFormatDepthArray() + { + $record = array( + 'message' => 'some log message', + 'context' => array( + 'nest2' => array( + 'property' => 'anything', + 'nest3' => array( + 'nest4' => 'value', + 'property' => 'nothing' + ) + ) + ), + 'level' => Logger::WARNING, + 'level_name' => Logger::getLevelName(Logger::WARNING), + 'channel' => 'test', + 'datetime' => new \DateTime('2014-02-01 00:00:00'), + 'extra' => array(), + ); + + $formatter = new MongoDBFormatter(2); + $formattedResult = $formatter->format($record); + + $this->assertEquals( + array( + 'nest2' => array( + 'property' => 'anything', + 'nest3' => '[...]', + ) + ), + $formattedResult['context'] + ); + } + + public function testFormatDepthArrayInfiniteNesting() + { + $record = array( + 'message' => 'some log message', + 'context' => array( + 'nest2' => array( + 'property' => 'something', + 'nest3' => array( + 'property' => 'anything', + 'nest4' => array( + 'property' => 'nothing', + ), + ) + ) + ), + 'level' => Logger::WARNING, + 'level_name' => Logger::getLevelName(Logger::WARNING), + 'channel' => 'test', + 'datetime' => new \DateTime('2014-02-01 00:00:00'), + 'extra' => array(), + ); + + $formatter = new MongoDBFormatter(0); + $formattedResult = $formatter->format($record); + + $this->assertEquals( + array( + 'nest2' => array( + 'property' => 'something', + 'nest3' => array( + 'property' => 'anything', + 'nest4' => array( + 'property' => 'nothing', + ) + ), + ) + ), + $formattedResult['context'] + ); + } + + public function testFormatDepthObjects() + { + $someObject = new \stdClass(); + $someObject->property = 'anything'; + $someObject->nest3 = new \stdClass(); + $someObject->nest3->property = 'nothing'; + $someObject->nest3->nest4 = 'invisible'; + + $record = array( + 'message' => 'some log message', + 'context' => array( + 'nest2' => $someObject + ), + 'level' => Logger::WARNING, + 'level_name' => Logger::getLevelName(Logger::WARNING), + 'channel' => 'test', + 'datetime' => new \DateTime('2014-02-01 00:00:00'), + 'extra' => array(), + ); + + $formatter = new MongoDBFormatter(2, true); + $formattedResult = $formatter->format($record); + + $this->assertEquals( + array( + 'nest2' => array( + 'property' => 'anything', + 'nest3' => '[...]', + 'class' => 'stdClass', + ), + ), + $formattedResult['context'] + ); + } + + public function testFormatDepthException() + { + $record = array( + 'message' => 'some log message', + 'context' => array( + 'nest2' => new \Exception('exception message', 987), + ), + 'level' => Logger::WARNING, + 'level_name' => Logger::getLevelName(Logger::WARNING), + 'channel' => 'test', + 'datetime' => new \DateTime('2014-02-01 00:00:00'), + 'extra' => array(), + ); + + $formatter = new MongoDBFormatter(2, false); + $formattedRecord = $formatter->format($record); + + $this->assertEquals('exception message', $formattedRecord['context']['nest2']['message']); + $this->assertEquals(987, $formattedRecord['context']['nest2']['code']); + $this->assertEquals('[...]', $formattedRecord['context']['nest2']['trace']); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Formatter/NormalizerFormatterTest.php b/vendor/monolog/monolog/tests/Monolog/Formatter/NormalizerFormatterTest.php new file mode 100644 index 00000000..00bbb249 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Formatter/NormalizerFormatterTest.php @@ -0,0 +1,247 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +/** + * @covers Monolog\Formatter\NormalizerFormatter + */ +class NormalizerFormatterTest extends \PHPUnit_Framework_TestCase +{ + public function testFormat() + { + $formatter = new NormalizerFormatter('Y-m-d'); + $formatted = $formatter->format(array( + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'message' => 'foo', + 'datetime' => new \DateTime, + 'extra' => array('foo' => new TestFooNorm, 'bar' => new TestBarNorm, 'baz' => array(), 'res' => fopen('php://memory', 'rb')), + 'context' => array( + 'foo' => 'bar', + 'baz' => 'qux', + ), + )); + + $this->assertEquals(array( + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'message' => 'foo', + 'datetime' => date('Y-m-d'), + 'extra' => array( + 'foo' => '[object] (Monolog\\Formatter\\TestFooNorm: {"foo":"foo"})', + 'bar' => '[object] (Monolog\\Formatter\\TestBarNorm: {})', + 'baz' => array(), + 'res' => '[resource]', + ), + 'context' => array( + 'foo' => 'bar', + 'baz' => 'qux', + ) + ), $formatted); + } + + public function testFormatExceptions() + { + $formatter = new NormalizerFormatter('Y-m-d'); + $e = new \LogicException('bar'); + $e2 = new \RuntimeException('foo', 0, $e); + $formatted = $formatter->format(array( + 'exception' => $e2, + )); + + $this->assertGreaterThan(5, count($formatted['exception']['trace'])); + $this->assertTrue(isset($formatted['exception']['previous'])); + unset($formatted['exception']['trace'], $formatted['exception']['previous']); + + $this->assertEquals(array( + 'exception' => array( + 'class' => get_class($e2), + 'message' => $e2->getMessage(), + 'code' => $e2->getCode(), + 'file' => $e2->getFile().':'.$e2->getLine(), + ) + ), $formatted); + } + + public function testBatchFormat() + { + $formatter = new NormalizerFormatter('Y-m-d'); + $formatted = $formatter->formatBatch(array( + array( + 'level_name' => 'CRITICAL', + 'channel' => 'test', + 'message' => 'bar', + 'context' => array(), + 'datetime' => new \DateTime, + 'extra' => array(), + ), + array( + 'level_name' => 'WARNING', + 'channel' => 'log', + 'message' => 'foo', + 'context' => array(), + 'datetime' => new \DateTime, + 'extra' => array(), + ), + )); + $this->assertEquals(array( + array( + 'level_name' => 'CRITICAL', + 'channel' => 'test', + 'message' => 'bar', + 'context' => array(), + 'datetime' => date('Y-m-d'), + 'extra' => array(), + ), + array( + 'level_name' => 'WARNING', + 'channel' => 'log', + 'message' => 'foo', + 'context' => array(), + 'datetime' => date('Y-m-d'), + 'extra' => array(), + ), + ), $formatted); + } + + /** + * Test issue #137 + */ + public function testIgnoresRecursiveObjectReferences() + { + // set up the recursion + $foo = new \stdClass(); + $bar = new \stdClass(); + + $foo->bar = $bar; + $bar->foo = $foo; + + // set an error handler to assert that the error is not raised anymore + $that = $this; + set_error_handler(function ($level, $message, $file, $line, $context) use ($that) { + if (error_reporting() & $level) { + restore_error_handler(); + $that->fail("$message should not be raised"); + } + }); + + $formatter = new NormalizerFormatter(); + $reflMethod = new \ReflectionMethod($formatter, 'toJson'); + $reflMethod->setAccessible(true); + $res = $reflMethod->invoke($formatter, array($foo, $bar), true); + + restore_error_handler(); + + $this->assertEquals(@json_encode(array($foo, $bar)), $res); + } + + public function testIgnoresInvalidTypes() + { + // set up the recursion + $resource = fopen(__FILE__, 'r'); + + // set an error handler to assert that the error is not raised anymore + $that = $this; + set_error_handler(function ($level, $message, $file, $line, $context) use ($that) { + if (error_reporting() & $level) { + restore_error_handler(); + $that->fail("$message should not be raised"); + } + }); + + $formatter = new NormalizerFormatter(); + $reflMethod = new \ReflectionMethod($formatter, 'toJson'); + $reflMethod->setAccessible(true); + $res = $reflMethod->invoke($formatter, array($resource), true); + + restore_error_handler(); + + $this->assertEquals(@json_encode(array($resource)), $res); + } + + public function testExceptionTraceWithArgs() + { + if (defined('HHVM_VERSION')) { + $this->markTestSkipped('Not supported in HHVM since it detects errors differently'); + } + + // This happens i.e. in React promises or Guzzle streams where stream wrappers are registered + // and no file or line are included in the trace because it's treated as internal function + set_error_handler(function ($errno, $errstr, $errfile, $errline) { + throw new \ErrorException($errstr, 0, $errno, $errfile, $errline); + }); + + try { + // This will contain $resource and $wrappedResource as arguments in the trace item + $resource = fopen('php://memory', 'rw+'); + fwrite($resource, 'test_resource'); + $wrappedResource = new TestStreamFoo($resource); + // Just do something stupid with a resource/wrapped resource as argument + array_keys($wrappedResource); + } catch (\Exception $e) { + restore_error_handler(); + } + + $formatter = new NormalizerFormatter(); + $record = array('context' => array('exception' => $e)); + $result = $formatter->format($record); + + $this->assertRegExp( + '%"resource":"\[resource\]"%', + $result['context']['exception']['trace'][0] + ); + + if (version_compare(PHP_VERSION, '5.5.0', '>=')) { + $pattern = '%"wrappedResource":"\[object\] \(Monolog\\\\\\\\Formatter\\\\\\\\TestStreamFoo: \)"%'; + } else { + $pattern = '%\\\\"resource\\\\":null%'; + } + + // Tests that the wrapped resource is ignored while encoding, only works for PHP <= 5.4 + $this->assertRegExp( + $pattern, + $result['context']['exception']['trace'][0] + ); + } +} + +class TestFooNorm +{ + public $foo = 'foo'; +} + +class TestBarNorm +{ + public function __toString() + { + return 'bar'; + } +} + +class TestStreamFoo +{ + public $foo; + public $resource; + + public function __construct($resource) + { + $this->resource = $resource; + $this->foo = 'BAR'; + } + + public function __toString() + { + fseek($this->resource, 0); + + return $this->foo . ' - ' . (string) stream_get_contents($this->resource); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Formatter/ScalarFormatterTest.php b/vendor/monolog/monolog/tests/Monolog/Formatter/ScalarFormatterTest.php new file mode 100644 index 00000000..c5a4ebb5 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Formatter/ScalarFormatterTest.php @@ -0,0 +1,98 @@ +<?php +namespace Monolog\Formatter; + +class ScalarFormatterTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + $this->formatter = new ScalarFormatter(); + } + + public function buildTrace(\Exception $e) + { + $data = array(); + $trace = $e->getTrace(); + foreach ($trace as $frame) { + if (isset($frame['file'])) { + $data[] = $frame['file'].':'.$frame['line']; + } else { + $data[] = json_encode($frame); + } + } + + return $data; + } + + public function encodeJson($data) + { + if (version_compare(PHP_VERSION, '5.4.0', '>=')) { + return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + } + + return json_encode($data); + } + + public function testFormat() + { + $exception = new \Exception('foo'); + $formatted = $this->formatter->format(array( + 'foo' => 'string', + 'bar' => 1, + 'baz' => false, + 'bam' => array(1, 2, 3), + 'bat' => array('foo' => 'bar'), + 'bap' => \DateTime::createFromFormat(\DateTime::ISO8601, '1970-01-01T00:00:00+0000'), + 'ban' => $exception + )); + + $this->assertSame(array( + 'foo' => 'string', + 'bar' => 1, + 'baz' => false, + 'bam' => $this->encodeJson(array(1, 2, 3)), + 'bat' => $this->encodeJson(array('foo' => 'bar')), + 'bap' => '1970-01-01 00:00:00', + 'ban' => $this->encodeJson(array( + 'class' => get_class($exception), + 'message' => $exception->getMessage(), + 'code' => $exception->getCode(), + 'file' => $exception->getFile() . ':' . $exception->getLine(), + 'trace' => $this->buildTrace($exception) + )) + ), $formatted); + } + + public function testFormatWithErrorContext() + { + $context = array('file' => 'foo', 'line' => 1); + $formatted = $this->formatter->format(array( + 'context' => $context + )); + + $this->assertSame(array( + 'context' => $this->encodeJson($context) + ), $formatted); + } + + public function testFormatWithExceptionContext() + { + $exception = new \Exception('foo'); + $formatted = $this->formatter->format(array( + 'context' => array( + 'exception' => $exception + ) + )); + + $this->assertSame(array( + 'context' => $this->encodeJson(array( + 'exception' => array( + 'class' => get_class($exception), + 'message' => $exception->getMessage(), + 'code' => $exception->getCode(), + 'file' => $exception->getFile() . ':' . $exception->getLine(), + 'trace' => $this->buildTrace($exception) + ) + )) + ), $formatted); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Formatter/WildfireFormatterTest.php b/vendor/monolog/monolog/tests/Monolog/Formatter/WildfireFormatterTest.php new file mode 100644 index 00000000..52f15a36 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Formatter/WildfireFormatterTest.php @@ -0,0 +1,142 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +use Monolog\Logger; + +class WildfireFormatterTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Monolog\Formatter\WildfireFormatter::format + */ + public function testDefaultFormat() + { + $wildfire = new WildfireFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('ip' => '127.0.0.1'), + 'message' => 'log', + ); + + $message = $wildfire->format($record); + + $this->assertEquals( + '125|[{"Type":"ERROR","File":"","Line":"","Label":"meh"},' + .'{"message":"log","context":{"from":"logger"},"extra":{"ip":"127.0.0.1"}}]|', + $message + ); + } + + /** + * @covers Monolog\Formatter\WildfireFormatter::format + */ + public function testFormatWithFileAndLine() + { + $wildfire = new WildfireFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('ip' => '127.0.0.1', 'file' => 'test', 'line' => 14), + 'message' => 'log', + ); + + $message = $wildfire->format($record); + + $this->assertEquals( + '129|[{"Type":"ERROR","File":"test","Line":14,"Label":"meh"},' + .'{"message":"log","context":{"from":"logger"},"extra":{"ip":"127.0.0.1"}}]|', + $message + ); + } + + /** + * @covers Monolog\Formatter\WildfireFormatter::format + */ + public function testFormatWithoutContext() + { + $wildfire = new WildfireFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ); + + $message = $wildfire->format($record); + + $this->assertEquals( + '58|[{"Type":"ERROR","File":"","Line":"","Label":"meh"},"log"]|', + $message + ); + } + + /** + * @covers Monolog\Formatter\WildfireFormatter::formatBatch + * @expectedException BadMethodCallException + */ + public function testBatchFormatThrowException() + { + $wildfire = new WildfireFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ); + + $wildfire->formatBatch(array($record)); + } + + /** + * @covers Monolog\Formatter\WildfireFormatter::format + */ + public function testTableFormat() + { + $wildfire = new WildfireFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'table-channel', + 'context' => array( + WildfireFormatter::TABLE => array( + array('col1', 'col2', 'col3'), + array('val1', 'val2', 'val3'), + array('foo1', 'foo2', 'foo3'), + array('bar1', 'bar2', 'bar3'), + ), + ), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'table-message', + ); + + $message = $wildfire->format($record); + + $this->assertEquals( + '171|[{"Type":"TABLE","File":"","Line":"","Label":"table-channel: table-message"},[["col1","col2","col3"],["val1","val2","val3"],["foo1","foo2","foo3"],["bar1","bar2","bar3"]]]|', + $message + ); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Functional/Handler/FirePHPHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Functional/Handler/FirePHPHandlerTest.php new file mode 100644 index 00000000..7e4e7eb5 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Functional/Handler/FirePHPHandlerTest.php @@ -0,0 +1,32 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +spl_autoload_register(function ($class) { + $file = __DIR__.'/../../../../src/'.strtr($class, '\\', '/').'.php'; + if (file_exists($file)) { + require $file; + + return true; + } +}); + +use Monolog\Logger; +use Monolog\Handler\FirePHPHandler; +use Monolog\Handler\ChromePHPHandler; + +$logger = new Logger('firephp'); +$logger->pushHandler(new FirePHPHandler); +$logger->pushHandler(new ChromePHPHandler()); + +$logger->addDebug('Debug'); +$logger->addInfo('Info'); +$logger->addWarning('Warning'); +$logger->addError('Error'); diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/AbstractHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/AbstractHandlerTest.php new file mode 100644 index 00000000..568eb9da --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/AbstractHandlerTest.php @@ -0,0 +1,115 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; +use Monolog\Formatter\LineFormatter; +use Monolog\Processor\WebProcessor; + +class AbstractHandlerTest extends TestCase +{ + /** + * @covers Monolog\Handler\AbstractHandler::__construct + * @covers Monolog\Handler\AbstractHandler::getLevel + * @covers Monolog\Handler\AbstractHandler::setLevel + * @covers Monolog\Handler\AbstractHandler::getBubble + * @covers Monolog\Handler\AbstractHandler::setBubble + * @covers Monolog\Handler\AbstractHandler::getFormatter + * @covers Monolog\Handler\AbstractHandler::setFormatter + */ + public function testConstructAndGetSet() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler', array(Logger::WARNING, false)); + $this->assertEquals(Logger::WARNING, $handler->getLevel()); + $this->assertEquals(false, $handler->getBubble()); + + $handler->setLevel(Logger::ERROR); + $handler->setBubble(true); + $handler->setFormatter($formatter = new LineFormatter); + $this->assertEquals(Logger::ERROR, $handler->getLevel()); + $this->assertEquals(true, $handler->getBubble()); + $this->assertSame($formatter, $handler->getFormatter()); + } + + /** + * @covers Monolog\Handler\AbstractHandler::handleBatch + */ + public function testHandleBatch() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler'); + $handler->expects($this->exactly(2)) + ->method('handle'); + $handler->handleBatch(array($this->getRecord(), $this->getRecord())); + } + + /** + * @covers Monolog\Handler\AbstractHandler::isHandling + */ + public function testIsHandling() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler', array(Logger::WARNING, false)); + $this->assertTrue($handler->isHandling($this->getRecord())); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG))); + } + + /** + * @covers Monolog\Handler\AbstractHandler::__construct + */ + public function testHandlesPsrStyleLevels() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler', array('warning', false)); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG))); + $handler->setLevel('debug'); + $this->assertTrue($handler->isHandling($this->getRecord(Logger::DEBUG))); + } + + /** + * @covers Monolog\Handler\AbstractHandler::getFormatter + * @covers Monolog\Handler\AbstractHandler::getDefaultFormatter + */ + public function testGetFormatterInitializesDefault() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler'); + $this->assertInstanceOf('Monolog\Formatter\LineFormatter', $handler->getFormatter()); + } + + /** + * @covers Monolog\Handler\AbstractHandler::pushProcessor + * @covers Monolog\Handler\AbstractHandler::popProcessor + * @expectedException LogicException + */ + public function testPushPopProcessor() + { + $logger = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler'); + $processor1 = new WebProcessor; + $processor2 = new WebProcessor; + + $logger->pushProcessor($processor1); + $logger->pushProcessor($processor2); + + $this->assertEquals($processor2, $logger->popProcessor()); + $this->assertEquals($processor1, $logger->popProcessor()); + $logger->popProcessor(); + } + + /** + * @covers Monolog\Handler\AbstractHandler::pushProcessor + * @expectedException InvalidArgumentException + */ + public function testPushProcessorWithNonCallable() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler'); + + $handler->pushProcessor(new \stdClass()); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/AbstractProcessingHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/AbstractProcessingHandlerTest.php new file mode 100644 index 00000000..24d4f63c --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/AbstractProcessingHandlerTest.php @@ -0,0 +1,80 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; +use Monolog\Processor\WebProcessor; + +class AbstractProcessingHandlerTest extends TestCase +{ + /** + * @covers Monolog\Handler\AbstractProcessingHandler::handle + */ + public function testHandleLowerLevelMessage() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::WARNING, true)); + $this->assertFalse($handler->handle($this->getRecord(Logger::DEBUG))); + } + + /** + * @covers Monolog\Handler\AbstractProcessingHandler::handle + */ + public function testHandleBubbling() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::DEBUG, true)); + $this->assertFalse($handler->handle($this->getRecord())); + } + + /** + * @covers Monolog\Handler\AbstractProcessingHandler::handle + */ + public function testHandleNotBubbling() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::DEBUG, false)); + $this->assertTrue($handler->handle($this->getRecord())); + } + + /** + * @covers Monolog\Handler\AbstractProcessingHandler::handle + */ + public function testHandleIsFalseWhenNotHandled() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::WARNING, false)); + $this->assertTrue($handler->handle($this->getRecord())); + $this->assertFalse($handler->handle($this->getRecord(Logger::DEBUG))); + } + + /** + * @covers Monolog\Handler\AbstractProcessingHandler::processRecord + */ + public function testProcessRecord() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler'); + $handler->pushProcessor(new WebProcessor(array( + 'REQUEST_URI' => '', + 'REQUEST_METHOD' => '', + 'REMOTE_ADDR' => '', + 'SERVER_NAME' => '', + 'UNIQUE_ID' => '', + ))); + $handledRecord = null; + $handler->expects($this->once()) + ->method('write') + ->will($this->returnCallback(function ($record) use (&$handledRecord) { + $handledRecord = $record; + })) + ; + $handler->handle($this->getRecord()); + $this->assertEquals(6, count($handledRecord['extra'])); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/AmqpHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/AmqpHandlerTest.php new file mode 100644 index 00000000..074d50c6 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/AmqpHandlerTest.php @@ -0,0 +1,137 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; +use PhpAmqpLib\Message\AMQPMessage; +use PhpAmqpLib\Channel\AMQPChannel; +use PhpAmqpLib\Connection\AMQPConnection; + +/** + * @covers Monolog\Handler\RotatingFileHandler + */ +class AmqpHandlerTest extends TestCase +{ + public function testHandleAmqpExt() + { + if (!class_exists('AMQPConnection') || !class_exists('AMQPExchange')) { + $this->markTestSkipped("amqp-php not installed"); + } + + if (!class_exists('AMQPChannel')) { + $this->markTestSkipped("Please update AMQP to version >= 1.0"); + } + + $messages = array(); + + $exchange = $this->getMock('AMQPExchange', array('publish', 'setName'), array(), '', false); + $exchange->expects($this->once()) + ->method('setName') + ->with('log') + ; + $exchange->expects($this->any()) + ->method('publish') + ->will($this->returnCallback(function ($message, $routing_key, $flags = 0, $attributes = array()) use (&$messages) { + $messages[] = array($message, $routing_key, $flags, $attributes); + })) + ; + + $handler = new AmqpHandler($exchange, 'log'); + + $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); + + $expected = array( + array( + 'message' => 'test', + 'context' => array( + 'data' => array(), + 'foo' => 34, + ), + 'level' => 300, + 'level_name' => 'WARNING', + 'channel' => 'test', + 'extra' => array(), + ), + 'warn.test', + 0, + array( + 'delivery_mode' => 2, + 'Content-type' => 'application/json' + ) + ); + + $handler->handle($record); + + $this->assertCount(1, $messages); + $messages[0][0] = json_decode($messages[0][0], true); + unset($messages[0][0]['datetime']); + $this->assertEquals($expected, $messages[0]); + } + + public function testHandlePhpAmqpLib() + { + if (!class_exists('PhpAmqpLib\Connection\AMQPConnection')) { + $this->markTestSkipped("php-amqplib not installed"); + } + + $messages = array(); + + $exchange = $this->getMock('PhpAmqpLib\Channel\AMQPChannel', array('basic_publish', '__destruct'), array(), '', false); + + $exchange->expects($this->any()) + ->method('basic_publish') + ->will($this->returnCallback(function (AMQPMessage $msg, $exchange = "", $routing_key = "", $mandatory = false, $immediate = false, $ticket = null) use (&$messages) { + $messages[] = array($msg, $exchange, $routing_key, $mandatory, $immediate, $ticket); + })) + ; + + $handler = new AmqpHandler($exchange, 'log'); + + $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); + + $expected = array( + array( + 'message' => 'test', + 'context' => array( + 'data' => array(), + 'foo' => 34, + ), + 'level' => 300, + 'level_name' => 'WARNING', + 'channel' => 'test', + 'extra' => array(), + ), + 'log', + 'warn.test', + false, + false, + null, + array( + 'delivery_mode' => 2, + 'content_type' => 'application/json' + ) + ); + + $handler->handle($record); + + $this->assertCount(1, $messages); + + /* @var $msg AMQPMessage */ + $msg = $messages[0][0]; + $messages[0][0] = json_decode($msg->body, true); + $messages[0][] = $msg->get_properties(); + unset($messages[0][0]['datetime']); + + $this->assertEquals($expected, $messages[0]); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/BrowserConsoleHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/BrowserConsoleHandlerTest.php new file mode 100644 index 00000000..ffb1d746 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/BrowserConsoleHandlerTest.php @@ -0,0 +1,130 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; + +/** + * @covers Monolog\Handler\BrowserConsoleHandlerTest + */ +class BrowserConsoleHandlerTest extends TestCase +{ + protected function setUp() + { + BrowserConsoleHandler::reset(); + } + + protected function generateScript() + { + $reflMethod = new \ReflectionMethod('Monolog\Handler\BrowserConsoleHandler', 'generateScript'); + $reflMethod->setAccessible(true); + + return $reflMethod->invoke(null); + } + + public function testStyling() + { + $handler = new BrowserConsoleHandler(); + $handler->setFormatter($this->getIdentityFormatter()); + + $handler->handle($this->getRecord(Logger::DEBUG, 'foo[[bar]]{color: red}')); + + $expected = <<<EOF +(function (c) {if (c && c.groupCollapsed) { +c.log("%cfoo%cbar%c", "font-weight: normal", "color: red", "font-weight: normal"); +}})(console); +EOF; + + $this->assertEquals($expected, $this->generateScript()); + } + + public function testEscaping() + { + $handler = new BrowserConsoleHandler(); + $handler->setFormatter($this->getIdentityFormatter()); + + $handler->handle($this->getRecord(Logger::DEBUG, "[foo] [[\"bar\n[baz]\"]]{color: red}")); + + $expected = <<<EOF +(function (c) {if (c && c.groupCollapsed) { +c.log("%c[foo] %c\"bar\\n[baz]\"%c", "font-weight: normal", "color: red", "font-weight: normal"); +}})(console); +EOF; + + $this->assertEquals($expected, $this->generateScript()); + } + + public function testAutolabel() + { + $handler = new BrowserConsoleHandler(); + $handler->setFormatter($this->getIdentityFormatter()); + + $handler->handle($this->getRecord(Logger::DEBUG, '[[foo]]{macro: autolabel}')); + $handler->handle($this->getRecord(Logger::DEBUG, '[[bar]]{macro: autolabel}')); + $handler->handle($this->getRecord(Logger::DEBUG, '[[foo]]{macro: autolabel}')); + + $expected = <<<EOF +(function (c) {if (c && c.groupCollapsed) { +c.log("%c%cfoo%c", "font-weight: normal", "background-color: blue; color: white; border-radius: 3px; padding: 0 2px 0 2px", "font-weight: normal"); +c.log("%c%cbar%c", "font-weight: normal", "background-color: green; color: white; border-radius: 3px; padding: 0 2px 0 2px", "font-weight: normal"); +c.log("%c%cfoo%c", "font-weight: normal", "background-color: blue; color: white; border-radius: 3px; padding: 0 2px 0 2px", "font-weight: normal"); +}})(console); +EOF; + + $this->assertEquals($expected, $this->generateScript()); + } + + public function testContext() + { + $handler = new BrowserConsoleHandler(); + $handler->setFormatter($this->getIdentityFormatter()); + + $handler->handle($this->getRecord(Logger::DEBUG, 'test', array('foo' => 'bar'))); + + $expected = <<<EOF +(function (c) {if (c && c.groupCollapsed) { +c.groupCollapsed("%ctest", "font-weight: normal"); +c.log("%c%s", "font-weight: bold", "Context"); +c.log("%s: %o", "foo", "bar"); +c.groupEnd(); +}})(console); +EOF; + + $this->assertEquals($expected, $this->generateScript()); + } + + public function testConcurrentHandlers() + { + $handler1 = new BrowserConsoleHandler(); + $handler1->setFormatter($this->getIdentityFormatter()); + + $handler2 = new BrowserConsoleHandler(); + $handler2->setFormatter($this->getIdentityFormatter()); + + $handler1->handle($this->getRecord(Logger::DEBUG, 'test1')); + $handler2->handle($this->getRecord(Logger::DEBUG, 'test2')); + $handler1->handle($this->getRecord(Logger::DEBUG, 'test3')); + $handler2->handle($this->getRecord(Logger::DEBUG, 'test4')); + + $expected = <<<EOF +(function (c) {if (c && c.groupCollapsed) { +c.log("%ctest1", "font-weight: normal"); +c.log("%ctest2", "font-weight: normal"); +c.log("%ctest3", "font-weight: normal"); +c.log("%ctest4", "font-weight: normal"); +}})(console); +EOF; + + $this->assertEquals($expected, $this->generateScript()); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/BufferHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/BufferHandlerTest.php new file mode 100644 index 00000000..da8b3c39 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/BufferHandlerTest.php @@ -0,0 +1,158 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; + +class BufferHandlerTest extends TestCase +{ + private $shutdownCheckHandler; + + /** + * @covers Monolog\Handler\BufferHandler::__construct + * @covers Monolog\Handler\BufferHandler::handle + * @covers Monolog\Handler\BufferHandler::close + */ + public function testHandleBuffers() + { + $test = new TestHandler(); + $handler = new BufferHandler($test); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + $this->assertFalse($test->hasDebugRecords()); + $this->assertFalse($test->hasInfoRecords()); + $handler->close(); + $this->assertTrue($test->hasInfoRecords()); + $this->assertTrue(count($test->getRecords()) === 2); + } + + /** + * @covers Monolog\Handler\BufferHandler::close + * @covers Monolog\Handler\BufferHandler::flush + */ + public function testPropagatesRecordsAtEndOfRequest() + { + $test = new TestHandler(); + $handler = new BufferHandler($test); + $handler->handle($this->getRecord(Logger::WARNING)); + $handler->handle($this->getRecord(Logger::DEBUG)); + $this->shutdownCheckHandler = $test; + register_shutdown_function(array($this, 'checkPropagation')); + } + + public function checkPropagation() + { + if (!$this->shutdownCheckHandler->hasWarningRecords() || !$this->shutdownCheckHandler->hasDebugRecords()) { + echo '!!! BufferHandlerTest::testPropagatesRecordsAtEndOfRequest failed to verify that the messages have been propagated' . PHP_EOL; + exit(1); + } + } + + /** + * @covers Monolog\Handler\BufferHandler::handle + */ + public function testHandleBufferLimit() + { + $test = new TestHandler(); + $handler = new BufferHandler($test, 2); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + $handler->handle($this->getRecord(Logger::WARNING)); + $handler->close(); + $this->assertTrue($test->hasWarningRecords()); + $this->assertTrue($test->hasInfoRecords()); + $this->assertFalse($test->hasDebugRecords()); + } + + /** + * @covers Monolog\Handler\BufferHandler::handle + */ + public function testHandleBufferLimitWithFlushOnOverflow() + { + $test = new TestHandler(); + $handler = new BufferHandler($test, 3, Logger::DEBUG, true, true); + + // send two records + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::DEBUG)); + $this->assertFalse($test->hasDebugRecords()); + $this->assertCount(0, $test->getRecords()); + + // overflow + $handler->handle($this->getRecord(Logger::INFO)); + $this->assertTrue($test->hasDebugRecords()); + $this->assertCount(3, $test->getRecords()); + + // should buffer again + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertCount(3, $test->getRecords()); + + $handler->close(); + $this->assertCount(5, $test->getRecords()); + $this->assertTrue($test->hasWarningRecords()); + $this->assertTrue($test->hasInfoRecords()); + } + + /** + * @covers Monolog\Handler\BufferHandler::handle + */ + public function testHandleLevel() + { + $test = new TestHandler(); + $handler = new BufferHandler($test, 0, Logger::INFO); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + $handler->handle($this->getRecord(Logger::WARNING)); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->close(); + $this->assertTrue($test->hasWarningRecords()); + $this->assertTrue($test->hasInfoRecords()); + $this->assertFalse($test->hasDebugRecords()); + } + + /** + * @covers Monolog\Handler\BufferHandler::flush + */ + public function testFlush() + { + $test = new TestHandler(); + $handler = new BufferHandler($test, 0); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + $handler->flush(); + $this->assertTrue($test->hasInfoRecords()); + $this->assertTrue($test->hasDebugRecords()); + $this->assertFalse($test->hasWarningRecords()); + } + + /** + * @covers Monolog\Handler\BufferHandler::handle + */ + public function testHandleUsesProcessors() + { + $test = new TestHandler(); + $handler = new BufferHandler($test); + $handler->pushProcessor(function ($record) { + $record['extra']['foo'] = true; + + return $record; + }); + $handler->handle($this->getRecord(Logger::WARNING)); + $handler->flush(); + $this->assertTrue($test->hasWarningRecords()); + $records = $test->getRecords(); + $this->assertTrue($records[0]['extra']['foo']); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/ChromePHPHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/ChromePHPHandlerTest.php new file mode 100644 index 00000000..2f55faf8 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/ChromePHPHandlerTest.php @@ -0,0 +1,141 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; + +/** + * @covers Monolog\Handler\ChromePHPHandler + */ +class ChromePHPHandlerTest extends TestCase +{ + protected function setUp() + { + TestChromePHPHandler::reset(); + $_SERVER['HTTP_USER_AGENT'] = 'Monolog Test; Chrome/1.0'; + } + + public function testHeaders() + { + $handler = new TestChromePHPHandler(); + $handler->setFormatter($this->getIdentityFormatter()); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::WARNING)); + + $expected = array( + 'X-ChromeLogger-Data' => base64_encode(utf8_encode(json_encode(array( + 'version' => ChromePHPHandler::VERSION, + 'columns' => array('label', 'log', 'backtrace', 'type'), + 'rows' => array( + 'test', + 'test', + ), + 'request_uri' => '', + )))) + ); + + $this->assertEquals($expected, $handler->getHeaders()); + } + + public function testHeadersOverflow() + { + $handler = new TestChromePHPHandler(); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::WARNING, str_repeat('a', 150*1024))); + + // overflow chrome headers limit + $handler->handle($this->getRecord(Logger::WARNING, str_repeat('a', 100*1024))); + + $expected = array( + 'X-ChromeLogger-Data' => base64_encode(utf8_encode(json_encode(array( + 'version' => ChromePHPHandler::VERSION, + 'columns' => array('label', 'log', 'backtrace', 'type'), + 'rows' => array( + array( + 'test', + 'test', + 'unknown', + 'log', + ), + array( + 'test', + str_repeat('a', 150*1024), + 'unknown', + 'warn', + ), + array( + 'monolog', + 'Incomplete logs, chrome header size limit reached', + 'unknown', + 'warn', + ), + ), + 'request_uri' => '', + )))) + ); + + $this->assertEquals($expected, $handler->getHeaders()); + } + + public function testConcurrentHandlers() + { + $handler = new TestChromePHPHandler(); + $handler->setFormatter($this->getIdentityFormatter()); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::WARNING)); + + $handler2 = new TestChromePHPHandler(); + $handler2->setFormatter($this->getIdentityFormatter()); + $handler2->handle($this->getRecord(Logger::DEBUG)); + $handler2->handle($this->getRecord(Logger::WARNING)); + + $expected = array( + 'X-ChromeLogger-Data' => base64_encode(utf8_encode(json_encode(array( + 'version' => ChromePHPHandler::VERSION, + 'columns' => array('label', 'log', 'backtrace', 'type'), + 'rows' => array( + 'test', + 'test', + 'test', + 'test', + ), + 'request_uri' => '', + )))) + ); + + $this->assertEquals($expected, $handler2->getHeaders()); + } +} + +class TestChromePHPHandler extends ChromePHPHandler +{ + protected $headers = array(); + + public static function reset() + { + self::$initialized = false; + self::$overflowed = false; + self::$sendHeaders = true; + self::$json['rows'] = array(); + } + + protected function sendHeader($header, $content) + { + $this->headers[$header] = $content; + } + + public function getHeaders() + { + return $this->headers; + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/CouchDBHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/CouchDBHandlerTest.php new file mode 100644 index 00000000..78a1d15c --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/CouchDBHandlerTest.php @@ -0,0 +1,41 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; + +class CouchDBHandlerTest extends TestCase +{ + public function testHandle() + { + $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); + + $expected = array( + 'message' => 'test', + 'context' => array('data' => '[object] (stdClass: {})', 'foo' => 34), + 'level' => Logger::WARNING, + 'level_name' => 'WARNING', + 'channel' => 'test', + 'datetime' => $record['datetime']->format('Y-m-d H:i:s'), + 'extra' => array(), + ); + + $handler = new CouchDBHandler(); + + try { + $handler->handle($record); + } catch (\RuntimeException $e) { + $this->markTestSkipped('Could not connect to couchdb server on http://localhost:5984'); + } + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/DoctrineCouchDBHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/DoctrineCouchDBHandlerTest.php new file mode 100644 index 00000000..d67da90a --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/DoctrineCouchDBHandlerTest.php @@ -0,0 +1,52 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; + +class DoctrineCouchDBHandlerTest extends TestCase +{ + protected function setup() + { + if (!class_exists('Doctrine\CouchDB\CouchDBClient')) { + $this->markTestSkipped('The "doctrine/couchdb" package is not installed'); + } + } + + public function testHandle() + { + $client = $this->getMockBuilder('Doctrine\\CouchDB\\CouchDBClient') + ->setMethods(array('postDocument')) + ->disableOriginalConstructor() + ->getMock(); + + $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); + + $expected = array( + 'message' => 'test', + 'context' => array('data' => '[object] (stdClass: {})', 'foo' => 34), + 'level' => Logger::WARNING, + 'level_name' => 'WARNING', + 'channel' => 'test', + 'datetime' => $record['datetime']->format('Y-m-d H:i:s'), + 'extra' => array(), + ); + + $client->expects($this->once()) + ->method('postDocument') + ->with($expected); + + $handler = new DoctrineCouchDBHandler($client); + $handler->handle($record); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/DynamoDbHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/DynamoDbHandlerTest.php new file mode 100644 index 00000000..a38a8cb7 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/DynamoDbHandlerTest.php @@ -0,0 +1,73 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; + +class DynamoDbHandlerTest extends TestCase +{ + public function setUp() + { + if (!class_exists('Aws\DynamoDb\DynamoDbClient')) { + $this->markTestSkipped('aws/aws-sdk-php not installed'); + } + + $this->client = $this->getMockBuilder('Aws\DynamoDb\DynamoDbClient') + ->setMethods(array('formatAttributes', '__call')) + ->disableOriginalConstructor()->getMock(); + } + + public function testConstruct() + { + $this->assertInstanceOf('Monolog\Handler\DynamoDbHandler', new DynamoDbHandler($this->client, 'foo')); + } + + public function testInterface() + { + $this->assertInstanceOf('Monolog\Handler\HandlerInterface', new DynamoDbHandler($this->client, 'foo')); + } + + public function testGetFormatter() + { + $handler = new DynamoDbHandler($this->client, 'foo'); + $this->assertInstanceOf('Monolog\Formatter\ScalarFormatter', $handler->getFormatter()); + } + + public function testHandle() + { + $record = $this->getRecord(); + $formatter = $this->getMock('Monolog\Formatter\FormatterInterface'); + $formatted = array('foo' => 1, 'bar' => 2); + $handler = new DynamoDbHandler($this->client, 'foo'); + $handler->setFormatter($formatter); + + $formatter + ->expects($this->once()) + ->method('format') + ->with($record) + ->will($this->returnValue($formatted)); + $this->client + ->expects($this->once()) + ->method('formatAttributes') + ->with($this->isType('array')) + ->will($this->returnValue($formatted)); + $this->client + ->expects($this->once()) + ->method('__call') + ->with('putItem', array(array( + 'TableName' => 'foo', + 'Item' => $formatted + ))); + + $handler->handle($record); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/ElasticSearchHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/ElasticSearchHandlerTest.php new file mode 100644 index 00000000..1687074b --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/ElasticSearchHandlerTest.php @@ -0,0 +1,239 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\ElasticaFormatter; +use Monolog\Formatter\NormalizerFormatter; +use Monolog\TestCase; +use Monolog\Logger; +use Elastica\Client; +use Elastica\Request; +use Elastica\Response; + +class ElasticSearchHandlerTest extends TestCase +{ + /** + * @var Client mock + */ + protected $client; + + /** + * @var array Default handler options + */ + protected $options = array( + 'index' => 'my_index', + 'type' => 'doc_type', + ); + + public function setUp() + { + // Elastica lib required + if (!class_exists("Elastica\Client")) { + $this->markTestSkipped("ruflin/elastica not installed"); + } + + // base mock Elastica Client object + $this->client = $this->getMockBuilder('Elastica\Client') + ->setMethods(array('addDocuments')) + ->disableOriginalConstructor() + ->getMock(); + } + + /** + * @covers Monolog\Handler\ElasticSearchHandler::write + * @covers Monolog\Handler\ElasticSearchHandler::handleBatch + * @covers Monolog\Handler\ElasticSearchHandler::bulkSend + * @covers Monolog\Handler\ElasticSearchHandler::getDefaultFormatter + */ + public function testHandle() + { + // log message + $msg = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('foo' => 7, 'bar', 'class' => new \stdClass), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ); + + // format expected result + $formatter = new ElasticaFormatter($this->options['index'], $this->options['type']); + $expected = array($formatter->format($msg)); + + // setup ES client mock + $this->client->expects($this->any()) + ->method('addDocuments') + ->with($expected); + + // perform tests + $handler = new ElasticSearchHandler($this->client, $this->options); + $handler->handle($msg); + $handler->handleBatch(array($msg)); + } + + /** + * @covers Monolog\Handler\ElasticSearchHandler::setFormatter + */ + public function testSetFormatter() + { + $handler = new ElasticSearchHandler($this->client); + $formatter = new ElasticaFormatter('index_new', 'type_new'); + $handler->setFormatter($formatter); + $this->assertInstanceOf('Monolog\Formatter\ElasticaFormatter', $handler->getFormatter()); + $this->assertEquals('index_new', $handler->getFormatter()->getIndex()); + $this->assertEquals('type_new', $handler->getFormatter()->getType()); + } + + /** + * @covers Monolog\Handler\ElasticSearchHandler::setFormatter + * @expectedException InvalidArgumentException + * @expectedExceptionMessage ElasticSearchHandler is only compatible with ElasticaFormatter + */ + public function testSetFormatterInvalid() + { + $handler = new ElasticSearchHandler($this->client); + $formatter = new NormalizerFormatter(); + $handler->setFormatter($formatter); + } + + /** + * @covers Monolog\Handler\ElasticSearchHandler::__construct + * @covers Monolog\Handler\ElasticSearchHandler::getOptions + */ + public function testOptions() + { + $expected = array( + 'index' => $this->options['index'], + 'type' => $this->options['type'], + 'ignore_error' => false, + ); + $handler = new ElasticSearchHandler($this->client, $this->options); + $this->assertEquals($expected, $handler->getOptions()); + } + + /** + * @covers Monolog\Handler\ElasticSearchHandler::bulkSend + * @dataProvider providerTestConnectionErrors + */ + public function testConnectionErrors($ignore, $expectedError) + { + $clientOpts = array('host' => '127.0.0.1', 'port' => 1); + $client = new Client($clientOpts); + $handlerOpts = array('ignore_error' => $ignore); + $handler = new ElasticSearchHandler($client, $handlerOpts); + + if ($expectedError) { + $this->setExpectedException($expectedError[0], $expectedError[1]); + $handler->handle($this->getRecord()); + } else { + $this->assertFalse($handler->handle($this->getRecord())); + } + } + + /** + * @return array + */ + public function providerTestConnectionErrors() + { + return array( + array(false, array('RuntimeException', 'Error sending messages to Elasticsearch')), + array(true, false), + ); + } + + /** + * Integration test using localhost Elastic Search server + * + * @covers Monolog\Handler\ElasticSearchHandler::__construct + * @covers Monolog\Handler\ElasticSearchHandler::handleBatch + * @covers Monolog\Handler\ElasticSearchHandler::bulkSend + * @covers Monolog\Handler\ElasticSearchHandler::getDefaultFormatter + */ + public function testHandleIntegration() + { + $msg = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('foo' => 7, 'bar', 'class' => new \stdClass), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ); + + $expected = $msg; + $expected['datetime'] = $msg['datetime']->format(\DateTime::ISO8601); + $expected['context'] = array( + 'class' => '[object] (stdClass: {})', + 'foo' => 7, + 0 => 'bar', + ); + + $client = new Client(); + $handler = new ElasticSearchHandler($client, $this->options); + try { + $handler->handleBatch(array($msg)); + } catch (\RuntimeException $e) { + $this->markTestSkipped("Cannot connect to Elastic Search server on localhost"); + } + + // check document id from ES server response + $documentId = $this->getCreatedDocId($client->getLastResponse()); + $this->assertNotEmpty($documentId, 'No elastic document id received'); + + // retrieve document source from ES and validate + $document = $this->getDocSourceFromElastic( + $client, + $this->options['index'], + $this->options['type'], + $documentId + ); + $this->assertEquals($expected, $document); + + // remove test index from ES + $client->request("/{$this->options['index']}", Request::DELETE); + } + + /** + * Return last created document id from ES response + * @param Response $response Elastica Response object + * @return string|null + */ + protected function getCreatedDocId(Response $response) + { + $data = $response->getData(); + if (!empty($data['items'][0]['create']['_id'])) { + return $data['items'][0]['create']['_id']; + } + } + + /** + * Retrieve document by id from Elasticsearch + * @param Client $client Elastica client + * @param string $index + * @param string $type + * @param string $documentId + * @return array + */ + protected function getDocSourceFromElastic(Client $client, $index, $type, $documentId) + { + $resp = $client->request("/{$index}/{$type}/{$documentId}", Request::GET); + $data = $resp->getData(); + if (!empty($data['_source'])) { + return $data['_source']; + } + + return array(); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/ErrorLogHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/ErrorLogHandlerTest.php new file mode 100644 index 00000000..99785cbb --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/ErrorLogHandlerTest.php @@ -0,0 +1,66 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; +use Monolog\Formatter\LineFormatter; + +function error_log() +{ + $GLOBALS['error_log'][] = func_get_args(); +} + +class ErrorLogHandlerTest extends TestCase +{ + protected function setUp() + { + $GLOBALS['error_log'] = array(); + } + + /** + * @covers Monolog\Handler\ErrorLogHandler::__construct + * @expectedException InvalidArgumentException + * @expectedExceptionMessage The given message type "42" is not supported + */ + public function testShouldNotAcceptAnInvalidTypeOnContructor() + { + new ErrorLogHandler(42); + } + + /** + * @covers Monolog\Handler\ErrorLogHandler::write + */ + public function testShouldLogMessagesUsingErrorLogFuncion() + { + $type = ErrorLogHandler::OPERATING_SYSTEM; + $handler = new ErrorLogHandler($type); + $handler->setFormatter(new LineFormatter('%channel%.%level_name%: %message% %context% %extra%', null, true)); + $handler->handle($this->getRecord(Logger::ERROR, "Foo\nBar\r\n\r\nBaz")); + + $this->assertSame("test.ERROR: Foo\nBar\r\n\r\nBaz [] []", $GLOBALS['error_log'][0][0]); + $this->assertSame($GLOBALS['error_log'][0][1], $type); + + $handler = new ErrorLogHandler($type, Logger::DEBUG, true, true); + $handler->setFormatter(new LineFormatter(null, null, true)); + $handler->handle($this->getRecord(Logger::ERROR, "Foo\nBar\r\n\r\nBaz")); + + $this->assertStringMatchesFormat('[%s] test.ERROR: Foo', $GLOBALS['error_log'][1][0]); + $this->assertSame($GLOBALS['error_log'][1][1], $type); + + $this->assertStringMatchesFormat('Bar', $GLOBALS['error_log'][2][0]); + $this->assertSame($GLOBALS['error_log'][2][1], $type); + + $this->assertStringMatchesFormat('Baz [] []', $GLOBALS['error_log'][3][0]); + $this->assertSame($GLOBALS['error_log'][3][1], $type); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/FilterHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/FilterHandlerTest.php new file mode 100644 index 00000000..31b7686a --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/FilterHandlerTest.php @@ -0,0 +1,170 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\TestCase; + +class FilterHandlerTest extends TestCase +{ + /** + * @covers Monolog\Handler\FilterHandler::isHandling + */ + public function testIsHandling() + { + $test = new TestHandler(); + $handler = new FilterHandler($test, Logger::INFO, Logger::NOTICE); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG))); + $this->assertTrue($handler->isHandling($this->getRecord(Logger::INFO))); + $this->assertTrue($handler->isHandling($this->getRecord(Logger::NOTICE))); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::WARNING))); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::ERROR))); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::CRITICAL))); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::ALERT))); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::EMERGENCY))); + } + + /** + * @covers Monolog\Handler\FilterHandler::handle + * @covers Monolog\Handler\FilterHandler::setAcceptedLevels + * @covers Monolog\Handler\FilterHandler::isHandling + */ + public function testHandleProcessOnlyNeededLevels() + { + $test = new TestHandler(); + $handler = new FilterHandler($test, Logger::INFO, Logger::NOTICE); + + $handler->handle($this->getRecord(Logger::DEBUG)); + $this->assertFalse($test->hasDebugRecords()); + + $handler->handle($this->getRecord(Logger::INFO)); + $this->assertTrue($test->hasInfoRecords()); + $handler->handle($this->getRecord(Logger::NOTICE)); + $this->assertTrue($test->hasNoticeRecords()); + + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertFalse($test->hasWarningRecords()); + $handler->handle($this->getRecord(Logger::ERROR)); + $this->assertFalse($test->hasErrorRecords()); + $handler->handle($this->getRecord(Logger::CRITICAL)); + $this->assertFalse($test->hasCriticalRecords()); + $handler->handle($this->getRecord(Logger::ALERT)); + $this->assertFalse($test->hasAlertRecords()); + $handler->handle($this->getRecord(Logger::EMERGENCY)); + $this->assertFalse($test->hasEmergencyRecords()); + + $test = new TestHandler(); + $handler = new FilterHandler($test, array(Logger::INFO, Logger::ERROR)); + + $handler->handle($this->getRecord(Logger::DEBUG)); + $this->assertFalse($test->hasDebugRecords()); + $handler->handle($this->getRecord(Logger::INFO)); + $this->assertTrue($test->hasInfoRecords()); + $handler->handle($this->getRecord(Logger::NOTICE)); + $this->assertFalse($test->hasNoticeRecords()); + $handler->handle($this->getRecord(Logger::ERROR)); + $this->assertTrue($test->hasErrorRecords()); + $handler->handle($this->getRecord(Logger::CRITICAL)); + $this->assertFalse($test->hasCriticalRecords()); + } + + /** + * @covers Monolog\Handler\FilterHandler::setAcceptedLevels + * @covers Monolog\Handler\FilterHandler::getAcceptedLevels + */ + public function testAcceptedLevelApi() + { + $test = new TestHandler(); + $handler = new FilterHandler($test); + + $levels = array(Logger::INFO, Logger::ERROR); + $handler->setAcceptedLevels($levels); + $this->assertSame($levels, $handler->getAcceptedLevels()); + + $handler->setAcceptedLevels(array('info', 'error')); + $this->assertSame($levels, $handler->getAcceptedLevels()); + + $levels = array(Logger::CRITICAL, Logger::ALERT, Logger::EMERGENCY); + $handler->setAcceptedLevels(Logger::CRITICAL, Logger::EMERGENCY); + $this->assertSame($levels, $handler->getAcceptedLevels()); + + $handler->setAcceptedLevels('critical', 'emergency'); + $this->assertSame($levels, $handler->getAcceptedLevels()); + } + + /** + * @covers Monolog\Handler\FilterHandler::handle + */ + public function testHandleUsesProcessors() + { + $test = new TestHandler(); + $handler = new FilterHandler($test, Logger::DEBUG, Logger::EMERGENCY); + $handler->pushProcessor( + function ($record) { + $record['extra']['foo'] = true; + + return $record; + } + ); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertTrue($test->hasWarningRecords()); + $records = $test->getRecords(); + $this->assertTrue($records[0]['extra']['foo']); + } + + /** + * @covers Monolog\Handler\FilterHandler::handle + */ + public function testHandleRespectsBubble() + { + $test = new TestHandler(); + + $handler = new FilterHandler($test, Logger::INFO, Logger::NOTICE, false); + $this->assertTrue($handler->handle($this->getRecord(Logger::INFO))); + $this->assertFalse($handler->handle($this->getRecord(Logger::WARNING))); + + $handler = new FilterHandler($test, Logger::INFO, Logger::NOTICE, true); + $this->assertFalse($handler->handle($this->getRecord(Logger::INFO))); + $this->assertFalse($handler->handle($this->getRecord(Logger::WARNING))); + } + + /** + * @covers Monolog\Handler\FilterHandler::handle + */ + public function testHandleWithCallback() + { + $test = new TestHandler(); + $handler = new FilterHandler( + function ($record, $handler) use ($test) { + return $test; + }, Logger::INFO, Logger::NOTICE, false + ); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + $this->assertFalse($test->hasDebugRecords()); + $this->assertTrue($test->hasInfoRecords()); + } + + /** + * @covers Monolog\Handler\FilterHandler::handle + * @expectedException \RuntimeException + */ + public function testHandleWithBadCallbackThrowsException() + { + $handler = new FilterHandler( + function ($record, $handler) { + return 'foo'; + } + ); + $handler->handle($this->getRecord(Logger::WARNING)); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/FingersCrossedHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/FingersCrossedHandlerTest.php new file mode 100644 index 00000000..a3d350d5 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/FingersCrossedHandlerTest.php @@ -0,0 +1,240 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; +use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy; +use Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy; + +class FingersCrossedHandlerTest extends TestCase +{ + /** + * @covers Monolog\Handler\FingersCrossedHandler::__construct + * @covers Monolog\Handler\FingersCrossedHandler::handle + */ + public function testHandleBuffers() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + $this->assertFalse($test->hasDebugRecords()); + $this->assertFalse($test->hasInfoRecords()); + $handler->handle($this->getRecord(Logger::WARNING)); + $handler->close(); + $this->assertTrue($test->hasInfoRecords()); + $this->assertTrue(count($test->getRecords()) === 3); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::handle + */ + public function testHandleStopsBufferingAfterTrigger() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test); + $handler->handle($this->getRecord(Logger::WARNING)); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->close(); + $this->assertTrue($test->hasWarningRecords()); + $this->assertTrue($test->hasDebugRecords()); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::handle + * @covers Monolog\Handler\FingersCrossedHandler::reset + */ + public function testHandleRestartBufferingAfterReset() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test); + $handler->handle($this->getRecord(Logger::WARNING)); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->reset(); + $handler->handle($this->getRecord(Logger::INFO)); + $handler->close(); + $this->assertTrue($test->hasWarningRecords()); + $this->assertTrue($test->hasDebugRecords()); + $this->assertFalse($test->hasInfoRecords()); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::handle + */ + public function testHandleRestartBufferingAfterBeingTriggeredWhenStopBufferingIsDisabled() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test, Logger::WARNING, 0, false, false); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::WARNING)); + $handler->handle($this->getRecord(Logger::INFO)); + $handler->close(); + $this->assertTrue($test->hasWarningRecords()); + $this->assertTrue($test->hasDebugRecords()); + $this->assertFalse($test->hasInfoRecords()); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::handle + */ + public function testHandleBufferLimit() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test, Logger::WARNING, 2); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertTrue($test->hasWarningRecords()); + $this->assertTrue($test->hasInfoRecords()); + $this->assertFalse($test->hasDebugRecords()); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::handle + */ + public function testHandleWithCallback() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler(function ($record, $handler) use ($test) { + return $test; + }); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + $this->assertFalse($test->hasDebugRecords()); + $this->assertFalse($test->hasInfoRecords()); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertTrue($test->hasInfoRecords()); + $this->assertTrue(count($test->getRecords()) === 3); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::handle + * @expectedException RuntimeException + */ + public function testHandleWithBadCallbackThrowsException() + { + $handler = new FingersCrossedHandler(function ($record, $handler) { + return 'foo'; + }); + $handler->handle($this->getRecord(Logger::WARNING)); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::isHandling + */ + public function testIsHandlingAlways() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test, Logger::ERROR); + $this->assertTrue($handler->isHandling($this->getRecord(Logger::DEBUG))); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::__construct + * @covers Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy::__construct + * @covers Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy::isHandlerActivated + */ + public function testErrorLevelActivationStrategy() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test, new ErrorLevelActivationStrategy(Logger::WARNING)); + $handler->handle($this->getRecord(Logger::DEBUG)); + $this->assertFalse($test->hasDebugRecords()); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertTrue($test->hasDebugRecords()); + $this->assertTrue($test->hasWarningRecords()); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::__construct + * @covers Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy::__construct + * @covers Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy::isHandlerActivated + */ + public function testErrorLevelActivationStrategyWithPsrLevel() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test, new ErrorLevelActivationStrategy('warning')); + $handler->handle($this->getRecord(Logger::DEBUG)); + $this->assertFalse($test->hasDebugRecords()); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertTrue($test->hasDebugRecords()); + $this->assertTrue($test->hasWarningRecords()); + } + + /** + * @covers Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy::__construct + * @covers Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy::isHandlerActivated + */ + public function testChannelLevelActivationStrategy() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test, new ChannelLevelActivationStrategy(Logger::ERROR, array('othertest' => Logger::DEBUG))); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertFalse($test->hasWarningRecords()); + $record = $this->getRecord(Logger::DEBUG); + $record['channel'] = 'othertest'; + $handler->handle($record); + $this->assertTrue($test->hasDebugRecords()); + $this->assertTrue($test->hasWarningRecords()); + } + + /** + * @covers Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy::__construct + * @covers Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy::isHandlerActivated + */ + public function testChannelLevelActivationStrategyWithPsrLevels() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test, new ChannelLevelActivationStrategy('error', array('othertest' => 'debug'))); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertFalse($test->hasWarningRecords()); + $record = $this->getRecord(Logger::DEBUG); + $record['channel'] = 'othertest'; + $handler->handle($record); + $this->assertTrue($test->hasDebugRecords()); + $this->assertTrue($test->hasWarningRecords()); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::handle + */ + public function testHandleUsesProcessors() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test, Logger::INFO); + $handler->pushProcessor(function ($record) { + $record['extra']['foo'] = true; + + return $record; + }); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertTrue($test->hasWarningRecords()); + $records = $test->getRecords(); + $this->assertTrue($records[0]['extra']['foo']); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::close + */ + public function testPassthruOnClose() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test, new ErrorLevelActivationStrategy(Logger::WARNING), 0, true, true, Logger::INFO); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + $handler->close(); + $this->assertFalse($test->hasDebugRecords()); + $this->assertTrue($test->hasInfoRecords()); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/FirePHPHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/FirePHPHandlerTest.php new file mode 100644 index 00000000..0eb10a63 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/FirePHPHandlerTest.php @@ -0,0 +1,96 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; + +/** + * @covers Monolog\Handler\FirePHPHandler + */ +class FirePHPHandlerTest extends TestCase +{ + public function setUp() + { + TestFirePHPHandler::reset(); + $_SERVER['HTTP_USER_AGENT'] = 'Monolog Test; FirePHP/1.0'; + } + + public function testHeaders() + { + $handler = new TestFirePHPHandler; + $handler->setFormatter($this->getIdentityFormatter()); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::WARNING)); + + $expected = array( + 'X-Wf-Protocol-1' => 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2', + 'X-Wf-1-Structure-1' => 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1', + 'X-Wf-1-Plugin-1' => 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3', + 'X-Wf-1-1-1-1' => 'test', + 'X-Wf-1-1-1-2' => 'test', + ); + + $this->assertEquals($expected, $handler->getHeaders()); + } + + public function testConcurrentHandlers() + { + $handler = new TestFirePHPHandler; + $handler->setFormatter($this->getIdentityFormatter()); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::WARNING)); + + $handler2 = new TestFirePHPHandler; + $handler2->setFormatter($this->getIdentityFormatter()); + $handler2->handle($this->getRecord(Logger::DEBUG)); + $handler2->handle($this->getRecord(Logger::WARNING)); + + $expected = array( + 'X-Wf-Protocol-1' => 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2', + 'X-Wf-1-Structure-1' => 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1', + 'X-Wf-1-Plugin-1' => 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3', + 'X-Wf-1-1-1-1' => 'test', + 'X-Wf-1-1-1-2' => 'test', + ); + + $expected2 = array( + 'X-Wf-1-1-1-3' => 'test', + 'X-Wf-1-1-1-4' => 'test', + ); + + $this->assertEquals($expected, $handler->getHeaders()); + $this->assertEquals($expected2, $handler2->getHeaders()); + } +} + +class TestFirePHPHandler extends FirePHPHandler +{ + protected $headers = array(); + + public static function reset() + { + self::$initialized = false; + self::$sendHeaders = true; + self::$messageIndex = 1; + } + + protected function sendHeader($header, $content) + { + $this->headers[$header] = $content; + } + + public function getHeaders() + { + return $this->headers; + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/FleepHookHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/FleepHookHandlerTest.php new file mode 100644 index 00000000..91cdd312 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/FleepHookHandlerTest.php @@ -0,0 +1,85 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\LineFormatter; +use Monolog\Logger; +use Monolog\TestCase; + +/** + * @coversDefaultClass \Monolog\Handler\FleepHookHandler + */ +class FleepHookHandlerTest extends TestCase +{ + /** + * Default token to use in tests + */ + const TOKEN = '123abc'; + + /** + * @var FleepHookHandler + */ + private $handler; + + public function setUp() + { + parent::setUp(); + + if (!extension_loaded('openssl')) { + $this->markTestSkipped('This test requires openssl extension to run'); + } + + // Create instances of the handler and logger for convenience + $this->handler = new FleepHookHandler(self::TOKEN); + } + + /** + * @covers ::__construct + */ + public function testConstructorSetsExpectedDefaults() + { + $this->assertEquals(Logger::DEBUG, $this->handler->getLevel()); + $this->assertEquals(true, $this->handler->getBubble()); + } + + /** + * @covers ::getDefaultFormatter + */ + public function testHandlerUsesLineFormatterWhichIgnoresEmptyArrays() + { + $record = array( + 'message' => 'msg', + 'context' => array(), + 'level' => Logger::DEBUG, + 'level_name' => Logger::getLevelName(Logger::DEBUG), + 'channel' => 'channel', + 'datetime' => new \DateTime(), + 'extra' => array(), + ); + + $expectedFormatter = new LineFormatter(null, null, true, true); + $expected = $expectedFormatter->format($record); + + $handlerFormatter = $this->handler->getFormatter(); + $actual = $handlerFormatter->format($record); + + $this->assertEquals($expected, $actual, 'Empty context and extra arrays should not be rendered'); + } + + /** + * @covers ::__construct + */ + public function testConnectionStringisConstructedCorrectly() + { + $this->assertEquals('ssl://' . FleepHookHandler::FLEEP_HOST . ':443', $this->handler->getConnectionString()); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/FlowdockHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/FlowdockHandlerTest.php new file mode 100644 index 00000000..4b120d51 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/FlowdockHandlerTest.php @@ -0,0 +1,88 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Formatter\FlowdockFormatter; +use Monolog\TestCase; +use Monolog\Logger; + +/** + * @author Dominik Liebler <liebler.dominik@gmail.com> + * @see https://www.hipchat.com/docs/api + */ +class FlowdockHandlerTest extends TestCase +{ + /** + * @var resource + */ + private $res; + + /** + * @var FlowdockHandler + */ + private $handler; + + public function setUp() + { + if (!extension_loaded('openssl')) { + $this->markTestSkipped('This test requires openssl to run'); + } + } + + public function testWriteHeader() + { + $this->createHandler(); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/POST \/v1\/messages\/team_inbox\/.* HTTP\/1.1\\r\\nHost: api.flowdock.com\\r\\nContent-Type: application\/json\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content); + + return $content; + } + + /** + * @depends testWriteHeader + */ + public function testWriteContent($content) + { + $this->assertRegexp('/"source":"test_source"/', $content); + $this->assertRegexp('/"from_address":"source@test\.com"/', $content); + } + + private function createHandler($token = 'myToken') + { + $constructorArgs = array($token, Logger::DEBUG); + $this->res = fopen('php://memory', 'a'); + $this->handler = $this->getMock( + '\Monolog\Handler\FlowdockHandler', + array('fsockopen', 'streamSetTimeout', 'closeSocket'), + $constructorArgs + ); + + $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($this->handler, 'localhost:1234'); + + $this->handler->expects($this->any()) + ->method('fsockopen') + ->will($this->returnValue($this->res)); + $this->handler->expects($this->any()) + ->method('streamSetTimeout') + ->will($this->returnValue(true)); + $this->handler->expects($this->any()) + ->method('closeSocket') + ->will($this->returnValue(true)); + + $this->handler->setFormatter(new FlowdockFormatter('test_source', 'source@test.com')); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/GelfHandlerLegacyTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/GelfHandlerLegacyTest.php new file mode 100644 index 00000000..d60a6db3 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/GelfHandlerLegacyTest.php @@ -0,0 +1,93 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Gelf\Message; +use Monolog\TestCase; +use Monolog\Logger; +use Monolog\Formatter\GelfMessageFormatter; + +class GelfHandlerLegacyTest extends TestCase +{ + public function setUp() + { + if (!class_exists('Gelf\MessagePublisher') || !class_exists('Gelf\Message')) { + $this->markTestSkipped("mlehner/gelf-php not installed"); + } + } + + /** + * @covers Monolog\Handler\GelfHandler::__construct + */ + public function testConstruct() + { + $handler = new GelfHandler($this->getMessagePublisher()); + $this->assertInstanceOf('Monolog\Handler\GelfHandler', $handler); + } + + protected function getHandler($messagePublisher) + { + $handler = new GelfHandler($messagePublisher); + + return $handler; + } + + protected function getMessagePublisher() + { + return new MockMessagePublisher('localhost'); + } + + public function testDebug() + { + $messagePublisher = $this->getMessagePublisher(); + $handler = $this->getHandler($messagePublisher); + + $record = $this->getRecord(Logger::DEBUG, "A test debug message"); + $handler->handle($record); + + $this->assertEquals(7, $messagePublisher->lastMessage->getLevel()); + $this->assertEquals('test', $messagePublisher->lastMessage->getFacility()); + $this->assertEquals($record['message'], $messagePublisher->lastMessage->getShortMessage()); + $this->assertEquals(null, $messagePublisher->lastMessage->getFullMessage()); + } + + public function testWarning() + { + $messagePublisher = $this->getMessagePublisher(); + $handler = $this->getHandler($messagePublisher); + + $record = $this->getRecord(Logger::WARNING, "A test warning message"); + $handler->handle($record); + + $this->assertEquals(4, $messagePublisher->lastMessage->getLevel()); + $this->assertEquals('test', $messagePublisher->lastMessage->getFacility()); + $this->assertEquals($record['message'], $messagePublisher->lastMessage->getShortMessage()); + $this->assertEquals(null, $messagePublisher->lastMessage->getFullMessage()); + } + + public function testInjectedGelfMessageFormatter() + { + $messagePublisher = $this->getMessagePublisher(); + $handler = $this->getHandler($messagePublisher); + + $handler->setFormatter(new GelfMessageFormatter('mysystem', 'EXT', 'CTX')); + + $record = $this->getRecord(Logger::WARNING, "A test warning message"); + $record['extra']['blarg'] = 'yep'; + $record['context']['from'] = 'logger'; + $handler->handle($record); + + $this->assertEquals('mysystem', $messagePublisher->lastMessage->getHost()); + $this->assertArrayHasKey('_EXTblarg', $messagePublisher->lastMessage->toArray()); + $this->assertArrayHasKey('_CTXfrom', $messagePublisher->lastMessage->toArray()); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/GelfHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/GelfHandlerTest.php new file mode 100644 index 00000000..8cdd64f4 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/GelfHandlerTest.php @@ -0,0 +1,117 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Gelf\Message; +use Monolog\TestCase; +use Monolog\Logger; +use Monolog\Formatter\GelfMessageFormatter; + +class GelfHandlerTest extends TestCase +{ + public function setUp() + { + if (!class_exists('Gelf\Publisher') || !class_exists('Gelf\Message')) { + $this->markTestSkipped("graylog2/gelf-php not installed"); + } + } + + /** + * @covers Monolog\Handler\GelfHandler::__construct + */ + public function testConstruct() + { + $handler = new GelfHandler($this->getMessagePublisher()); + $this->assertInstanceOf('Monolog\Handler\GelfHandler', $handler); + } + + protected function getHandler($messagePublisher) + { + $handler = new GelfHandler($messagePublisher); + + return $handler; + } + + protected function getMessagePublisher() + { + return $this->getMock('Gelf\Publisher', array('publish'), array(), '', false); + } + + public function testDebug() + { + $record = $this->getRecord(Logger::DEBUG, "A test debug message"); + $expectedMessage = new Message(); + $expectedMessage + ->setLevel(7) + ->setFacility("test") + ->setShortMessage($record['message']) + ->setTimestamp($record['datetime']) + ; + + $messagePublisher = $this->getMessagePublisher(); + $messagePublisher->expects($this->once()) + ->method('publish') + ->with($expectedMessage); + + $handler = $this->getHandler($messagePublisher); + + $handler->handle($record); + } + + public function testWarning() + { + $record = $this->getRecord(Logger::WARNING, "A test warning message"); + $expectedMessage = new Message(); + $expectedMessage + ->setLevel(4) + ->setFacility("test") + ->setShortMessage($record['message']) + ->setTimestamp($record['datetime']) + ; + + $messagePublisher = $this->getMessagePublisher(); + $messagePublisher->expects($this->once()) + ->method('publish') + ->with($expectedMessage); + + $handler = $this->getHandler($messagePublisher); + + $handler->handle($record); + } + + public function testInjectedGelfMessageFormatter() + { + $record = $this->getRecord(Logger::WARNING, "A test warning message"); + $record['extra']['blarg'] = 'yep'; + $record['context']['from'] = 'logger'; + + $expectedMessage = new Message(); + $expectedMessage + ->setLevel(4) + ->setFacility("test") + ->setHost("mysystem") + ->setShortMessage($record['message']) + ->setTimestamp($record['datetime']) + ->setAdditional("EXTblarg", 'yep') + ->setAdditional("CTXfrom", 'logger') + ; + + $messagePublisher = $this->getMessagePublisher(); + $messagePublisher->expects($this->once()) + ->method('publish') + ->with($expectedMessage); + + $handler = $this->getHandler($messagePublisher); + $handler->setFormatter(new GelfMessageFormatter('mysystem', 'EXT', 'CTX')); + $handler->handle($record); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/GroupHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/GroupHandlerTest.php new file mode 100644 index 00000000..c6298a6e --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/GroupHandlerTest.php @@ -0,0 +1,89 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; + +class GroupHandlerTest extends TestCase +{ + /** + * @covers Monolog\Handler\GroupHandler::__construct + * @expectedException InvalidArgumentException + */ + public function testConstructorOnlyTakesHandler() + { + new GroupHandler(array(new TestHandler(), "foo")); + } + + /** + * @covers Monolog\Handler\GroupHandler::__construct + * @covers Monolog\Handler\GroupHandler::handle + */ + public function testHandle() + { + $testHandlers = array(new TestHandler(), new TestHandler()); + $handler = new GroupHandler($testHandlers); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + foreach ($testHandlers as $test) { + $this->assertTrue($test->hasDebugRecords()); + $this->assertTrue($test->hasInfoRecords()); + $this->assertTrue(count($test->getRecords()) === 2); + } + } + + /** + * @covers Monolog\Handler\GroupHandler::handleBatch + */ + public function testHandleBatch() + { + $testHandlers = array(new TestHandler(), new TestHandler()); + $handler = new GroupHandler($testHandlers); + $handler->handleBatch(array($this->getRecord(Logger::DEBUG), $this->getRecord(Logger::INFO))); + foreach ($testHandlers as $test) { + $this->assertTrue($test->hasDebugRecords()); + $this->assertTrue($test->hasInfoRecords()); + $this->assertTrue(count($test->getRecords()) === 2); + } + } + + /** + * @covers Monolog\Handler\GroupHandler::isHandling + */ + public function testIsHandling() + { + $testHandlers = array(new TestHandler(Logger::ERROR), new TestHandler(Logger::WARNING)); + $handler = new GroupHandler($testHandlers); + $this->assertTrue($handler->isHandling($this->getRecord(Logger::ERROR))); + $this->assertTrue($handler->isHandling($this->getRecord(Logger::WARNING))); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG))); + } + + /** + * @covers Monolog\Handler\GroupHandler::handle + */ + public function testHandleUsesProcessors() + { + $test = new TestHandler(); + $handler = new GroupHandler(array($test)); + $handler->pushProcessor(function ($record) { + $record['extra']['foo'] = true; + + return $record; + }); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertTrue($test->hasWarningRecords()); + $records = $test->getRecords(); + $this->assertTrue($records[0]['extra']['foo']); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/HipChatHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/HipChatHandlerTest.php new file mode 100644 index 00000000..d58386a1 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/HipChatHandlerTest.php @@ -0,0 +1,166 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; + +/** + * @author Rafael Dohms <rafael@doh.ms> + * @see https://www.hipchat.com/docs/api + */ +class HipChatHandlerTest extends TestCase +{ + private $res; + private $handler; + + public function testWriteHeader() + { + $this->createHandler(); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/POST \/v1\/rooms\/message\?format=json&auth_token=.* HTTP\/1.1\\r\\nHost: api.hipchat.com\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content); + + return $content; + } + + /** + * @depends testWriteHeader + */ + public function testWriteContent($content) + { + $this->assertRegexp('/from=Monolog&room_id=room1¬ify=0&message=test1&message_format=text&color=red$/', $content); + } + + public function testWriteWithComplexMessage() + { + $this->createHandler(); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'Backup of database "example" finished in 16 minutes.')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/message=Backup\+of\+database\+%22example%22\+finished\+in\+16\+minutes\./', $content); + } + + /** + * @dataProvider provideLevelColors + */ + public function testWriteWithErrorLevelsAndColors($level, $expectedColor) + { + $this->createHandler(); + $this->handler->handle($this->getRecord($level, 'Backup of database "example" finished in 16 minutes.')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/color='.$expectedColor.'/', $content); + } + + public function provideLevelColors() + { + return array( + array(Logger::DEBUG, 'gray'), + array(Logger::INFO, 'green'), + array(Logger::WARNING, 'yellow'), + array(Logger::ERROR, 'red'), + array(Logger::CRITICAL, 'red'), + array(Logger::ALERT, 'red'), + array(Logger::EMERGENCY,'red'), + array(Logger::NOTICE, 'green'), + ); + } + + /** + * @dataProvider provideBatchRecords + */ + public function testHandleBatch($records, $expectedColor) + { + $this->createHandler(); + + $this->handler->handleBatch($records); + + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/color='.$expectedColor.'/', $content); + } + + public function provideBatchRecords() + { + return array( + array( + array( + array('level' => Logger::WARNING, 'message' => 'Oh bugger!', 'level_name' => 'warning', 'datetime' => new \DateTime()), + array('level' => Logger::NOTICE, 'message' => 'Something noticeable happened.', 'level_name' => 'notice', 'datetime' => new \DateTime()), + array('level' => Logger::CRITICAL, 'message' => 'Everything is broken!', 'level_name' => 'critical', 'datetime' => new \DateTime()) + ), + 'red', + ), + array( + array( + array('level' => Logger::WARNING, 'message' => 'Oh bugger!', 'level_name' => 'warning', 'datetime' => new \DateTime()), + array('level' => Logger::NOTICE, 'message' => 'Something noticeable happened.', 'level_name' => 'notice', 'datetime' => new \DateTime()), + ), + 'yellow', + ), + array( + array( + array('level' => Logger::DEBUG, 'message' => 'Just debugging.', 'level_name' => 'debug', 'datetime' => new \DateTime()), + array('level' => Logger::NOTICE, 'message' => 'Something noticeable happened.', 'level_name' => 'notice', 'datetime' => new \DateTime()), + ), + 'green', + ), + array( + array( + array('level' => Logger::DEBUG, 'message' => 'Just debugging.', 'level_name' => 'debug', 'datetime' => new \DateTime()), + ), + 'gray', + ), + ); + } + + private function createHandler($token = 'myToken', $room = 'room1', $name = 'Monolog', $notify = false) + { + $constructorArgs = array($token, $room, $name, $notify, Logger::DEBUG); + $this->res = fopen('php://memory', 'a'); + $this->handler = $this->getMock( + '\Monolog\Handler\HipChatHandler', + array('fsockopen', 'streamSetTimeout', 'closeSocket'), + $constructorArgs + ); + + $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($this->handler, 'localhost:1234'); + + $this->handler->expects($this->any()) + ->method('fsockopen') + ->will($this->returnValue($this->res)); + $this->handler->expects($this->any()) + ->method('streamSetTimeout') + ->will($this->returnValue(true)); + $this->handler->expects($this->any()) + ->method('closeSocket') + ->will($this->returnValue(true)); + + $this->handler->setFormatter($this->getIdentityFormatter()); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testCreateWithTooLongName() + { + $hipChatHandler = new \Monolog\Handler\HipChatHandler('token', 'room', 'SixteenCharsHere'); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/LogEntriesHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/LogEntriesHandlerTest.php new file mode 100644 index 00000000..7af60be8 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/LogEntriesHandlerTest.php @@ -0,0 +1,84 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; + +/** + * @author Robert Kaufmann III <rok3@rok3.me> + */ +class LogEntriesHandlerTest extends TestCase +{ + /** + * @var resource + */ + private $res; + + /** + * @var LogEntriesHandler + */ + private $handler; + + public function testWriteContent() + { + $this->createHandler(); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'Critical write test')); + + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/testToken \[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\] test.CRITICAL: Critical write test/', $content); + } + + public function testWriteBatchContent() + { + $records = array( + $this->getRecord(), + $this->getRecord(), + $this->getRecord() + ); + $this->createHandler(); + $this->handler->handleBatch($records); + + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/(testToken \[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\] .* \[\] \[\]\n){3}/', $content); + } + + private function createHandler() + { + $useSSL = extension_loaded('openssl'); + $args = array('testToken', $useSSL, Logger::DEBUG, true); + $this->res = fopen('php://memory', 'a'); + $this->handler = $this->getMock( + '\Monolog\Handler\LogEntriesHandler', + array('fsockopen', 'streamSetTimeout', 'closeSocket'), + $args + ); + + $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($this->handler, 'localhost:1234'); + + $this->handler->expects($this->any()) + ->method('fsockopen') + ->will($this->returnValue($this->res)); + $this->handler->expects($this->any()) + ->method('streamSetTimeout') + ->will($this->returnValue(true)); + $this->handler->expects($this->any()) + ->method('closeSocket') + ->will($this->returnValue(true)); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/MailHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/MailHandlerTest.php new file mode 100644 index 00000000..6754f3d6 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/MailHandlerTest.php @@ -0,0 +1,75 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\TestCase; + +class MailHandlerTest extends TestCase +{ + /** + * @covers Monolog\Handler\MailHandler::handleBatch + */ + public function testHandleBatch() + { + $formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface'); + $formatter->expects($this->once()) + ->method('formatBatch'); // Each record is formatted + + $handler = $this->getMockForAbstractClass('Monolog\\Handler\\MailHandler'); + $handler->expects($this->once()) + ->method('send'); + $handler->expects($this->never()) + ->method('write'); // write is for individual records + + $handler->setFormatter($formatter); + + $handler->handleBatch($this->getMultipleRecords()); + } + + /** + * @covers Monolog\Handler\MailHandler::handleBatch + */ + public function testHandleBatchNotSendsMailIfMessagesAreBelowLevel() + { + $records = array( + $this->getRecord(Logger::DEBUG, 'debug message 1'), + $this->getRecord(Logger::DEBUG, 'debug message 2'), + $this->getRecord(Logger::INFO, 'information'), + ); + + $handler = $this->getMockForAbstractClass('Monolog\\Handler\\MailHandler'); + $handler->expects($this->never()) + ->method('send'); + $handler->setLevel(Logger::ERROR); + + $handler->handleBatch($records); + } + + /** + * @covers Monolog\Handler\MailHandler::write + */ + public function testHandle() + { + $handler = $this->getMockForAbstractClass('Monolog\\Handler\\MailHandler'); + + $record = $this->getRecord(); + $records = array($record); + $records[0]['formatted'] = '['.$record['datetime']->format('Y-m-d H:i:s').'] test.WARNING: test [] []'."\n"; + + $handler->expects($this->once()) + ->method('send') + ->with($records[0]['formatted'], $records); + + $handler->handle($record); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/MockRavenClient.php b/vendor/monolog/monolog/tests/Monolog/Handler/MockRavenClient.php new file mode 100644 index 00000000..fbaab9bc --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/MockRavenClient.php @@ -0,0 +1,26 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Raven_Client; + +class MockRavenClient extends Raven_Client +{ + public function capture($data, $stack, $vars = null) + { + $this->lastData = $data; + $this->lastStack = $stack; + } + + public $lastData; + public $lastStack; +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/MongoDBHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/MongoDBHandlerTest.php new file mode 100644 index 00000000..0fdef63a --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/MongoDBHandlerTest.php @@ -0,0 +1,65 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; + +class MongoDBHandlerTest extends TestCase +{ + /** + * @expectedException InvalidArgumentException + */ + public function testConstructorShouldThrowExceptionForInvalidMongo() + { + new MongoDBHandler(new \stdClass(), 'DB', 'Collection'); + } + + public function testHandle() + { + $mongo = $this->getMock('Mongo', array('selectCollection'), array(), '', false); + $collection = $this->getMock('stdClass', array('save')); + + $mongo->expects($this->once()) + ->method('selectCollection') + ->with('DB', 'Collection') + ->will($this->returnValue($collection)); + + $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); + + $expected = array( + 'message' => 'test', + 'context' => array('data' => '[object] (stdClass: {})', 'foo' => 34), + 'level' => Logger::WARNING, + 'level_name' => 'WARNING', + 'channel' => 'test', + 'datetime' => $record['datetime']->format('Y-m-d H:i:s'), + 'extra' => array(), + ); + + $collection->expects($this->once()) + ->method('save') + ->with($expected); + + $handler = new MongoDBHandler($mongo, 'DB', 'Collection'); + $handler->handle($record); + } +} + +if (!class_exists('Mongo')) { + class Mongo + { + public function selectCollection() + { + } + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/NativeMailerHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/NativeMailerHandlerTest.php new file mode 100644 index 00000000..c2553ee4 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/NativeMailerHandlerTest.php @@ -0,0 +1,61 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; + +class NativeMailerHandlerTest extends TestCase +{ + /** + * @expectedException InvalidArgumentException + */ + public function testConstructorHeaderInjection() + { + $mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', "receiver@example.org\r\nFrom: faked@attacker.org"); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testSetterHeaderInjection() + { + $mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', 'receiver@example.org'); + $mailer->addHeader("Content-Type: text/html\r\nFrom: faked@attacker.org"); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testSetterArrayHeaderInjection() + { + $mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', 'receiver@example.org'); + $mailer->addHeader(array("Content-Type: text/html\r\nFrom: faked@attacker.org")); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testSetterContentTypeInjection() + { + $mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', 'receiver@example.org'); + $mailer->setContentType("text/html\r\nFrom: faked@attacker.org"); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testSetterEncodingInjection() + { + $mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', 'receiver@example.org'); + $mailer->setEncoding("utf-8\r\nFrom: faked@attacker.org"); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/NewRelicHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/NewRelicHandlerTest.php new file mode 100644 index 00000000..22014908 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/NewRelicHandlerTest.php @@ -0,0 +1,192 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; + +class NewRelicHandlerTest extends TestCase +{ + public static $appname; + public static $customParameters; + public static $transactionName; + + public function setUp() + { + self::$appname = null; + self::$customParameters = array(); + self::$transactionName = null; + } + + /** + * @expectedException Monolog\Handler\MissingExtensionException + */ + public function testThehandlerThrowsAnExceptionIfTheNRExtensionIsNotLoaded() + { + $handler = new StubNewRelicHandlerWithoutExtension(); + $handler->handle($this->getRecord(Logger::ERROR)); + } + + public function testThehandlerCanHandleTheRecord() + { + $handler = new StubNewRelicHandler(); + $handler->handle($this->getRecord(Logger::ERROR)); + } + + public function testThehandlerCanAddContextParamsToTheNewRelicTrace() + { + $handler = new StubNewRelicHandler(); + $handler->handle($this->getRecord(Logger::ERROR, 'log message', array('a' => 'b'))); + $this->assertEquals(array('context_a' => 'b'), self::$customParameters); + } + + public function testThehandlerCanAddExplodedContextParamsToTheNewRelicTrace() + { + $handler = new StubNewRelicHandler(Logger::ERROR, true, self::$appname, true); + $handler->handle($this->getRecord( + Logger::ERROR, + 'log message', + array('a' => array('key1' => 'value1', 'key2' => 'value2')) + )); + $this->assertEquals( + array('context_a_key1' => 'value1', 'context_a_key2' => 'value2'), + self::$customParameters + ); + } + + public function testThehandlerCanAddExtraParamsToTheNewRelicTrace() + { + $record = $this->getRecord(Logger::ERROR, 'log message'); + $record['extra'] = array('c' => 'd'); + + $handler = new StubNewRelicHandler(); + $handler->handle($record); + + $this->assertEquals(array('extra_c' => 'd'), self::$customParameters); + } + + public function testThehandlerCanAddExplodedExtraParamsToTheNewRelicTrace() + { + $record = $this->getRecord(Logger::ERROR, 'log message'); + $record['extra'] = array('c' => array('key1' => 'value1', 'key2' => 'value2')); + + $handler = new StubNewRelicHandler(Logger::ERROR, true, self::$appname, true); + $handler->handle($record); + + $this->assertEquals( + array('extra_c_key1' => 'value1', 'extra_c_key2' => 'value2'), + self::$customParameters + ); + } + + public function testThehandlerCanAddExtraContextAndParamsToTheNewRelicTrace() + { + $record = $this->getRecord(Logger::ERROR, 'log message', array('a' => 'b')); + $record['extra'] = array('c' => 'd'); + + $handler = new StubNewRelicHandler(); + $handler->handle($record); + + $expected = array( + 'context_a' => 'b', + 'extra_c' => 'd', + ); + + $this->assertEquals($expected, self::$customParameters); + } + + public function testTheAppNameIsNullByDefault() + { + $handler = new StubNewRelicHandler(); + $handler->handle($this->getRecord(Logger::ERROR, 'log message')); + + $this->assertEquals(null, self::$appname); + } + + public function testTheAppNameCanBeInjectedFromtheConstructor() + { + $handler = new StubNewRelicHandler(Logger::DEBUG, false, 'myAppName'); + $handler->handle($this->getRecord(Logger::ERROR, 'log message')); + + $this->assertEquals('myAppName', self::$appname); + } + + public function testTheAppNameCanBeOverriddenFromEachLog() + { + $handler = new StubNewRelicHandler(Logger::DEBUG, false, 'myAppName'); + $handler->handle($this->getRecord(Logger::ERROR, 'log message', array('appname' => 'logAppName'))); + + $this->assertEquals('logAppName', self::$appname); + } + + public function testTheTransactionNameIsNullByDefault() + { + $handler = new StubNewRelicHandler(); + $handler->handle($this->getRecord(Logger::ERROR, 'log message')); + + $this->assertEquals(null, self::$transactionName); + } + + public function testTheTransactionNameCanBeInjectedFromtheConstructor() + { + $handler = new StubNewRelicHandler(Logger::DEBUG, false, null, false, 'myTransaction'); + $handler->handle($this->getRecord(Logger::ERROR, 'log message')); + + $this->assertEquals('myTransaction', self::$transactionName); + } + + public function testTheTransactionNameCanBeOverriddenFromEachLog() + { + $handler = new StubNewRelicHandler(Logger::DEBUG, false, null, false, 'myTransaction'); + $handler->handle($this->getRecord(Logger::ERROR, 'log message', array('transaction_name' => 'logTransactName'))); + + $this->assertEquals('logTransactName', self::$transactionName); + } +} + +class StubNewRelicHandlerWithoutExtension extends NewRelicHandler +{ + protected function isNewRelicEnabled() + { + return false; + } +} + +class StubNewRelicHandler extends NewRelicHandler +{ + protected function isNewRelicEnabled() + { + return true; + } +} + +function newrelic_notice_error() +{ + return true; +} + +function newrelic_set_appname($appname) +{ + return NewRelicHandlerTest::$appname = $appname; +} + +function newrelic_name_transaction($transactionName) +{ + return NewRelicHandlerTest::$transactionName = $transactionName; +} + +function newrelic_add_custom_parameter($key, $value) +{ + NewRelicHandlerTest::$customParameters[$key] = $value; + + return true; +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/NullHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/NullHandlerTest.php new file mode 100644 index 00000000..292df78c --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/NullHandlerTest.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; + +/** + * @covers Monolog\Handler\NullHandler::handle + */ +class NullHandlerTest extends TestCase +{ + public function testHandle() + { + $handler = new NullHandler(); + $this->assertTrue($handler->handle($this->getRecord())); + } + + public function testHandleLowerLevelRecord() + { + $handler = new NullHandler(Logger::WARNING); + $this->assertFalse($handler->handle($this->getRecord(Logger::DEBUG))); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/PsrHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/PsrHandlerTest.php new file mode 100644 index 00000000..64eaab16 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/PsrHandlerTest.php @@ -0,0 +1,50 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; + +/** + * @covers Monolog\Handler\PsrHandler::handle + */ +class PsrHandlerTest extends TestCase +{ + public function logLevelProvider() + { + $levels = array(); + $monologLogger = new Logger(''); + + foreach ($monologLogger->getLevels() as $levelName => $level) { + $levels[] = array($levelName, $level); + } + + return $levels; + } + + /** + * @dataProvider logLevelProvider + */ + public function testHandlesAllLevels($levelName, $level) + { + $message = 'Hello, world! ' . $level; + $context = array('foo' => 'bar', 'level' => $level); + + $psrLogger = $this->getMock('Psr\Log\NullLogger'); + $psrLogger->expects($this->once()) + ->method('log') + ->with(strtolower($levelName), $message, $context); + + $handler = new PsrHandler($psrLogger); + $handler->handle(array('level' => $level, 'level_name' => $levelName, 'message' => $message, 'context' => $context)); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/PushoverHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/PushoverHandlerTest.php new file mode 100644 index 00000000..89408236 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/PushoverHandlerTest.php @@ -0,0 +1,141 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; + +/** + * Almost all examples (expected header, titles, messages) taken from + * https://www.pushover.net/api + * @author Sebastian Göttschkes <sebastian.goettschkes@googlemail.com> + * @see https://www.pushover.net/api + */ +class PushoverHandlerTest extends TestCase +{ + private $res; + private $handler; + + public function testWriteHeader() + { + $this->createHandler(); + $this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/POST \/1\/messages.json HTTP\/1.1\\r\\nHost: api.pushover.net\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content); + + return $content; + } + + /** + * @depends testWriteHeader + */ + public function testWriteContent($content) + { + $this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog×tamp=\d{10}$/', $content); + } + + public function testWriteWithComplexTitle() + { + $this->createHandler('myToken', 'myUser', 'Backup finished - SQL1', Logger::EMERGENCY); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/title=Backup\+finished\+-\+SQL1/', $content); + } + + public function testWriteWithComplexMessage() + { + $this->createHandler(); + $this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'Backup of database "example" finished in 16 minutes.')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/message=Backup\+of\+database\+%22example%22\+finished\+in\+16\+minutes\./', $content); + } + + public function testWriteWithTooLongMessage() + { + $message = str_pad('test', 520, 'a'); + $this->createHandler(); + $this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications + $this->handler->handle($this->getRecord(Logger::CRITICAL, $message)); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $expectedMessage = substr($message, 0, 505); + + $this->assertRegexp('/message=' . $expectedMessage . '&title/', $content); + } + + public function testWriteWithHighPriority() + { + $this->createHandler(); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog×tamp=\d{10}&priority=1$/', $content); + } + + public function testWriteWithEmergencyPriority() + { + $this->createHandler(); + $this->handler->handle($this->getRecord(Logger::EMERGENCY, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog×tamp=\d{10}&priority=2&retry=30&expire=25200$/', $content); + } + + public function testWriteToMultipleUsers() + { + $this->createHandler('myToken', array('userA', 'userB')); + $this->handler->handle($this->getRecord(Logger::EMERGENCY, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/token=myToken&user=userA&message=test1&title=Monolog×tamp=\d{10}&priority=2&retry=30&expire=25200POST/', $content); + $this->assertRegexp('/token=myToken&user=userB&message=test1&title=Monolog×tamp=\d{10}&priority=2&retry=30&expire=25200$/', $content); + } + + private function createHandler($token = 'myToken', $user = 'myUser', $title = 'Monolog') + { + $constructorArgs = array($token, $user, $title); + $this->res = fopen('php://memory', 'a'); + $this->handler = $this->getMock( + '\Monolog\Handler\PushoverHandler', + array('fsockopen', 'streamSetTimeout', 'closeSocket'), + $constructorArgs + ); + + $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($this->handler, 'localhost:1234'); + + $this->handler->expects($this->any()) + ->method('fsockopen') + ->will($this->returnValue($this->res)); + $this->handler->expects($this->any()) + ->method('streamSetTimeout') + ->will($this->returnValue(true)); + $this->handler->expects($this->any()) + ->method('closeSocket') + ->will($this->returnValue(true)); + + $this->handler->setFormatter($this->getIdentityFormatter()); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/RavenHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/RavenHandlerTest.php new file mode 100644 index 00000000..8fe86961 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/RavenHandlerTest.php @@ -0,0 +1,150 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; +use Monolog\Formatter\LineFormatter; + +class RavenHandlerTest extends TestCase +{ + public function setUp() + { + if (!class_exists("Raven_Client")) { + $this->markTestSkipped("raven/raven not installed"); + } + + require_once __DIR__ . '/MockRavenClient.php'; + } + + /** + * @covers Monolog\Handler\RavenHandler::__construct + */ + public function testConstruct() + { + $handler = new RavenHandler($this->getRavenClient()); + $this->assertInstanceOf('Monolog\Handler\RavenHandler', $handler); + } + + protected function getHandler($ravenClient) + { + $handler = new RavenHandler($ravenClient); + + return $handler; + } + + protected function getRavenClient() + { + $dsn = 'http://43f6017361224d098402974103bfc53d:a6a0538fc2934ba2bed32e08741b2cd3@marca.python.live.cheggnet.com:9000/1'; + + return new MockRavenClient($dsn); + } + + public function testDebug() + { + $ravenClient = $this->getRavenClient(); + $handler = $this->getHandler($ravenClient); + + $record = $this->getRecord(Logger::DEBUG, "A test debug message"); + $handler->handle($record); + + $this->assertEquals($ravenClient::DEBUG, $ravenClient->lastData['level']); + $this->assertContains($record['message'], $ravenClient->lastData['message']); + } + + public function testWarning() + { + $ravenClient = $this->getRavenClient(); + $handler = $this->getHandler($ravenClient); + + $record = $this->getRecord(Logger::WARNING, "A test warning message"); + $handler->handle($record); + + $this->assertEquals($ravenClient::WARNING, $ravenClient->lastData['level']); + $this->assertContains($record['message'], $ravenClient->lastData['message']); + } + + public function testTag() + { + $ravenClient = $this->getRavenClient(); + $handler = $this->getHandler($ravenClient); + + $tags = array(1, 2, 'foo'); + $record = $this->getRecord(Logger::INFO, "test", array('tags' => $tags)); + $handler->handle($record); + + $this->assertEquals($tags, $ravenClient->lastData['tags']); + } + + public function testException() + { + $ravenClient = $this->getRavenClient(); + $handler = $this->getHandler($ravenClient); + + try { + $this->methodThatThrowsAnException(); + } catch (\Exception $e) { + $record = $this->getRecord(Logger::ERROR, $e->getMessage(), array('exception' => $e)); + $handler->handle($record); + } + + $this->assertEquals($record['message'], $ravenClient->lastData['message']); + } + + public function testHandleBatch() + { + $records = $this->getMultipleRecords(); + $records[] = $this->getRecord(Logger::WARNING, 'warning'); + $records[] = $this->getRecord(Logger::WARNING, 'warning'); + + $logFormatter = $this->getMock('Monolog\\Formatter\\FormatterInterface'); + $logFormatter->expects($this->once())->method('formatBatch'); + + $formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface'); + $formatter->expects($this->once())->method('format')->with($this->callback(function ($record) { + return $record['level'] == 400; + })); + + $handler = $this->getHandler($this->getRavenClient()); + $handler->setBatchFormatter($logFormatter); + $handler->setFormatter($formatter); + $handler->handleBatch($records); + } + + public function testHandleBatchDoNothingIfRecordsAreBelowLevel() + { + $records = array( + $this->getRecord(Logger::DEBUG, 'debug message 1'), + $this->getRecord(Logger::DEBUG, 'debug message 2'), + $this->getRecord(Logger::INFO, 'information'), + ); + + $handler = $this->getMock('Monolog\Handler\RavenHandler', null, array($this->getRavenClient())); + $handler->expects($this->never())->method('handle'); + $handler->setLevel(Logger::ERROR); + $handler->handleBatch($records); + } + + public function testGetSetBatchFormatter() + { + $ravenClient = $this->getRavenClient(); + $handler = $this->getHandler($ravenClient); + + $handler->setBatchFormatter($formatter = new LineFormatter()); + $this->assertSame($formatter, $handler->getBatchFormatter()); + } + + private function methodThatThrowsAnException() + { + throw new \Exception('This is an exception'); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/RedisHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/RedisHandlerTest.php new file mode 100644 index 00000000..3629f8a2 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/RedisHandlerTest.php @@ -0,0 +1,71 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; +use Monolog\Formatter\LineFormatter; + +class RedisHandlerTest extends TestCase +{ + /** + * @expectedException InvalidArgumentException + */ + public function testConstructorShouldThrowExceptionForInvalidRedis() + { + new RedisHandler(new \stdClass(), 'key'); + } + + public function testConstructorShouldWorkWithPredis() + { + $redis = $this->getMock('Predis\Client'); + $this->assertInstanceof('Monolog\Handler\RedisHandler', new RedisHandler($redis, 'key')); + } + + public function testConstructorShouldWorkWithRedis() + { + $redis = $this->getMock('Redis'); + $this->assertInstanceof('Monolog\Handler\RedisHandler', new RedisHandler($redis, 'key')); + } + + public function testPredisHandle() + { + $redis = $this->getMock('Predis\Client', array('rpush')); + + // Predis\Client uses rpush + $redis->expects($this->once()) + ->method('rpush') + ->with('key', 'test'); + + $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); + + $handler = new RedisHandler($redis, 'key'); + $handler->setFormatter(new LineFormatter("%message%")); + $handler->handle($record); + } + + public function testRedisHandle() + { + $redis = $this->getMock('Redis', array('rpush')); + + // Redis uses rPush + $redis->expects($this->once()) + ->method('rPush') + ->with('key', 'test'); + + $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); + + $handler = new RedisHandler($redis, 'key'); + $handler->setFormatter(new LineFormatter("%message%")); + $handler->handle($record); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/RotatingFileHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/RotatingFileHandlerTest.php new file mode 100644 index 00000000..f4cefda1 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/RotatingFileHandlerTest.php @@ -0,0 +1,99 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; + +/** + * @covers Monolog\Handler\RotatingFileHandler + */ +class RotatingFileHandlerTest extends TestCase +{ + public function setUp() + { + $dir = __DIR__.'/Fixtures'; + chmod($dir, 0777); + if (!is_writable($dir)) { + $this->markTestSkipped($dir.' must be writeable to test the RotatingFileHandler.'); + } + } + + public function testRotationCreatesNewFile() + { + touch(__DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400).'.rot'); + + $handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot'); + $handler->setFormatter($this->getIdentityFormatter()); + $handler->handle($this->getRecord()); + + $log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot'; + $this->assertTrue(file_exists($log)); + $this->assertEquals('test', file_get_contents($log)); + } + + /** + * @dataProvider rotationTests + */ + public function testRotation($createFile) + { + touch($old1 = __DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400).'.rot'); + touch($old2 = __DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400 * 2).'.rot'); + touch($old3 = __DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400 * 3).'.rot'); + touch($old4 = __DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400 * 4).'.rot'); + + $log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot'; + + if ($createFile) { + touch($log); + } + + $handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot', 2); + $handler->setFormatter($this->getIdentityFormatter()); + $handler->handle($this->getRecord()); + + $handler->close(); + + $this->assertTrue(file_exists($log)); + $this->assertTrue(file_exists($old1)); + $this->assertEquals($createFile, file_exists($old2)); + $this->assertEquals($createFile, file_exists($old3)); + $this->assertEquals($createFile, file_exists($old4)); + $this->assertEquals('test', file_get_contents($log)); + } + + public function rotationTests() + { + return array( + 'Rotation is triggered when the file of the current day is not present' + => array(true), + 'Rotation is not triggered when the file is already present' + => array(false), + ); + } + + public function testReuseCurrentFile() + { + $log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot'; + file_put_contents($log, "foo"); + $handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot'); + $handler->setFormatter($this->getIdentityFormatter()); + $handler->handle($this->getRecord()); + $this->assertEquals('footest', file_get_contents($log)); + } + + public function tearDown() + { + foreach (glob(__DIR__.'/Fixtures/*.rot') as $file) { + unlink($file); + } + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/SamplingHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/SamplingHandlerTest.php new file mode 100644 index 00000000..b354cee1 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/SamplingHandlerTest.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; + +/** + * @covers Monolog\Handler\SamplingHandler::handle + */ +class SamplingHandlerTest extends TestCase +{ + public function testHandle() + { + $testHandler = new TestHandler(); + $handler = new SamplingHandler($testHandler, 2); + for ($i = 0; $i < 10000; $i++) { + $handler->handle($this->getRecord()); + } + $count = count($testHandler->getRecords()); + // $count should be half of 10k, so between 4k and 6k + $this->assertLessThan(6000, $count); + $this->assertGreaterThan(4000, $count); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/SlackHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/SlackHandlerTest.php new file mode 100644 index 00000000..d657fae3 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/SlackHandlerTest.php @@ -0,0 +1,133 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; + +/** + * @author Greg Kedzierski <greg@gregkedzierski.com> + * @see https://api.slack.com/ + */ +class SlackHandlerTest extends TestCase +{ + /** + * @var resource + */ + private $res; + + /** + * @var SlackHandler + */ + private $handler; + + public function setUp() + { + if (!extension_loaded('openssl')) { + $this->markTestSkipped('This test requires openssl to run'); + } + } + + public function testWriteHeader() + { + $this->createHandler(); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/POST \/api\/chat.postMessage HTTP\/1.1\\r\\nHost: slack.com\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content); + } + + public function testWriteContent() + { + $this->createHandler(); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/token=myToken&channel=channel1&username=Monolog&text=&attachments=.*$/', $content); + } + + public function testWriteContentWithEmoji() + { + $this->createHandler('myToken', 'channel1', 'Monolog', true, 'alien'); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/icon_emoji=%3Aalien%3A$/', $content); + } + + /** + * @dataProvider provideLevelColors + */ + public function testWriteContentWithColors($level, $expectedColor) + { + $this->createHandler(); + $this->handler->handle($this->getRecord($level, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/color%22%3A%22'.$expectedColor.'/', $content); + } + + public function testWriteContentWithPlainTextMessage() + { + $this->createHandler('myToken', 'channel1', 'Monolog', false); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/text=test1/', $content); + } + + public function provideLevelColors() + { + return array( + array(Logger::DEBUG, '%23e3e4e6'), // escaped #e3e4e6 + array(Logger::INFO, 'good'), + array(Logger::NOTICE, 'good'), + array(Logger::WARNING, 'warning'), + array(Logger::ERROR, 'danger'), + array(Logger::CRITICAL, 'danger'), + array(Logger::ALERT, 'danger'), + array(Logger::EMERGENCY,'danger'), + ); + } + + private function createHandler($token = 'myToken', $channel = 'channel1', $username = 'Monolog', $useAttachment = true, $iconEmoji = null, $useShortAttachment = false, $includeExtra = false) + { + $constructorArgs = array($token, $channel, $username, $useAttachment, $iconEmoji, Logger::DEBUG, true, $useShortAttachment, $includeExtra); + $this->res = fopen('php://memory', 'a'); + $this->handler = $this->getMock( + '\Monolog\Handler\SlackHandler', + array('fsockopen', 'streamSetTimeout', 'closeSocket'), + $constructorArgs + ); + + $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($this->handler, 'localhost:1234'); + + $this->handler->expects($this->any()) + ->method('fsockopen') + ->will($this->returnValue($this->res)); + $this->handler->expects($this->any()) + ->method('streamSetTimeout') + ->will($this->returnValue(true)); + $this->handler->expects($this->any()) + ->method('closeSocket') + ->will($this->returnValue(true)); + + $this->handler->setFormatter($this->getIdentityFormatter()); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/SocketHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/SocketHandlerTest.php new file mode 100644 index 00000000..2e3d504a --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/SocketHandlerTest.php @@ -0,0 +1,282 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; + +/** + * @author Pablo de Leon Belloc <pablolb@gmail.com> + */ +class SocketHandlerTest extends TestCase +{ + /** + * @var Monolog\Handler\SocketHandler + */ + private $handler; + + /** + * @var resource + */ + private $res; + + /** + * @expectedException UnexpectedValueException + */ + public function testInvalidHostname() + { + $this->createHandler('garbage://here'); + $this->writeRecord('data'); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testBadConnectionTimeout() + { + $this->createHandler('localhost:1234'); + $this->handler->setConnectionTimeout(-1); + } + + public function testSetConnectionTimeout() + { + $this->createHandler('localhost:1234'); + $this->handler->setConnectionTimeout(10.1); + $this->assertEquals(10.1, $this->handler->getConnectionTimeout()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testBadTimeout() + { + $this->createHandler('localhost:1234'); + $this->handler->setTimeout(-1); + } + + public function testSetTimeout() + { + $this->createHandler('localhost:1234'); + $this->handler->setTimeout(10.25); + $this->assertEquals(10.25, $this->handler->getTimeout()); + } + + public function testSetConnectionString() + { + $this->createHandler('tcp://localhost:9090'); + $this->assertEquals('tcp://localhost:9090', $this->handler->getConnectionString()); + } + + /** + * @expectedException UnexpectedValueException + */ + public function testExceptionIsThrownOnFsockopenError() + { + $this->setMockHandler(array('fsockopen')); + $this->handler->expects($this->once()) + ->method('fsockopen') + ->will($this->returnValue(false)); + $this->writeRecord('Hello world'); + } + + /** + * @expectedException UnexpectedValueException + */ + public function testExceptionIsThrownOnPfsockopenError() + { + $this->setMockHandler(array('pfsockopen')); + $this->handler->expects($this->once()) + ->method('pfsockopen') + ->will($this->returnValue(false)); + $this->handler->setPersistent(true); + $this->writeRecord('Hello world'); + } + + /** + * @expectedException UnexpectedValueException + */ + public function testExceptionIsThrownIfCannotSetTimeout() + { + $this->setMockHandler(array('streamSetTimeout')); + $this->handler->expects($this->once()) + ->method('streamSetTimeout') + ->will($this->returnValue(false)); + $this->writeRecord('Hello world'); + } + + /** + * @expectedException RuntimeException + */ + public function testWriteFailsOnIfFwriteReturnsFalse() + { + $this->setMockHandler(array('fwrite')); + + $callback = function ($arg) { + $map = array( + 'Hello world' => 6, + 'world' => false, + ); + + return $map[$arg]; + }; + + $this->handler->expects($this->exactly(2)) + ->method('fwrite') + ->will($this->returnCallback($callback)); + + $this->writeRecord('Hello world'); + } + + /** + * @expectedException RuntimeException + */ + public function testWriteFailsIfStreamTimesOut() + { + $this->setMockHandler(array('fwrite', 'streamGetMetadata')); + + $callback = function ($arg) { + $map = array( + 'Hello world' => 6, + 'world' => 5, + ); + + return $map[$arg]; + }; + + $this->handler->expects($this->exactly(1)) + ->method('fwrite') + ->will($this->returnCallback($callback)); + $this->handler->expects($this->exactly(1)) + ->method('streamGetMetadata') + ->will($this->returnValue(array('timed_out' => true))); + + $this->writeRecord('Hello world'); + } + + /** + * @expectedException RuntimeException + */ + public function testWriteFailsOnIncompleteWrite() + { + $this->setMockHandler(array('fwrite', 'streamGetMetadata')); + + $res = $this->res; + $callback = function ($string) use ($res) { + fclose($res); + + return strlen('Hello'); + }; + + $this->handler->expects($this->exactly(1)) + ->method('fwrite') + ->will($this->returnCallback($callback)); + $this->handler->expects($this->exactly(1)) + ->method('streamGetMetadata') + ->will($this->returnValue(array('timed_out' => false))); + + $this->writeRecord('Hello world'); + } + + public function testWriteWithMemoryFile() + { + $this->setMockHandler(); + $this->writeRecord('test1'); + $this->writeRecord('test2'); + $this->writeRecord('test3'); + fseek($this->res, 0); + $this->assertEquals('test1test2test3', fread($this->res, 1024)); + } + + public function testWriteWithMock() + { + $this->setMockHandler(array('fwrite')); + + $callback = function ($arg) { + $map = array( + 'Hello world' => 6, + 'world' => 5, + ); + + return $map[$arg]; + }; + + $this->handler->expects($this->exactly(2)) + ->method('fwrite') + ->will($this->returnCallback($callback)); + + $this->writeRecord('Hello world'); + } + + public function testClose() + { + $this->setMockHandler(); + $this->writeRecord('Hello world'); + $this->assertInternalType('resource', $this->res); + $this->handler->close(); + $this->assertFalse(is_resource($this->res), "Expected resource to be closed after closing handler"); + } + + public function testCloseDoesNotClosePersistentSocket() + { + $this->setMockHandler(); + $this->handler->setPersistent(true); + $this->writeRecord('Hello world'); + $this->assertTrue(is_resource($this->res)); + $this->handler->close(); + $this->assertTrue(is_resource($this->res)); + } + + private function createHandler($connectionString) + { + $this->handler = new SocketHandler($connectionString); + $this->handler->setFormatter($this->getIdentityFormatter()); + } + + private function writeRecord($string) + { + $this->handler->handle($this->getRecord(Logger::WARNING, $string)); + } + + private function setMockHandler(array $methods = array()) + { + $this->res = fopen('php://memory', 'a'); + + $defaultMethods = array('fsockopen', 'pfsockopen', 'streamSetTimeout'); + $newMethods = array_diff($methods, $defaultMethods); + + $finalMethods = array_merge($defaultMethods, $newMethods); + + $this->handler = $this->getMock( + '\Monolog\Handler\SocketHandler', $finalMethods, array('localhost:1234') + ); + + if (!in_array('fsockopen', $methods)) { + $this->handler->expects($this->any()) + ->method('fsockopen') + ->will($this->returnValue($this->res)); + } + + if (!in_array('pfsockopen', $methods)) { + $this->handler->expects($this->any()) + ->method('pfsockopen') + ->will($this->returnValue($this->res)); + } + + if (!in_array('streamSetTimeout', $methods)) { + $this->handler->expects($this->any()) + ->method('streamSetTimeout') + ->will($this->returnValue(true)); + } + + $this->handler->setFormatter($this->getIdentityFormatter()); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/StreamHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/StreamHandlerTest.php new file mode 100644 index 00000000..44d3d9f1 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/StreamHandlerTest.php @@ -0,0 +1,118 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; + +class StreamHandlerTest extends TestCase +{ + /** + * @covers Monolog\Handler\StreamHandler::__construct + * @covers Monolog\Handler\StreamHandler::write + */ + public function testWrite() + { + $handle = fopen('php://memory', 'a+'); + $handler = new StreamHandler($handle); + $handler->setFormatter($this->getIdentityFormatter()); + $handler->handle($this->getRecord(Logger::WARNING, 'test')); + $handler->handle($this->getRecord(Logger::WARNING, 'test2')); + $handler->handle($this->getRecord(Logger::WARNING, 'test3')); + fseek($handle, 0); + $this->assertEquals('testtest2test3', fread($handle, 100)); + } + + /** + * @covers Monolog\Handler\StreamHandler::close + */ + public function testClose() + { + $handle = fopen('php://memory', 'a+'); + $handler = new StreamHandler($handle); + $this->assertTrue(is_resource($handle)); + $handler->close(); + $this->assertFalse(is_resource($handle)); + } + + /** + * @covers Monolog\Handler\StreamHandler::write + */ + public function testWriteCreatesTheStreamResource() + { + $handler = new StreamHandler('php://memory'); + $handler->handle($this->getRecord()); + } + + /** + * @covers Monolog\Handler\StreamHandler::__construct + * @covers Monolog\Handler\StreamHandler::write + */ + public function testWriteLocking() + { + $temp = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'monolog_locked_log'; + $handler = new StreamHandler($temp, Logger::DEBUG, true, null, true); + $handler->handle($this->getRecord()); + } + + /** + * @expectedException LogicException + * @covers Monolog\Handler\StreamHandler::__construct + * @covers Monolog\Handler\StreamHandler::write + */ + public function testWriteMissingResource() + { + $handler = new StreamHandler(null); + $handler->handle($this->getRecord()); + } + + public function invalidArgumentProvider() + { + return array( + array(1), + array(array()), + array(array('bogus://url')), + ); + } + + /** + * @dataProvider invalidArgumentProvider + * @expectedException InvalidArgumentException + * @covers Monolog\Handler\StreamHandler::__construct + */ + public function testWriteInvalidArgument($invalidArgument) + { + $handler = new StreamHandler($invalidArgument); + } + + /** + * @expectedException UnexpectedValueException + * @covers Monolog\Handler\StreamHandler::__construct + * @covers Monolog\Handler\StreamHandler::write + */ + public function testWriteInvalidResource() + { + $handler = new StreamHandler('bogus://url'); + $handler->handle($this->getRecord()); + } + + /** + * @expectedException UnexpectedValueException + * @covers Monolog\Handler\StreamHandler::__construct + * @covers Monolog\Handler\StreamHandler::write + */ + public function testWriteNonExistingResource() + { + $handler = new StreamHandler('/foo/bar/baz/'.rand(0, 10000)); + $handler->handle($this->getRecord()); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/SyslogHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/SyslogHandlerTest.php new file mode 100644 index 00000000..8f9e46bf --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/SyslogHandlerTest.php @@ -0,0 +1,44 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; + +class SyslogHandlerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Monolog\Handler\SyslogHandler::__construct + */ + public function testConstruct() + { + $handler = new SyslogHandler('test'); + $this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler); + + $handler = new SyslogHandler('test', LOG_USER); + $this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler); + + $handler = new SyslogHandler('test', 'user'); + $this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler); + + $handler = new SyslogHandler('test', LOG_USER, Logger::DEBUG, true, LOG_PERROR); + $this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler); + } + + /** + * @covers Monolog\Handler\SyslogHandler::__construct + */ + public function testConstructInvalidFacility() + { + $this->setExpectedException('UnexpectedValueException'); + $handler = new SyslogHandler('test', 'unknown'); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/SyslogUdpHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/SyslogUdpHandlerTest.php new file mode 100644 index 00000000..497812b3 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/SyslogUdpHandlerTest.php @@ -0,0 +1,49 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +/** + * @requires extension sockets + */ +class SyslogUdpHandlerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @expectedException UnexpectedValueException + */ + public function testWeValidateFacilities() + { + $handler = new SyslogUdpHandler("ip", null, "invalidFacility"); + } + + public function testWeSplitIntoLines() + { + $handler = new SyslogUdpHandler("127.0.0.1", 514, "authpriv"); + $handler->setFormatter(new \Monolog\Formatter\ChromePHPFormatter()); + + $socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', array('write'), array('lol', 'lol')); + $socket->expects($this->at(0)) + ->method('write') + ->with("lol", "<".(LOG_AUTHPRIV + LOG_WARNING).">1 "); + $socket->expects($this->at(1)) + ->method('write') + ->with("hej", "<".(LOG_AUTHPRIV + LOG_WARNING).">1 "); + + $handler->setSocket($socket); + + $handler->handle($this->getRecordWithMessage("hej\nlol")); + } + + protected function getRecordWithMessage($msg) + { + return array('message' => $msg, 'level' => \Monolog\Logger::WARNING, 'context' => null, 'extra' => array(), 'channel' => 'lol'); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/TestHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/TestHandlerTest.php new file mode 100644 index 00000000..801d80a9 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/TestHandlerTest.php @@ -0,0 +1,56 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; + +/** + * @covers Monolog\Handler\TestHandler + */ +class TestHandlerTest extends TestCase +{ + /** + * @dataProvider methodProvider + */ + public function testHandler($method, $level) + { + $handler = new TestHandler; + $record = $this->getRecord($level, 'test'.$method); + $this->assertFalse($handler->{'has'.$method}($record)); + $this->assertFalse($handler->{'has'.$method.'Records'}()); + $handler->handle($record); + + $this->assertFalse($handler->{'has'.$method}('bar')); + $this->assertTrue($handler->{'has'.$method}($record)); + $this->assertTrue($handler->{'has'.$method}('test'.$method)); + $this->assertTrue($handler->{'has'.$method.'Records'}()); + + $records = $handler->getRecords(); + unset($records[0]['formatted']); + $this->assertEquals(array($record), $records); + } + + public function methodProvider() + { + return array( + array('Emergency', Logger::EMERGENCY), + array('Alert' , Logger::ALERT), + array('Critical' , Logger::CRITICAL), + array('Error' , Logger::ERROR), + array('Warning' , Logger::WARNING), + array('Info' , Logger::INFO), + array('Notice' , Logger::NOTICE), + array('Debug' , Logger::DEBUG), + ); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/UdpSocketTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/UdpSocketTest.php new file mode 100644 index 00000000..bcaf52b3 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/UdpSocketTest.php @@ -0,0 +1,46 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; + +/** + * @requires extension sockets + */ +class UdpSocketTest extends TestCase +{ + public function testWeDoNotTruncateShortMessages() + { + $socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', array('send'), array('lol', 'lol')); + + $socket->expects($this->at(0)) + ->method('send') + ->with("HEADER: The quick brown fox jumps over the lazy dog"); + + $socket->write("The quick brown fox jumps over the lazy dog", "HEADER: "); + } + + public function testLongMessagesAreTruncated() + { + $socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', array('send'), array('lol', 'lol')); + + $truncatedString = str_repeat("derp", 16254).'d'; + + $socket->expects($this->exactly(1)) + ->method('send') + ->with("HEADER" . $truncatedString); + + $longString = str_repeat("derp", 20000); + + $socket->write($longString, "HEADER"); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/WhatFailureGroupHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/WhatFailureGroupHandlerTest.php new file mode 100644 index 00000000..8d37a1fc --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/WhatFailureGroupHandlerTest.php @@ -0,0 +1,121 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; + +class WhatFailureGroupHandlerTest extends TestCase +{ + /** + * @covers Monolog\Handler\WhatFailureGroupHandler::__construct + * @expectedException InvalidArgumentException + */ + public function testConstructorOnlyTakesHandler() + { + new WhatFailureGroupHandler(array(new TestHandler(), "foo")); + } + + /** + * @covers Monolog\Handler\WhatFailureGroupHandler::__construct + * @covers Monolog\Handler\WhatFailureGroupHandler::handle + */ + public function testHandle() + { + $testHandlers = array(new TestHandler(), new TestHandler()); + $handler = new WhatFailureGroupHandler($testHandlers); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + foreach ($testHandlers as $test) { + $this->assertTrue($test->hasDebugRecords()); + $this->assertTrue($test->hasInfoRecords()); + $this->assertTrue(count($test->getRecords()) === 2); + } + } + + /** + * @covers Monolog\Handler\WhatFailureGroupHandler::handleBatch + */ + public function testHandleBatch() + { + $testHandlers = array(new TestHandler(), new TestHandler()); + $handler = new WhatFailureGroupHandler($testHandlers); + $handler->handleBatch(array($this->getRecord(Logger::DEBUG), $this->getRecord(Logger::INFO))); + foreach ($testHandlers as $test) { + $this->assertTrue($test->hasDebugRecords()); + $this->assertTrue($test->hasInfoRecords()); + $this->assertTrue(count($test->getRecords()) === 2); + } + } + + /** + * @covers Monolog\Handler\WhatFailureGroupHandler::isHandling + */ + public function testIsHandling() + { + $testHandlers = array(new TestHandler(Logger::ERROR), new TestHandler(Logger::WARNING)); + $handler = new WhatFailureGroupHandler($testHandlers); + $this->assertTrue($handler->isHandling($this->getRecord(Logger::ERROR))); + $this->assertTrue($handler->isHandling($this->getRecord(Logger::WARNING))); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG))); + } + + /** + * @covers Monolog\Handler\WhatFailureGroupHandler::handle + */ + public function testHandleUsesProcessors() + { + $test = new TestHandler(); + $handler = new WhatFailureGroupHandler(array($test)); + $handler->pushProcessor(function ($record) { + $record['extra']['foo'] = true; + + return $record; + }); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertTrue($test->hasWarningRecords()); + $records = $test->getRecords(); + $this->assertTrue($records[0]['extra']['foo']); + } + + /** + * @covers Monolog\Handler\WhatFailureGroupHandler::handle + */ + public function testHandleException() + { + $test = new TestHandler(); + $exception = new ExceptionTestHandler(); + $handler = new WhatFailureGroupHandler(array($exception, $test, $exception)); + $handler->pushProcessor(function ($record) { + $record['extra']['foo'] = true; + + return $record; + }); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertTrue($test->hasWarningRecords()); + $records = $test->getRecords(); + $this->assertTrue($records[0]['extra']['foo']); + } +} + +class ExceptionTestHandler extends TestHandler +{ + /** + * {@inheritdoc} + */ + public function handle(array $record) + { + parent::handle($record); + + throw new \Exception("ExceptionTestHandler::handle"); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/ZendMonitorHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/ZendMonitorHandlerTest.php new file mode 100644 index 00000000..416039e6 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/ZendMonitorHandlerTest.php @@ -0,0 +1,69 @@ +<?php +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; + +class ZendMonitorHandlerTest extends TestCase +{ + protected $zendMonitorHandler; + + public function setUp() + { + if (!function_exists('zend_monitor_custom_event')) { + $this->markTestSkipped('ZendServer is not installed'); + } + } + + /** + * @covers Monolog\Handler\ZendMonitorHandler::write + */ + public function testWrite() + { + $record = $this->getRecord(); + $formatterResult = array( + 'message' => $record['message'] + ); + + $zendMonitor = $this->getMockBuilder('Monolog\Handler\ZendMonitorHandler') + ->setMethods(array('writeZendMonitorCustomEvent', 'getDefaultFormatter')) + ->getMock(); + + $formatterMock = $this->getMockBuilder('Monolog\Formatter\NormalizerFormatter') + ->disableOriginalConstructor() + ->getMock(); + + $formatterMock->expects($this->once()) + ->method('format') + ->will($this->returnValue($formatterResult)); + + $zendMonitor->expects($this->once()) + ->method('getDefaultFormatter') + ->will($this->returnValue($formatterMock)); + + $levelMap = $zendMonitor->getLevelMap(); + + $zendMonitor->expects($this->once()) + ->method('writeZendMonitorCustomEvent') + ->with($levelMap[$record['level']], $record['message'], $formatterResult); + + $zendMonitor->handle($record); + } + + /** + * @covers Monolog\Handler\ZendMonitorHandler::getDefaultFormatter + */ + public function testGetDefaultFormatterReturnsNormalizerFormatter() + { + $zendMonitor = new ZendMonitorHandler(); + $this->assertInstanceOf('Monolog\Formatter\NormalizerFormatter', $zendMonitor->getDefaultFormatter()); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/LoggerTest.php b/vendor/monolog/monolog/tests/Monolog/LoggerTest.php new file mode 100644 index 00000000..7a19c0b4 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/LoggerTest.php @@ -0,0 +1,409 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog; + +use Monolog\Processor\WebProcessor; +use Monolog\Handler\TestHandler; + +class LoggerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Monolog\Logger::getName + */ + public function testGetName() + { + $logger = new Logger('foo'); + $this->assertEquals('foo', $logger->getName()); + } + + /** + * @covers Monolog\Logger::getLevelName + */ + public function testGetLevelName() + { + $this->assertEquals('ERROR', Logger::getLevelName(Logger::ERROR)); + } + + /** + * @covers Monolog\Logger::getLevelName + * @expectedException InvalidArgumentException + */ + public function testGetLevelNameThrows() + { + Logger::getLevelName(5); + } + + /** + * @covers Monolog\Logger::__construct + */ + public function testChannel() + { + $logger = new Logger('foo'); + $handler = new TestHandler; + $logger->pushHandler($handler); + $logger->addWarning('test'); + list($record) = $handler->getRecords(); + $this->assertEquals('foo', $record['channel']); + } + + /** + * @covers Monolog\Logger::addRecord + */ + public function testLog() + { + $logger = new Logger(__METHOD__); + + $handler = $this->getMock('Monolog\Handler\NullHandler', array('handle')); + $handler->expects($this->once()) + ->method('handle'); + $logger->pushHandler($handler); + + $this->assertTrue($logger->addWarning('test')); + } + + /** + * @covers Monolog\Logger::addRecord + */ + public function testLogNotHandled() + { + $logger = new Logger(__METHOD__); + + $handler = $this->getMock('Monolog\Handler\NullHandler', array('handle'), array(Logger::ERROR)); + $handler->expects($this->never()) + ->method('handle'); + $logger->pushHandler($handler); + + $this->assertFalse($logger->addWarning('test')); + } + + public function testHandlersInCtor() + { + $handler1 = new TestHandler; + $handler2 = new TestHandler; + $logger = new Logger(__METHOD__, array($handler1, $handler2)); + + $this->assertEquals($handler1, $logger->popHandler()); + $this->assertEquals($handler2, $logger->popHandler()); + } + + public function testProcessorsInCtor() + { + $processor1 = new WebProcessor; + $processor2 = new WebProcessor; + $logger = new Logger(__METHOD__, array(), array($processor1, $processor2)); + + $this->assertEquals($processor1, $logger->popProcessor()); + $this->assertEquals($processor2, $logger->popProcessor()); + } + + /** + * @covers Monolog\Logger::pushHandler + * @covers Monolog\Logger::popHandler + * @expectedException LogicException + */ + public function testPushPopHandler() + { + $logger = new Logger(__METHOD__); + $handler1 = new TestHandler; + $handler2 = new TestHandler; + + $logger->pushHandler($handler1); + $logger->pushHandler($handler2); + + $this->assertEquals($handler2, $logger->popHandler()); + $this->assertEquals($handler1, $logger->popHandler()); + $logger->popHandler(); + } + + /** + * @covers Monolog\Logger::pushProcessor + * @covers Monolog\Logger::popProcessor + * @expectedException LogicException + */ + public function testPushPopProcessor() + { + $logger = new Logger(__METHOD__); + $processor1 = new WebProcessor; + $processor2 = new WebProcessor; + + $logger->pushProcessor($processor1); + $logger->pushProcessor($processor2); + + $this->assertEquals($processor2, $logger->popProcessor()); + $this->assertEquals($processor1, $logger->popProcessor()); + $logger->popProcessor(); + } + + /** + * @covers Monolog\Logger::pushProcessor + * @expectedException InvalidArgumentException + */ + public function testPushProcessorWithNonCallable() + { + $logger = new Logger(__METHOD__); + + $logger->pushProcessor(new \stdClass()); + } + + /** + * @covers Monolog\Logger::addRecord + */ + public function testProcessorsAreExecuted() + { + $logger = new Logger(__METHOD__); + $handler = new TestHandler; + $logger->pushHandler($handler); + $logger->pushProcessor(function ($record) { + $record['extra']['win'] = true; + + return $record; + }); + $logger->addError('test'); + list($record) = $handler->getRecords(); + $this->assertTrue($record['extra']['win']); + } + + /** + * @covers Monolog\Logger::addRecord + */ + public function testProcessorsAreCalledOnlyOnce() + { + $logger = new Logger(__METHOD__); + $handler = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler->expects($this->any()) + ->method('isHandling') + ->will($this->returnValue(true)) + ; + $handler->expects($this->any()) + ->method('handle') + ->will($this->returnValue(true)) + ; + $logger->pushHandler($handler); + + $processor = $this->getMockBuilder('Monolog\Processor\WebProcessor') + ->disableOriginalConstructor() + ->setMethods(array('__invoke')) + ->getMock() + ; + $processor->expects($this->once()) + ->method('__invoke') + ->will($this->returnArgument(0)) + ; + $logger->pushProcessor($processor); + + $logger->addError('test'); + } + + /** + * @covers Monolog\Logger::addRecord + */ + public function testProcessorsNotCalledWhenNotHandled() + { + $logger = new Logger(__METHOD__); + $handler = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler->expects($this->once()) + ->method('isHandling') + ->will($this->returnValue(false)) + ; + $logger->pushHandler($handler); + $that = $this; + $logger->pushProcessor(function ($record) use ($that) { + $that->fail('The processor should not be called'); + }); + $logger->addAlert('test'); + } + + /** + * @covers Monolog\Logger::addRecord + */ + public function testHandlersNotCalledBeforeFirstHandling() + { + $logger = new Logger(__METHOD__); + + $handler1 = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler1->expects($this->never()) + ->method('isHandling') + ->will($this->returnValue(false)) + ; + $handler1->expects($this->once()) + ->method('handle') + ->will($this->returnValue(false)) + ; + $logger->pushHandler($handler1); + + $handler2 = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler2->expects($this->once()) + ->method('isHandling') + ->will($this->returnValue(true)) + ; + $handler2->expects($this->once()) + ->method('handle') + ->will($this->returnValue(false)) + ; + $logger->pushHandler($handler2); + + $handler3 = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler3->expects($this->once()) + ->method('isHandling') + ->will($this->returnValue(false)) + ; + $handler3->expects($this->never()) + ->method('handle') + ; + $logger->pushHandler($handler3); + + $logger->debug('test'); + } + + /** + * @covers Monolog\Logger::addRecord + */ + public function testBubblingWhenTheHandlerReturnsFalse() + { + $logger = new Logger(__METHOD__); + + $handler1 = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler1->expects($this->any()) + ->method('isHandling') + ->will($this->returnValue(true)) + ; + $handler1->expects($this->once()) + ->method('handle') + ->will($this->returnValue(false)) + ; + $logger->pushHandler($handler1); + + $handler2 = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler2->expects($this->any()) + ->method('isHandling') + ->will($this->returnValue(true)) + ; + $handler2->expects($this->once()) + ->method('handle') + ->will($this->returnValue(false)) + ; + $logger->pushHandler($handler2); + + $logger->debug('test'); + } + + /** + * @covers Monolog\Logger::addRecord + */ + public function testNotBubblingWhenTheHandlerReturnsTrue() + { + $logger = new Logger(__METHOD__); + + $handler1 = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler1->expects($this->any()) + ->method('isHandling') + ->will($this->returnValue(true)) + ; + $handler1->expects($this->never()) + ->method('handle') + ; + $logger->pushHandler($handler1); + + $handler2 = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler2->expects($this->any()) + ->method('isHandling') + ->will($this->returnValue(true)) + ; + $handler2->expects($this->once()) + ->method('handle') + ->will($this->returnValue(true)) + ; + $logger->pushHandler($handler2); + + $logger->debug('test'); + } + + /** + * @covers Monolog\Logger::isHandling + */ + public function testIsHandling() + { + $logger = new Logger(__METHOD__); + + $handler1 = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler1->expects($this->any()) + ->method('isHandling') + ->will($this->returnValue(false)) + ; + + $logger->pushHandler($handler1); + $this->assertFalse($logger->isHandling(Logger::DEBUG)); + + $handler2 = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler2->expects($this->any()) + ->method('isHandling') + ->will($this->returnValue(true)) + ; + + $logger->pushHandler($handler2); + $this->assertTrue($logger->isHandling(Logger::DEBUG)); + } + + /** + * @dataProvider logMethodProvider + * @covers Monolog\Logger::addDebug + * @covers Monolog\Logger::addInfo + * @covers Monolog\Logger::addNotice + * @covers Monolog\Logger::addWarning + * @covers Monolog\Logger::addError + * @covers Monolog\Logger::addCritical + * @covers Monolog\Logger::addAlert + * @covers Monolog\Logger::addEmergency + * @covers Monolog\Logger::debug + * @covers Monolog\Logger::info + * @covers Monolog\Logger::notice + * @covers Monolog\Logger::warn + * @covers Monolog\Logger::err + * @covers Monolog\Logger::crit + * @covers Monolog\Logger::alert + * @covers Monolog\Logger::emerg + */ + public function testLogMethods($method, $expectedLevel) + { + $logger = new Logger('foo'); + $handler = new TestHandler; + $logger->pushHandler($handler); + $logger->{$method}('test'); + list($record) = $handler->getRecords(); + $this->assertEquals($expectedLevel, $record['level']); + } + + public function logMethodProvider() + { + return array( + // monolog methods + array('addDebug', Logger::DEBUG), + array('addInfo', Logger::INFO), + array('addNotice', Logger::NOTICE), + array('addWarning', Logger::WARNING), + array('addError', Logger::ERROR), + array('addCritical', Logger::CRITICAL), + array('addAlert', Logger::ALERT), + array('addEmergency', Logger::EMERGENCY), + + // ZF/Sf2 compat methods + array('debug', Logger::DEBUG), + array('info', Logger::INFO), + array('notice', Logger::NOTICE), + array('warn', Logger::WARNING), + array('err', Logger::ERROR), + array('crit', Logger::CRITICAL), + array('alert', Logger::ALERT), + array('emerg', Logger::EMERGENCY), + ); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Processor/GitProcessorTest.php b/vendor/monolog/monolog/tests/Monolog/Processor/GitProcessorTest.php new file mode 100644 index 00000000..5adb505d --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Processor/GitProcessorTest.php @@ -0,0 +1,29 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +use Monolog\TestCase; + +class GitProcessorTest extends TestCase +{ + /** + * @covers Monolog\Processor\GitProcessor::__invoke + */ + public function testProcessor() + { + $processor = new GitProcessor(); + $record = $processor($this->getRecord()); + + $this->assertArrayHasKey('git', $record['extra']); + $this->assertTrue(!is_array($record['extra']['git']['branch'])); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Processor/IntrospectionProcessorTest.php b/vendor/monolog/monolog/tests/Monolog/Processor/IntrospectionProcessorTest.php new file mode 100644 index 00000000..0dd411d7 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Processor/IntrospectionProcessorTest.php @@ -0,0 +1,123 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Acme; + +class Tester +{ + public function test($handler, $record) + { + $handler->handle($record); + } +} + +function tester($handler, $record) +{ + $handler->handle($record); +} + +namespace Monolog\Processor; + +use Monolog\Logger; +use Monolog\TestCase; +use Monolog\Handler\TestHandler; + +class IntrospectionProcessorTest extends TestCase +{ + public function getHandler() + { + $processor = new IntrospectionProcessor(); + $handler = new TestHandler(); + $handler->pushProcessor($processor); + + return $handler; + } + + public function testProcessorFromClass() + { + $handler = $this->getHandler(); + $tester = new \Acme\Tester; + $tester->test($handler, $this->getRecord()); + list($record) = $handler->getRecords(); + $this->assertEquals(__FILE__, $record['extra']['file']); + $this->assertEquals(18, $record['extra']['line']); + $this->assertEquals('Acme\Tester', $record['extra']['class']); + $this->assertEquals('test', $record['extra']['function']); + } + + public function testProcessorFromFunc() + { + $handler = $this->getHandler(); + \Acme\tester($handler, $this->getRecord()); + list($record) = $handler->getRecords(); + $this->assertEquals(__FILE__, $record['extra']['file']); + $this->assertEquals(24, $record['extra']['line']); + $this->assertEquals(null, $record['extra']['class']); + $this->assertEquals('Acme\tester', $record['extra']['function']); + } + + public function testLevelTooLow() + { + $input = array( + 'level' => Logger::DEBUG, + 'extra' => array(), + ); + + $expected = $input; + + $processor = new IntrospectionProcessor(Logger::CRITICAL); + $actual = $processor($input); + + $this->assertEquals($expected, $actual); + } + + public function testLevelEqual() + { + $input = array( + 'level' => Logger::CRITICAL, + 'extra' => array(), + ); + + $expected = $input; + $expected['extra'] = array( + 'file' => null, + 'line' => null, + 'class' => 'ReflectionMethod', + 'function' => 'invokeArgs', + ); + + $processor = new IntrospectionProcessor(Logger::CRITICAL); + $actual = $processor($input); + + $this->assertEquals($expected, $actual); + } + + public function testLevelHigher() + { + $input = array( + 'level' => Logger::EMERGENCY, + 'extra' => array(), + ); + + $expected = $input; + $expected['extra'] = array( + 'file' => null, + 'line' => null, + 'class' => 'ReflectionMethod', + 'function' => 'invokeArgs', + ); + + $processor = new IntrospectionProcessor(Logger::CRITICAL); + $actual = $processor($input); + + $this->assertEquals($expected, $actual); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Processor/MemoryPeakUsageProcessorTest.php b/vendor/monolog/monolog/tests/Monolog/Processor/MemoryPeakUsageProcessorTest.php new file mode 100644 index 00000000..eb666144 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Processor/MemoryPeakUsageProcessorTest.php @@ -0,0 +1,42 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +use Monolog\TestCase; + +class MemoryPeakUsageProcessorTest extends TestCase +{ + /** + * @covers Monolog\Processor\MemoryPeakUsageProcessor::__invoke + * @covers Monolog\Processor\MemoryProcessor::formatBytes + */ + public function testProcessor() + { + $processor = new MemoryPeakUsageProcessor(); + $record = $processor($this->getRecord()); + $this->assertArrayHasKey('memory_peak_usage', $record['extra']); + $this->assertRegExp('#[0-9.]+ (M|K)?B$#', $record['extra']['memory_peak_usage']); + } + + /** + * @covers Monolog\Processor\MemoryPeakUsageProcessor::__invoke + * @covers Monolog\Processor\MemoryProcessor::formatBytes + */ + public function testProcessorWithoutFormatting() + { + $processor = new MemoryPeakUsageProcessor(true, false); + $record = $processor($this->getRecord()); + $this->assertArrayHasKey('memory_peak_usage', $record['extra']); + $this->assertInternalType('int', $record['extra']['memory_peak_usage']); + $this->assertGreaterThan(0, $record['extra']['memory_peak_usage']); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Processor/MemoryUsageProcessorTest.php b/vendor/monolog/monolog/tests/Monolog/Processor/MemoryUsageProcessorTest.php new file mode 100644 index 00000000..4692dbfc --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Processor/MemoryUsageProcessorTest.php @@ -0,0 +1,42 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +use Monolog\TestCase; + +class MemoryUsageProcessorTest extends TestCase +{ + /** + * @covers Monolog\Processor\MemoryUsageProcessor::__invoke + * @covers Monolog\Processor\MemoryProcessor::formatBytes + */ + public function testProcessor() + { + $processor = new MemoryUsageProcessor(); + $record = $processor($this->getRecord()); + $this->assertArrayHasKey('memory_usage', $record['extra']); + $this->assertRegExp('#[0-9.]+ (M|K)?B$#', $record['extra']['memory_usage']); + } + + /** + * @covers Monolog\Processor\MemoryUsageProcessor::__invoke + * @covers Monolog\Processor\MemoryProcessor::formatBytes + */ + public function testProcessorWithoutFormatting() + { + $processor = new MemoryUsageProcessor(true, false); + $record = $processor($this->getRecord()); + $this->assertArrayHasKey('memory_usage', $record['extra']); + $this->assertInternalType('int', $record['extra']['memory_usage']); + $this->assertGreaterThan(0, $record['extra']['memory_usage']); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Processor/ProcessIdProcessorTest.php b/vendor/monolog/monolog/tests/Monolog/Processor/ProcessIdProcessorTest.php new file mode 100644 index 00000000..458d2a33 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Processor/ProcessIdProcessorTest.php @@ -0,0 +1,30 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +use Monolog\TestCase; + +class ProcessIdProcessorTest extends TestCase +{ + /** + * @covers Monolog\Processor\ProcessIdProcessor::__invoke + */ + public function testProcessor() + { + $processor = new ProcessIdProcessor(); + $record = $processor($this->getRecord()); + $this->assertArrayHasKey('process_id', $record['extra']); + $this->assertInternalType('int', $record['extra']['process_id']); + $this->assertGreaterThan(0, $record['extra']['process_id']); + $this->assertEquals(getmypid(), $record['extra']['process_id']); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Processor/PsrLogMessageProcessorTest.php b/vendor/monolog/monolog/tests/Monolog/Processor/PsrLogMessageProcessorTest.php new file mode 100644 index 00000000..81bfbdc3 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Processor/PsrLogMessageProcessorTest.php @@ -0,0 +1,43 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +class PsrLogMessageProcessorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @dataProvider getPairs + */ + public function testReplacement($val, $expected) + { + $proc = new PsrLogMessageProcessor; + + $message = $proc(array( + 'message' => '{foo}', + 'context' => array('foo' => $val) + )); + $this->assertEquals($expected, $message['message']); + } + + public function getPairs() + { + return array( + array('foo', 'foo'), + array('3', '3'), + array(3, '3'), + array(null, ''), + array(true, '1'), + array(false, ''), + array(new \stdClass, '[object stdClass]'), + array(array(), '[array]'), + ); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Processor/TagProcessorTest.php b/vendor/monolog/monolog/tests/Monolog/Processor/TagProcessorTest.php new file mode 100644 index 00000000..851a9dc2 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Processor/TagProcessorTest.php @@ -0,0 +1,29 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +use Monolog\TestCase; + +class TagProcessorTest extends TestCase +{ + /** + * @covers Monolog\Processor\TagProcessor::__invoke + */ + public function testProcessor() + { + $tags = array(1, 2, 3); + $processor = new TagProcessor($tags); + $record = $processor($this->getRecord()); + + $this->assertEquals($tags, $record['extra']['tags']); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Processor/UidProcessorTest.php b/vendor/monolog/monolog/tests/Monolog/Processor/UidProcessorTest.php new file mode 100644 index 00000000..7ced62ca --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Processor/UidProcessorTest.php @@ -0,0 +1,27 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +use Monolog\TestCase; + +class UidProcessorTest extends TestCase +{ + /** + * @covers Monolog\Processor\UidProcessor::__invoke + */ + public function testProcessor() + { + $processor = new UidProcessor(); + $record = $processor($this->getRecord()); + $this->assertArrayHasKey('uid', $record['extra']); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Processor/WebProcessorTest.php b/vendor/monolog/monolog/tests/Monolog/Processor/WebProcessorTest.php new file mode 100644 index 00000000..dba89412 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Processor/WebProcessorTest.php @@ -0,0 +1,98 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Processor; + +use Monolog\TestCase; + +class WebProcessorTest extends TestCase +{ + public function testProcessor() + { + $server = array( + 'REQUEST_URI' => 'A', + 'REMOTE_ADDR' => 'B', + 'REQUEST_METHOD' => 'C', + 'HTTP_REFERER' => 'D', + 'SERVER_NAME' => 'F', + 'UNIQUE_ID' => 'G', + ); + + $processor = new WebProcessor($server); + $record = $processor($this->getRecord()); + $this->assertEquals($server['REQUEST_URI'], $record['extra']['url']); + $this->assertEquals($server['REMOTE_ADDR'], $record['extra']['ip']); + $this->assertEquals($server['REQUEST_METHOD'], $record['extra']['http_method']); + $this->assertEquals($server['HTTP_REFERER'], $record['extra']['referrer']); + $this->assertEquals($server['SERVER_NAME'], $record['extra']['server']); + $this->assertEquals($server['UNIQUE_ID'], $record['extra']['unique_id']); + } + + public function testProcessorDoNothingIfNoRequestUri() + { + $server = array( + 'REMOTE_ADDR' => 'B', + 'REQUEST_METHOD' => 'C', + ); + $processor = new WebProcessor($server); + $record = $processor($this->getRecord()); + $this->assertEmpty($record['extra']); + } + + public function testProcessorReturnNullIfNoHttpReferer() + { + $server = array( + 'REQUEST_URI' => 'A', + 'REMOTE_ADDR' => 'B', + 'REQUEST_METHOD' => 'C', + 'SERVER_NAME' => 'F', + ); + $processor = new WebProcessor($server); + $record = $processor($this->getRecord()); + $this->assertNull($record['extra']['referrer']); + } + + public function testProcessorDoesNotAddUniqueIdIfNotPresent() + { + $server = array( + 'REQUEST_URI' => 'A', + 'REMOTE_ADDR' => 'B', + 'REQUEST_METHOD' => 'C', + 'SERVER_NAME' => 'F', + ); + $processor = new WebProcessor($server); + $record = $processor($this->getRecord()); + $this->assertFalse(isset($record['extra']['unique_id'])); + } + + public function testProcessorAddsOnlyRequestedExtraFields() + { + $server = array( + 'REQUEST_URI' => 'A', + 'REMOTE_ADDR' => 'B', + 'REQUEST_METHOD' => 'C', + 'SERVER_NAME' => 'F', + ); + + $processor = new WebProcessor($server, array('url', 'http_method')); + $record = $processor($this->getRecord()); + + $this->assertSame(array('url' => 'A', 'http_method' => 'C'), $record['extra']); + } + + /** + * @expectedException UnexpectedValueException + */ + public function testInvalidData() + { + new WebProcessor(new \stdClass); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/PsrLogCompatTest.php b/vendor/monolog/monolog/tests/Monolog/PsrLogCompatTest.php new file mode 100644 index 00000000..ab899449 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/PsrLogCompatTest.php @@ -0,0 +1,47 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog; + +use Monolog\Handler\TestHandler; +use Monolog\Formatter\LineFormatter; +use Monolog\Processor\PsrLogMessageProcessor; +use Psr\Log\Test\LoggerInterfaceTest; + +class PsrLogCompatTest extends LoggerInterfaceTest +{ + private $handler; + + public function getLogger() + { + $logger = new Logger('foo'); + $logger->pushHandler($handler = new TestHandler); + $logger->pushProcessor(new PsrLogMessageProcessor); + $handler->setFormatter(new LineFormatter('%level_name% %message%')); + + $this->handler = $handler; + + return $logger; + } + + public function getLogs() + { + $convert = function ($record) { + $lower = function ($match) { + return strtolower($match[0]); + }; + + return preg_replace_callback('{^[A-Z]+}', $lower, $record['formatted']); + }; + + return array_map($convert, $this->handler->getRecords()); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/TestCase.php b/vendor/monolog/monolog/tests/Monolog/TestCase.php new file mode 100644 index 00000000..cae79340 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/TestCase.php @@ -0,0 +1,58 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog; + +class TestCase extends \PHPUnit_Framework_TestCase +{ + /** + * @return array Record + */ + protected function getRecord($level = Logger::WARNING, $message = 'test', $context = array()) + { + return array( + 'message' => $message, + 'context' => $context, + 'level' => $level, + 'level_name' => Logger::getLevelName($level), + 'channel' => 'test', + 'datetime' => \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true))), + 'extra' => array(), + ); + } + + /** + * @return array + */ + protected function getMultipleRecords() + { + return array( + $this->getRecord(Logger::DEBUG, 'debug message 1'), + $this->getRecord(Logger::DEBUG, 'debug message 2'), + $this->getRecord(Logger::INFO, 'information'), + $this->getRecord(Logger::WARNING, 'warning'), + $this->getRecord(Logger::ERROR, 'error') + ); + } + + /** + * @return Monolog\Formatter\FormatterInterface + */ + protected function getIdentityFormatter() + { + $formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface'); + $formatter->expects($this->any()) + ->method('format') + ->will($this->returnCallback(function ($record) { return $record['message']; })); + + return $formatter; + } +} diff --git a/vendor/monolog/monolog/tests/bootstrap.php b/vendor/monolog/monolog/tests/bootstrap.php new file mode 100644 index 00000000..b78740e2 --- /dev/null +++ b/vendor/monolog/monolog/tests/bootstrap.php @@ -0,0 +1,15 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +$loader = require __DIR__ . "/../vendor/autoload.php"; +$loader->addPsr4('Monolog\\', __DIR__.'/Monolog'); + +date_default_timezone_set('UTC'); diff --git a/vendor/oojs/oojs-ui/.mailmap b/vendor/oojs/oojs-ui/.mailmap deleted file mode 100644 index 84db0c6e..00000000 --- a/vendor/oojs/oojs-ui/.mailmap +++ /dev/null @@ -1,18 +0,0 @@ -Alex Monk <krenair@gmail.com> -Alex Monk <krenair@gmail.com> <krenair@wikimedia.org> -Bartosz Dziewoński <matma.rex@gmail.com> -Christian Williams <christian@wikia-inc.com> -David Chan <david@sheetmusic.org.uk> -Ed Sanders <esanders@wikimedia.org> -Inez Korczynski <inez@wikia-inc.com> -James D. Forrester <jforrester@wikimedia.org> -Kirsten Menger-Anderson <kmenger@wikimedia.org> -Marielle Volz <marielle.volz@gmail.com> -Moriel Schottlender <moriel@gmail.com> -Roan Kattouw <roan.kattouw@gmail.com> -Roan Kattouw <roan.kattouw@gmail.com> <roan@wikimedia.org> -Rob Moen <rmoen@wikimedia.org> -Sucheta Ghoshal <sghoshal@wikimedia.org> -Timo Tijhof <krinklemail@gmail.com> -Trevor Parscal <trevorparscal@gmail.com> - diff --git a/vendor/psr/log/Psr/Log/LoggerAwareTrait.php b/vendor/psr/log/Psr/Log/LoggerAwareTrait.php deleted file mode 100644 index f087a3da..00000000 --- a/vendor/psr/log/Psr/Log/LoggerAwareTrait.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -namespace Psr\Log; - -/** - * Basic Implementation of LoggerAwareInterface. - */ -trait LoggerAwareTrait -{ - /** @var LoggerInterface */ - protected $logger; - - /** - * Sets a logger. - * - * @param LoggerInterface $logger - */ - public function setLogger(LoggerInterface $logger) - { - $this->logger = $logger; - } -} diff --git a/vendor/psr/log/Psr/Log/LoggerTrait.php b/vendor/psr/log/Psr/Log/LoggerTrait.php deleted file mode 100644 index 59124960..00000000 --- a/vendor/psr/log/Psr/Log/LoggerTrait.php +++ /dev/null @@ -1,131 +0,0 @@ -<?php - -namespace Psr\Log; - -/** - * This is a simple Logger trait that classes unable to extend AbstractLogger - * (because they extend another class, etc) can include. - * - * It simply delegates all log-level-specific methods to the `log` method to - * reduce boilerplate code that a simple Logger that does the same thing with - * messages regardless of the error level has to implement. - */ -trait LoggerTrait -{ - /** - * System is unusable. - * - * @param string $message - * @param array $context - * @return null - */ - public function emergency($message, array $context = array()) - { - $this->log(LogLevel::EMERGENCY, $message, $context); - } - - /** - * Action must be taken immediately. - * - * Example: Entire website down, database unavailable, etc. This should - * trigger the SMS alerts and wake you up. - * - * @param string $message - * @param array $context - * @return null - */ - public function alert($message, array $context = array()) - { - $this->log(LogLevel::ALERT, $message, $context); - } - - /** - * Critical conditions. - * - * Example: Application component unavailable, unexpected exception. - * - * @param string $message - * @param array $context - * @return null - */ - public function critical($message, array $context = array()) - { - $this->log(LogLevel::CRITICAL, $message, $context); - } - - /** - * Runtime errors that do not require immediate action but should typically - * be logged and monitored. - * - * @param string $message - * @param array $context - * @return null - */ - public function error($message, array $context = array()) - { - $this->log(LogLevel::ERROR, $message, $context); - } - - /** - * Exceptional occurrences that are not errors. - * - * Example: Use of deprecated APIs, poor use of an API, undesirable things - * that are not necessarily wrong. - * - * @param string $message - * @param array $context - * @return null - */ - public function warning($message, array $context = array()) - { - $this->log(LogLevel::WARNING, $message, $context); - } - - /** - * Normal but significant events. - * - * @param string $message - * @param array $context - * @return null - */ - public function notice($message, array $context = array()) - { - $this->log(LogLevel::NOTICE, $message, $context); - } - - /** - * Interesting events. - * - * Example: User logs in, SQL logs. - * - * @param string $message - * @param array $context - * @return null - */ - public function info($message, array $context = array()) - { - $this->log(LogLevel::INFO, $message, $context); - } - - /** - * Detailed debug information. - * - * @param string $message - * @param array $context - * @return null - */ - public function debug($message, array $context = array()) - { - $this->log(LogLevel::DEBUG, $message, $context); - } - - /** - * Logs with an arbitrary level. - * - * @param mixed $level - * @param string $message - * @param array $context - * @return null - */ - abstract public function log($level, $message, array $context = array()); -} diff --git a/vendor/ruflin/elastica/LICENSE.txt b/vendor/ruflin/elastica/LICENSE.txt new file mode 100644 index 00000000..21580de7 --- /dev/null +++ b/vendor/ruflin/elastica/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Nicolas Ruflin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.
\ No newline at end of file diff --git a/vendor/ruflin/elastica/README.markdown b/vendor/ruflin/elastica/README.markdown new file mode 100644 index 00000000..a94e9ba3 --- /dev/null +++ b/vendor/ruflin/elastica/README.markdown @@ -0,0 +1,29 @@ +Elastica: elasticsearch PHP Client +================================== + +[![Latest Stable Version](https://poser.pugx.org/ruflin/Elastica/v/stable.png)](https://packagist.org/packages/ruflin/elastica) +[![Build Status](https://secure.travis-ci.org/ruflin/Elastica.png?branch=master)](http://travis-ci.org/ruflin/Elastica) +[![Coverage Status](https://coveralls.io/repos/ruflin/Elastica/badge.png)](https://coveralls.io/r/ruflin/Elastica) +[![Dependency Status](https://www.versioneye.com/php/ruflin:Elastica/master/badge.png)](https://www.versioneye.com/php/ruflin:elastica/) +[![Total Downloads](https://poser.pugx.org/ruflin/Elastica/downloads.png)](https://packagist.org/packages/ruflin/elastica) + +All documentation for Elastica can be found under [Elastica.io](http://Elastica.io/). If you have questions, don't hesitate to ask them in the [Elastica google group](https://groups.google.com/group/elastica-php-client). All library issues should go to the [issue tracker from github](https://github.com/ruflin/Elastica/issues). + +Contributing +------------ +Help is very welcomed, but code contributions must be done in respect of [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md). More details on how to contribute and guidelines for [pull requests](http://elastica.io/contribute/pull-request.html) can be found [here](http://elastica.io/contribute/). + +See [Coding guidelines](http://elastica.io/contribute/coding-guidelines.html) for tips on how to do so. All changes which are made to the project are added to the [changes.txt](https://github.com/ruflin/Elastica/blob/master/changes.txt). + + +Dependencies +------------ +| Project | Version | Required | +|---------|---------|----------| +|[Elasticsearch](https://github.com/elasticsearch/elasticsearch/tree/v1.1.1)|1.1.1|yes| +|[Elasticsearch mapper attachments plugin](https://github.com/elasticsearch/elasticsearch-mapper-attachments/tree/v2.0.0.RC1)|2.0.0.RC1|no| +|[Elasticsearch thrift transport plugin](https://github.com/elasticsearch/elasticsearch-transport-thrift/tree/v2.0.0)|2.0.0|no| +|[Elasticsearch geocluster facet plugin](https://github.com/zenobase/geocluster-facet/tree/0.0.10)|0.0.10|no| + + + diff --git a/vendor/ruflin/elastica/Vagrantfile b/vendor/ruflin/elastica/Vagrantfile new file mode 100644 index 00000000..e8cd5533 --- /dev/null +++ b/vendor/ruflin/elastica/Vagrantfile @@ -0,0 +1,14 @@ +# Elastica debian image +# +# All passwords and username (db, ...) are root / root +# +# The image has 2GB of memory and a size of 10GB + +Vagrant::Config.run do |config| + + config.vm.box = "debian-6.0.3-64-elastica-20120115" + config.vm.box_url = "http://files.ruflin.com/vagrant/debian-6.0.3-64-elastica-20120528.box" + config.vm.network :hostonly, "10.10.10.10" + + config.vm.share_folder "project", "/project", "." +end diff --git a/vendor/ruflin/elastica/build.xml b/vendor/ruflin/elastica/build.xml new file mode 100644 index 00000000..f24fbec7 --- /dev/null +++ b/vendor/ruflin/elastica/build.xml @@ -0,0 +1,232 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project name="Elastica" default="build" basedir="."> + + <property name="source" value="${basedir}/lib"/> + + <target name="parallelTasks"> + <parallel threadCount="2"> + <sequential> + <antcall target="pdepend"/> + <antcall target="phpmd-ci"/> + <antcall target="phpcb"/> + </sequential> + <antcall target="phpcpd"/> + <antcall target="phpcs-ci"/> + <antcall target="phpdoc-ci"/> + </parallel> + </target> + + <target name="clean" description="Cleanup build artifacts"> + <delete dir="${basedir}/build/api"/> + <delete dir="${basedir}/build/code-browser"/> + <delete dir="${basedir}/build/coverage"/> + <delete dir="${basedir}/build/logs"/> + <delete dir="${basedir}/build/pdepend"/> + <delete dir="${basedir}/build/docs"/> + <delete file="${basedir}/cache.properties"/> + </target> + + <target name="prepare" depends="clean" description="Prepare for build"> + <mkdir dir="${basedir}/build/api"/> + <mkdir dir="${basedir}/build/code-browser"/> + <mkdir dir="${basedir}/build/coverage"/> + <mkdir dir="${basedir}/build/logs"/> + <mkdir dir="${basedir}/build/docs"/> + <mkdir dir="${basedir}/build/pdepend"/> + </target> + + <target name="install" description="installs and starts elasticsearch"> + <exec executable="bash"> + <arg value="-c" /> + <arg value="curl -sS https://getcomposer.org/installer | php" /> + </exec> + <exec executable="php"> + <arg value="composer.phar" /> + <arg value="self-update" /> + </exec> + <exec executable="php"> + <arg value="composer.phar" /> + <arg value="--dev" /> + <arg value="install" /> + </exec> + <exec executable="bash"> + <env key="ES_VER" value="0.90.0"/> + <env key="ES_MAPPER_ATTACHMENTS_VER" value="1.6.0"/> + <env key="ES_TRANSPORT_THRIFT_VER" value="1.4.0"/> + <arg value="test/bin/run_elasticsearch.sh"/> + </exec> + </target> + + <target name="composer" depends="prepare" description="Install dependencies"> + <exec executable="composer"> + <arg value="--dev"></arg> + <arg value="install"></arg> + </exec> + </target> + + <target name="lint"> + <apply executable="php" failonerror="true"> + <arg value="-lf"/> + + <fileset dir="${source}"> + <include name="**/*.php"/> + <modified/> + </fileset> + + <fileset dir="${basedir}/test"> + <include name="**/*.php"/> + <modified/> + </fileset> + </apply> + </target> + + <target name="phpunit" depends="composer"> + <exec executable="phpunit" dir="${basedir}/test" failonerror="off" /> + </target> + + <!-- Generate jdepend.xml and software metrics charts --> + <target name="pdepend"> + <exec executable="pdepend"> + <arg value="--jdepend-xml=${basedir}/build/logs/jdepend.xml" /> + <arg value="--jdepend-chart=${basedir}/build/pdepend/dependencies.svg" /> + <arg value="--overview-pyramid=${basedir}/build/pdepend/overview-pyramid.svg" /> + <arg path="${source}" /> + </exec> + </target> + + <target name="phpmd-ci"> + <exec executable="phpmd"> + <arg path="${source}" /> + <arg value="xml" /> + <arg value="codesize,unusedcode,naming,design" /> + <arg value="--reportfile" /> + <arg value="${basedir}/build/logs/pmd.xml" /> + </exec> + </target> + + <!-- Generate pmd-cpd.xml --> + <target name="phpcpd"> + <exec executable="phpcpd"> + <arg line="--log-pmd ${basedir}/build/logs/pmd-cpd.xml ${source}" /> + </exec> + </target> + + <!-- Generate checkstyle.xml --> + <target name="phpcs-ci"> + <exec executable="phpcs" output="/dev/null"> + <arg line="--report=checkstyle --report-file=${basedir}/build/logs/checkstyle.xml --standard=PSR2 ${source}" /> + </exec> + </target> + + <target name="phploc" description="Generate phploc.csv"> + <exec executable="phploc"> + <arg value="--log-csv" /> + <arg value="${basedir}/build/logs/phploc.csv" /> + <arg path="${source}" /> + </exec> + </target> + + <!-- Generate API documentation --> + <target name="phpdoc"> + <exec executable="phpdoc"> + <arg line="run" /> + <arg line="-d lib/" /> + <arg line="-t build/docs" /> + </exec> + </target> + + <target name="phpdoc-ci"> + <exec executable="phpdoc"> + <arg line="run" /> + <arg line="-d lib/" /> + <arg line="-t build/docs" /> + <arg line="-q" /> + </exec> + </target> + + <target name="phpcb"> + <exec executable="phpcb"> + <arg line="--log ${basedir}/build/logs + --source ${source} + --output ${basedir}/build/code-browser" /> + </exec> + </target> + + <target name="build" depends="prepare,composer,lint,parallelTasks,phpunit"/> + + <!-- Checkstyle with human output --> + <target name="phpcs"> + <exec executable="phpcs"> + <arg line="--standard=PSR2 ${source}" /> + </exec> + </target> + + <target name="phpmd" description="Perform phpmd with human readable output"> + <exec executable="phpmd"> + <arg path="${source}"/> + <arg value="text"/> + <arg value="codesize,unusedcode,naming,design" /> + <arg value="${basedir}/build/phpmd.xml"/> + </exec> + </target> + + <!-- Setups test environment --> + <target name="setup" description="setups php libs for"> + <exec executable="pear"> + <arg line="channel-discover pear.pdepend.org" /> + </exec> + <exec executable="pear"> + <arg line="channel-discover pear.phpmd.org" /> + </exec> + <exec executable="pear"> + <arg line="channel-discover pear.phpunit.de" /> + </exec> + <exec executable="pear"> + <arg line="channel-discover components.ez.no" /> + </exec> + <exec executable="pear"> + <arg line="channel-discover pear.symfony-project.com" /> + </exec> + <exec executable="pear"> + <arg line="channel-discover pear.michelf.com" /> + </exec> + <exec executable="pear"> + <arg line="channel-discover pear.phpdoc.org" /> + </exec> + + <exec executable="pear"> + <arg line="install pdepend/PHP_Depend" /> + </exec> + <exec executable="pear"> + <arg line="install phpmd/PHP_PMD" /> + </exec> + <exec executable="pear"> + <arg line="install phpunit/phpcpd" /> + </exec> + <exec executable="pear"> + <arg line="install phpunit/phploc" /> + </exec> + <exec executable="pear"> + <arg line="install phpdoc/phpDocumentor-alpha" /> + </exec> + <exec executable="pear"> + <arg line="install PHP_CodeSniffer" /> + </exec> + <exec executable="pear"> + <arg line="install --alldeps phpunit/PHP_CodeBrowser" /> + </exec> + <exec executable="pear"> + <arg line="install --alldeps phpunit/PHPUnit" /> + </exec> + </target> + + <target name="gource" description="Visualize repos with gource"> + <exec executable="gource"> + <arg line="--log-format git" /> + <arg line="--seconds-per-day 0.1" /> + <arg line="--title 'Elastica (https://github.com/ruflin/Elastica)'" /> + <arg line="--user-scale 1" /> + <arg line="--max-user-speed 50" /> + </exec> + </target> +</project> diff --git a/vendor/ruflin/elastica/changes.txt b/vendor/ruflin/elastica/changes.txt new file mode 100644 index 00000000..525a6336 --- /dev/null +++ b/vendor/ruflin/elastica/changes.txt @@ -0,0 +1,797 @@ +CHANGES + +2014-07-26 +- Release v1.3.0.0 +- Prepare Elastica Release v1.3.0.0 + +2014-07-25 +- Update to elasticsearch version 1.3.0 http://www.elasticsearch.org/downloads/1-3-0/ + +2014-07-14 + - Add setQuery() method to Elastica\Query\ConstantScore #653 + +2014-07-12 + - Be able to configure ES host/port via ENV var in test env #652 + +2014-07-07 + - Fix FunstionScore Query random_score without seed bug. #647 + +2014-07-02 +- Add setPostFilter method to Elastica\Query (http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/_filtering_queries_and_aggregations.html#_post_filter) #645 + +2014-06-30 +- Add Reverse Nested aggregation (http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations-bucket-reverse-nested-aggregation.html). #642 + +2014-06-14 +- Release v1.2.1.0 +- Removed the requirement to set arguments filter and/or query in Filtered, according to the documentation: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-filtered-query.html #616 + +2014-06-13 +- Stop ClientTest->testDeleteIdsIdxStringTypeString from failing 1/3 of the time #634 +- Stop ScanAndScrollTest->testQuerySizeOverride from failing frequently for no reason #635 +- rework Document and Script so they can share some infrastructure allowing scripts to specify things like _retry_on_conflict and _routing #629 + +2014-06-11 +- Allow bulk API deletes to be routed #631 + +2014-06-10 +- Update travis to elasticsearch 1.2.1, disable Thrift plugin as not compatible and fix incompatible tests + +2014-06-04 +- Implement Boosting Query (http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-boosting-query.html) #625 + +2014-06-02 +- add retry_on_conflict support to bulk #623 + +2014-06-01 +- toString updated to consider doc_as_upsert if sent an array source #622 + +2014-05-27 +- Fix Aggragations/Filter to work with es v1.2.0 #619 + +2014-05-25 +- Added Guzzle transport as an alternative to the default Http transport #618 +- Added Elastica\ScanAndScroll Iterator (http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/scan-scroll.html) #617 + +2014-05-13 +- Add JSON compat library; Elasticsearch JSON flags and nicer error handling #614 + +2014-05-12 +- Update dev builds to phpunit 4.1.* + +2014-05-11 +- Set processIsolation and backupGlobals to false to speed up tests. processIsolation was very slow with phpunit 4.0.19. + +2014-05-05 +- Fix get settings on alaised index #608 +- Added named function for source filtering #605 +- Scroll type constant to Elastica\Search added #607 + +2014-04-28 +- Added setAnalyzer method to Query\FuzzyLikeThis Class and fixed issue with params not being merged #611 +- Typo fixes #600, #602 +- Remove unreachable return statement #598 + +2014-04-27 +- Release v1.1.1.1 +- Fix missing use in TermsStats->setOrder() #597 +- Replace all instances of ElasticSearch with Elasticsearch #597 + +2014-04-24 +- Fixing the Bool filter with Bool filter children bug #594 + +2014-04-22 +- Remove useless echo in the Memcache Transport object #595 + +2014-04-21 +- escape \ by \\ #592 + +2014-04-20 +- Handling of HasChild type parsing bug #585 +- Consolidate Index getMapping tests #591 +- Fix Type::getMapping when using an aliased index #588 + +2014-04-19 +- Release v1.1.1.0 +- Update to elasticsearch 1.1.1 http://www.elasticsearch.org/downloads/1-1-1/ +- Remove CustomFiltersScore and CustomScore query as removed in elasticsearch 1.1.0 https://github.com/elasticsearch/elasticsearch/pull/5076/files +- Update Node Info to use plugins instead of plugin (https://github.com/elasticsearch/elasticsearch/pull/5072) +- Fix mapping issue for aliases #588 + +2014-04-17 +- Only trap real JSON parse errors in Response class #586 + +2014-04-09 +- Added Cardinality aggregation #581 + +2014-04-7 +- Support for Terms filter lookup options #579 + +2014-03-29 +- Update to elasticsearch 1.1.0 http://www.elasticsearch.org/downloads/1-1-0/ + +2014-03-26 +- Fixed Query\Match Fuzziness parameter type #576 + +2014-03-24 +- Release v1.0.1.2 +- Added Filter\Indices #574 + +2014-03-25 +- Allow json string as data srouce for Bulk\Action on update #575 + +2014-03-20 +- Allow for request params in delete by query calls #573 + +2014-03-17 +- Added filters: AbstractGeoShape, GeoShapePreIndexed, GeoShapeProvided #568 + +2014-03-15 +- Percolate existing documents and add percolate options (#570) + +2014-03-14 +- Added Query\Rescore #441 + +2014-03-13 +- Added missing query options for MultiMatch (operator, minimum_should_match, zero_terms_query, cutoff_frequency, type, fuzziness, prefix_length, max_expansions, analyzer) #569 +- Added missing query options for Match (zero_terms_query, cutoff_frequency) #569 + +2014-03-11 +- Fixed request body reuse in http transport #567 + +2014-03-08 +- Release v1.0.1.1 +- Enable goecluster-facet again as now compatible with elasticsearch 1.0 on travis +- Run elasticsearch in the background to not have log output in travis build +- Set memache php version as environment variable +- Update to memcache 3.0.8 for travis + +2014-03-07 +- Add snapshot / restore functionality (Elastica\Snapshot) #566 + +2014-03-04 +- Add PHP 5.6 to travis test environment +- Improve performance of Elastica/Status->getIndicesWithAlias and aliasExists on clusters with many indices #563 + +2014-03-02 +- Release v1.0.1.0 +- Fixed Type->deleteByQuery() not working with Query objects #554 + +2014-02-27 +- Update to elasticsearch 1.0.1. Update Thrift and Geocluster plugin. + +2014-02-25 +- Add JSON_UNESCAPED_UNICODE and JSON_UNESCAPED_SLASHES options in Elastica/Transport/Http, Elastica/Bulk/Action #559 + +2014-02-20 +- Fixed unregister percolator (still used _percolator instead of .percolator). removed duplicate slash from register percolator route. #558 + +2014-02-17 +- Throw PartialShardFailureException if response has failed shards +- Elastica/Aggregations/GlobalAggragation not allowed as sub aggragation #555 + +2014-02-14 +- Add methods setSize, setShardSize to Elastica/Aggregation/Terms +- Elastica/Aggregation/GlobalAggregationTest fixed bug where JSON returned [] instead of {} +- Elastica/ResultSet added method hasAggregations + +2014-02-13 +- Moved from Apache License to MIT license + +2014-02-12 +- Release v1.0.0.0 +- Updated to elasticsearch 1.0: http://www.elasticsearch.org/blog/1-0-0-released/ + +2014-02-11 +- Add aggregations + +2014-02-08 +- Setting shard timeout doesn't work #547 + +2014-02-04 +- Remove Elastica\Query\Field and Elastica\Query\Text, which are not supported in ES 1.0.0.RC1 +- Minor tweaking of request and result handling classes to adjust for changes in ES 1.0.0.RC1 +- Update mapper-attachments plugin to version 2.0.0.RC1 in .travis.yml +- Adjust tests to account for changes in ES 1.0.0.RC1 +- Prevent the geocluster-facet plugin from being installed in test/bin/run_elasticsearch.sh as the plugin has not yet been updated for ES 1.0.0.RC1 + +2014-01-06 +- Update to elasticsearch v1.0.0.RC2 + +2014-01-02 +- Added Elastica\Query\DisMax +- Update to elasticsearch v1.0.0.RC1 + +2014-01-02 +- Release v0.90.10 + +2014-01-31 +- Fix _bulk delete proxy methods if type or index not explicitly defined. + +2014-01-28 +- Add _bulk delete proxy methods to Index and Type for consistency. +- Use the HTTP response code of GET requests (getDocument), instead of extists/found json property. + +2014-01-22 +- Add getParam & getProperties methods to Elastica\Type\Mapping + +2014-01-21 +- Code coverage generation for coveralls.io added: https://coveralls.io/r/ruflin/Elastica +- Add support for shard timeout to the Bulk api. + +2014-01-17 +- Fix typo in constant name: Elastica\Query\FunctionScore::DECAY_GUASS becomes DECAY_GAUSS + +2014-01-13 +- Add support for _bulk update + +2014-01-14 +- added \Elastica\Exception\ResponseException::getElasticsearchException() +- Changed logger default log level to debug from info + +2014-01-13 +- Update to elasticsearch 0.90.10 +- Add Elastica\Facet\TermsStats::setOrder() + +2014-01-08 +- Adding analyze function to Index to expose the _analyze API + +2014-01-07 +- Document::setDocAsUpsert() now returns the Document + +2013-12-18 +- Update to Elasticsearch 0.90.8 +- Add support for simple_query_string query + +2013-12-15 +- Add support for filter inside HasChild filter +- Add support for filter inside HasParent filter + +2013-12-12 +- Always send scroll_id via HTTP body instead of as a query param +- Fix the manner in which suggestion results are returned in \Elastica\ResultSet and adjust associated tests to account for the fix. +- Add \Elastica\Resultset::hasSuggests() + +2013-12-11 +- Pass arguments to optimize as query +- Add refreshAll on Client + +2013-12-07 +- Added Result::hasFields() and Result::hasParam() methods for consistency with Document + +2013-12-07 +- Escape slash in Util::escapeTerm, as it is used for regexp from Elastic 0.90 + +2013-12-05 +- Add *.iml to .gitignore +- Refactor suggest implementation (\Elastica\Suggest, \Elastica\Suggest\AbstractSuggest, and \Elastica\Suggest\Term) to more closely resemble query implementation. (BC break) +- \Elastica\Search::addSuggest() has been renamed to \Elastica\Search::setSuggest() +- \Elastica\Query::addSuggest() has been renamed to \Elastica\Query::setSuggest() +- Add \Elastica\Suggest\Phrase, \Elastica\Suggest\CandidateGenerator\AbstractCandidateGenerator, and \Elastica\Suggest\CandidateGenerator\DirectGenerator + (see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters-phrase.html) + +2013-12-04 +- Remove boost from FunctionScore::addFunction because this is not supported by elasticsearch + +2013-12-02 +- Issue #491 resolved + +2013-12-01 +- Issue #501 resolved +- satooshi/php-coveralls package added for coverall.io +- Multiple badges for downloads and latest stable release added + +2013-11-30 +- Remove facets param from query if is empty array +- Add size param to API for TermsStats + +2013-11-23 +- Release v0.90.7.0 + +2013-11-19 +- Updated geocluster-facet to 0.0.9 + +2013-11-18 +- Added \Elastica\Filter\Regexp + +2013-11-16 +- Remove wrong documentation for "no limit" #496 +- Update to elasticsearch 0.90.7 + +2013-11-03 +- Issue #490: Set Elastica\Query\FunctionScore::DECAY_EXPONENTIAL to "exp" instead of "exponential" + +2013-10-29 +- Elastica_Type::exists() added + See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-types-exists.html#indices-types-exists + +2013-10-27 +- Adapted possible values (not only in) for minimum_should_match param based on elasticsearch documetnation http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-minimum-should-match.html + +2013-10-27 +- Release v0.90.5.0 + +2013-10-26 +- Update to elasticsearch 0.90.5 + +2013-10-21 +- Fix \Elastica\Filter\HasParent usage of \Elastica\Query as to not collide with \Elastica\Filter\Query, bring \Elasitca\Filter\HasChild into line + +2013-10-01 +- Also pass the current client object to the failure callback in \Elastica\Client. + +2013-09-20 +- Update to geocluster-facet 0.0.8 +- Add support for term suggest API + See http://www.elasticsearch.org/guide/reference/api/search/term-suggest/ + +2013-09-18 +- Fix \Elastica\Filter\HasChild usage of \Elastica\Query as to not collide with \Elastica\Filter\Query namespace + +2013-09-17 +- Update to elasticsearch 0.90.4 +- Add support for function_score query +- Skip geocluster-facet test if the plugin is not installed +- Correct \Elastica\Test\ClientTest to catch the proper exception type on connection failure +- Fix unit test errors + +2013-09-14 +- Nested filter supports now the setFilter method + +2013-09-03 +- Support isset() calls on Result objects + +2013-08-27 +- Add \ArrayAccess on the ResultSet object + +2013-08-25 +- Update to elasticsearch 0.90.3 + +2013-08-25 +- Release v0.90.2.0 + +2013-08-20 +- Support for "proxy" param for http connections + +2013-08-17 +- Add support for fields parameter in Elastica_Type::getDocument() + +2013-08-13 +- Add a getQuery method on the FilteredQuery object + +2013-08-01 +- Second param to \Elastica\Search.php:count($query = '', $fullResult = false) added. If second param is set to true, full ResultSet is returned including facets. + +2013-07-16 +- Plugin geocluster-facet support added + +2013-07-02 +- Add Query\Common +- Can now create a query by passing an array to Type::search() + +2013-07-01 +- Add Filter\GeohashCell + +2013-06-30 +- Revamped upsert so that Scripts are now first class citizens. (BC break) + See http://elastica.io/migration/0.90.2/upsert.html +- Implemented doc_as_upsert. + +2013-06-29 +- Update to elasticsearch 0.90.2 +- Enabled ES_WAIT_ON_MAPPING_CHANGE for travis builds + +2013-06-25 +- Added upsert support when updating a document with a partial document or a script. + +2013-06-23 +- Add filtered queries to the percolator API. + +2013-06-21 +- Correct class name for TermTest unit test +- Implement terms lookup feature for terms filter + +2013-06-14 +- Fix support for making scroll queries once the scroll has been started. + +2013-06-07 +- Release 0.90.1.0 + +2013-06-05 +- Changed package name to lowercase to prevent potential issues with case sensitive file systems and to refelect the package name from packagist.org. + If you are requiring elastica in your project you might want to change the name in the require to lowercase, although it will still work if written in uppercase. + The composer autoloader will handle the package correctly and you will not notice any difference. + If you are requiring or including a file by hand with require() or include() from the composer vendor folder, pay attention that the package name in + the path will change to lowercase. +- Add Bulk\Action\UpdateDocument. +- Update Bulk\Action\AbstractDocument and Bulk\Action to enable use of OP_TYPE_UPDATE. +- Update .travis.yml to use Elasticsearch version 0.9.1, as bulk update is a new feature in 0.9.1. + +2013-06-04 +- Elastica\Client::_configureParams() changed to _prepareConnectionParams(), which now takes the config array as an argument + +2013-06-03 +- Add getPlugins and hasPlugin methods to Node\Info + +2013-05-30 +- Update Index\Status::getAliases() to use new API +- Update Index\Status::getSettings() to use new API + +2013-05-29 +- Add _meta to mapping. #330 + +2013-05-27 +- Added parameters to implement scroll + +2013-05-23 +- add support PSR-3(https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) +- Elastica\Log implement LoggerInterface(extends Psr\Log\AbstractLogger) + if you want use logging need install https://github.com/php-fig/log for example (composer require psr/log:dev-master) + if use Elastica\Log inside Elastica\Client nothing more is needed + if use Elastica\Log outside we need use as(https://github.com/php-fig/log) for example Elastica\Log::info($message) or Elastica\Log::log(LogLevel::INFO,$message) +- Elastica\Client add setLogger for setting custom Logger for example Monolog(https://github.com/Seldaek/monolog) + +2013-05-18 +- Elastica\Index::exists fixed for 0.90.0. HEAD request method introduced +- Elastica\Filter\AbstractMulti::getFilters() added +- Implement Elastica\Type\Mapping::enableAllField +- Refresh for Elastica\Index::flush implemented #316 +- Added optional parameter to filter result while percolate #384 + +2013-05-07 +- Added EXPERIMENTAL DocumentObjectInterface to be used with Type::addObject()/addObjects() + +2013-04-23 +- Removed Elastica\Exception\AbstractException +- All Exceptions now implement Elastica\Exception\ExceptionInterface + +2013-04-17 +- Query\Fuzzy to comply with DSL spec. Multi-field queries now throw an exception. Implemented: Query\Fuzzy::setField, Query\Fuzzy::setFieldOption. +- Query\Fuzzy::addField has been deprecated. + +2013-04-12 +- Adding max score information in ResultSet +- Adding test for the ResultSet class + +2013-03-20 +- Removal of unsupported minimum_number_should_match for Boolean Filter + +2013-02-25 +- Added Elastica\Bulk class responsible for performing bulk requests. New bulk requests implemented: Client::deleteDocuments(), Bulk::sendUdp() + +2013-02-20 +- Release candidate 0.20.5.0.RC1 + +2013-02-14 +- Added factory for transports that is used by the Connection class +- The transport instances now has support for parameters that can be injected by specifying an array as a transport when creating the Elastica client + +2013-02-08 +- Terms->setScript() Added, namespace Elastica\Facet + +2013-01-31 +- Removed deprecated method Type::getType() +- Removed deprecated old constructor call in Filter\GeoDistance::__construct() +- Removed deprecated method Filter\Script::setQuery() +- Removed deprecated methods Query\QueryString::setTieBraker() and Query\QueryString::setQueryString() +- Removed deprecated methods Query\Builder::minimumShouldMatch() and Query\Builder::tieBreaker() + +2013-01-25 +- Add get/set/has/remove methods to Document +- Add magic methods __get/__set/__isset/__unset to Document +- Document::add method became deprecated, use set instead +- Populate document id created by elasticsearch on addDocument()/addDocuments() call if no document id was set +- Populate updated fields in document on Client::updateDocument() call if fields options is set + +2013-01-24 +- Added serialization support. Objects can be added to elastica directly when a serializer callable is configured on \Elastica\Type + +2013-01-21 +- Added Thrift transport. Ir requires installing munkie/elasticsearch-thrift-php package and elasticsearch-tranport-thrift plugin should be installed in elastcisearch + +2013-01-13 +- Add version option to Elastica_Search::search +- Remove compatibility for PHP 5.2 +- Changed all syntax using namespaces, in compliance with PSR-2. +- Usage of composer for lib and test autoloading +- Added PHPUnit as a dev dependency in composer.json +- All tests were rewritten for new syntax. +- All tests where moved in Elastica\Test namespace +- All tests now inherit from Elastica\Test\Base +- Removed all executable flags on files where not needed. +- Update to elasticsearch 0.20.2 +- Refactored Elastica_Script and added it support in Elastica_Query_CustomFiltersScore, Elastica_Query_CustomScore and Elastica_Filter_Script +- Refactored Elastica_Client::updateDocument() method to support partial document update. $data can be Elastic_Script, Elastic_Document or array. +- Elastica_Type::updateDocument() now takes Elastica_Document instead of Elastica_Script (BC break). Script can be set to document to perform script update. + +2012-12-23 +- Elastica_Client config param "servers" to "connections" renamed. "headers" and "curl" are now a config param inside "connections" +- Elastica_Connection added to allow connection management (enabled / disable) +- Refactoring of Elastica_Request. Takes Elastica_Connection in constructor instead of Elastica_Client +- Elastica_Transport refactored +- Elastica_Log refactored +- Renamed Elastica_Exception_Client to Elastica_Exception_Connection +- Use Elastica_Connection for the following constants: DEFAULT_PORT, DEFAULT_HOST, DEFAULT_TRANSPORT, TIMEOUT + +2012-11-28 +- Added Elastica_Filter_GeoDistanceRange filter + +2012-11-23 +- Simplified Elastica_Document data handling by extending Elastica_Param + +2012-11-10 +- Added Elastica_Cluster_Health, Elastica_Cluster_Health_Index and Elastica_Cluster_Health_Shard which wrap the _cluster/health endpoint. +- Added Elastica_Document::setId() +- Added options parameter to Elastica_Type::getDocument() +- Added Elastica_Query_Filtered::getFilter() + +2012-10-30 +- Elastica_Search implement Elastica_Searchable interface + +2012-10-28 +- Add Elastica_Filter_HasParent and Elastic_Query_HasParent + +2012-08-11 +- Release v0.19.8.0 +- Elastica_Query_Prefix added + +2012-07-26 +- Change Elastica_Filter_GeoDistance::__construct(), accepts geohash parameter (BC break, before: ($key, $latitude, $longitude, $distance), after: ($key, $location, $distance) where $location is array('lat' => $latitude, 'lon' => $longitude) or a geohash) + +2012-07-17 +- Changed naming for several methods to camelCase +- Enforced PSR1 code style, as per https://github.com/pmjones/fig-standards/blob/psr-1-style-guide/proposed/PSR-1-basic.md +- Added Elastica_Script::toArray +- Added Elastica_ScriptFields +- Elastica_Query::setScriptFields now takes Elastica_ScriptFields or associative array as argument, the old implementation was bogus. + +2012-06-24 +- Simplify Elastica_Type::search and Elastica_Index::search by using Elastica_Search +- Implement Elastica_Filter_Abstract::setCache and Elastica_Filter_Abstract::setCacheKey +- Add Elastica_Param::hasParam +- Remove unsupported use of minimum number should match for Boolean Filter +- Remove old style path creation through params in Elastica_Index::create and Elastica_Search::search + +2012-06-22 +- Add Elastica_Filter_Limit +- Add getters+setters for Index Setting blocks 'read', 'write' and 'metadata' +- Add Elastica_Filter_MatchAll + +2012-06-20 +- Facet scope added + +2012-06-09 +- Change $_parent to null to also support 0 for an id +- Fix Elasitca_Document->toArray() + +2012-05-01 +- Release v0.19.3.0 +- MoreLikeThis Query in Elastica_Document +- Add query param for request (allows GET params) + +2012-03-04 +- Node info call update. The receive os info and more, param is needed. By default, only basics are returned +- Release v0.19.0.0 which is compatible with ES 0.19.0 http://www.elasticsearch.org/blog/2012/03/01/0.19.0-released.html + +2012-02-21 +- Allow percolate queries in bulk requests +- Fix memory leak in curl requests + +2012-01-23 +- Packagist added http://packagist.org/ + +2012-01-15 +- Vagrantfile for vagrant environment with elasticsearch added. Run: vagrant up + +2012-01-08 +- Allow to set curl params over client config #106 #107 +- Add the possiblity to add path or url in config for a request #120 + +2012-01-04 +- Elastica_Index::exists() and Elastica_Cluster::getIndexNames() added + +2012-01-01 +- Elastica_Cluster_Settings added +- Read only feature for cluster and index added. This feature is elasticsearch >0.19.0 only. ES 0.19.0 release is not out yet + +2011-12-29 +- Elastica_Type::deleteByQuery implemented + +2011-12-20 +- Release v0.18.6.0 + +2011-12-19 +- Percolator for Type and Documents added + +2011-12-06 +- Elastica_Percolator added. See tests for more details + +2011-12-02 +- Rename Elastica_Type::getType() to Elastica_Type::getName(), getType() is now deprecated + +2011-12-01 +- Elastica_Filter_Term::addTerm renamed to setTerm, Elastica_Filter_Term::setTerm renamed to setRawTerm +- Elastica_Query_Term::addTerm renamed to setTerm, Elastica_Query_Term::setTerm renamed to setRawTerm + +2011-11-30 +- Release v0.18.5.0 + +2011-11-28 +- Elastica_Filter_Nested added + +2011-11-26 +- Elastica_Search::addIndices(), Elastica_Search::addTypes() added + +2011-11-20 +- Release v0.18.4.1 +- Elastica_Log added for logging. Has to be passed as client config to enable +- Elastica blogging introduced: http://ruflin.com/en/elastica + +2011-11-17 +- Release v0.18.4.0 +- Support for Travis CI added: http://travis-ci.org/ruflin/Elastica + +2011-11-07 +- Elastica_Index_Stats added + +2011-11-05 +- Elastica_Query_Nested added + +2011-10-29 +- TTL for document and mapping added + +2011-10-28 +- Refactored Elastica_Query_CustomScore::addCSParam to ::addParams +- Rename Elastica_Query_CustomScore::addParam to ::addCSParam +- Release v0.18.1.0 + +2011-10-20 +- Release v0.17.9.0 +- Elastica_Filter_Type added + +2011-10-19 +- Elastica_Query_CustomFilterScore added + +2011-10-15 +- API Documentation changed to DocBlox + +2011-10-10 +- Bug fixing +- Release v0.17.8.0 added + +2011-09-19 +- Release v0.17.7.0 added +- Release v0.17.6.1 added + +2011-09-18 +- Elastica_Exception_ExpectedFieldNotFound renamed to Elastica_Exception_NotFound + +2011-08-25 +- Https transport layer added + +2011-08-22 +- Typo in Terms query fixed (issue #74) + +2011-08-15 +- Refactoring HTTP connection to keep alive connection -> speed improvement during using the same client +- Release v0.17.6.0 added + +2011-08-09 +- Automatic creation of id for documents added. This was more a bug +- Release v0.17.4.0 added + +2011-08-08 +- Elastica_Query_Text added +- Params (constructor) of Elastica_Filter_GeoBoundingBox changed (array instead of single params) + +2011-08-07 +- Elastica_Query_MoreLikeThis added by @juneym. Still work under progress +- Refactoring Queries and Filters to use Elastica_Param. Adding tests + +2011-08-05 +- Elastica_Filter_Abstract enhanced for more general usage (set/get/addParam(s)) added + +2011-08-04 +- Release v0.17.3.0 added +- Elastica_Index_Settings::set/get response updated. get('...') does not require 'index.' in front anymore +- Nodes and Cluster shutdown added +- Elastica_Node::getIp() and getPort() added + +2011-07-30 +- Readd merge_factor to settings. Now working as expected. Index has to be closed first. + +2011-07-29 +- Release tag v0.17.2.0 added. Elastica is compatible with elasticsearch 0.17.2 + +2011-07-22 +- Elastica_Index_Settings::getMergePolicyMergeFactor and set removed because of enhanced merge policy implementation in ES 0.17.0 https://github.com/elasticsearch/elasticsearch/issues/998 +- Release tav v0.17.1.0 added + +2011-07-21 +- Elastica_Query_HasChild and _parent feature added by fabian +- Elastica_Filter_GeoBoundingBox added by fabian + +2011-07-20 +- Elastica_Query_Builder added by chrisdegrim + +2011-07-19 +- Release tag v0.17.0.0 added. Elastica is compatible with elasticsearch 0.17.0 + +2011-07-18 +- ResultSet::hasFacets added +- QueryString useDisMax added + +2011-07-15 +- Facet/DateHistogram and Facet/Historgram added +- Documentation pages added unter http://ruflin.github.com/Elastica +- Release tag v0.16.4.0 added + +2011-06-19 +- Add support for multiple servers to Elastica_Client (issue #39) + +2011-06-16 +- Support for multiple index, type queries and _all queries added through Elastica_Search object +- Elastica_Index::clearCache added to clean cache +- Elastica_Index::flush added + +2011-06-07 +- Elastica_Index::setNumberOfShards removed as not supported after creating index + +2011-05-11 +- Refactor client constructor. Elastica_Client::__construct(array $config) now takes a config array instead of host and port + +2011-05-08 +- Elastica_Query_QueryString::escapeTerm move to Elastica_Util::escapeTerm + +2011-04-29 +- Added getParam to Elastica_Result that more values can be retrieved from the hit array +- Elastica_Filter_Ids added http://www.elasticsearch.org/guide/reference/query-dsl/ids-filter.html +- getMergePolicyMergeFactor and getRefreshInterval to Elastica_Type_Settings added. If no value is set, default values are returned + +2011-04-28 +- Release of version 0.16.0.0 (see new version naming structure in README) + +2011-04-27 +- Refactoring of Elastica_Type::setMapping. No source parameter anymore. +- Elastica_Type_Mapping object introduced to set more fine grained mapping + +2011-04-17 +- Elastica_Filter_Exists added + +2011-04-14 +- Elastica_Type getCount replace by count() +- Count has now optional query parametere + +2011-04-01 +- Renaming of functions in Elastica_Query_Terms and Ela-stica_Query_Filter to fit new naming convention. setTerms, addTerm have different API now! + +2011-03-31 +- Deprecated code removed +- Break backward compatibility to 0.15.1 (versions introduced by wlp1979) + +2011-03-30 +- Filtered query introduced +- setRawArguments in Elastica_Query is now setParam +- open / close for index added +- Remove Elastica_Filter and Elastica_Facets because not needed anymore + +2011-03-29 +- Renaming Elastica_Filter->addQuery, addFilter to setQuery, setFilter +- Add parts of Facets API +- Add facet Terms +- Renaming Elastica_Query->addFilter to setFilter + +2011-03-24 +- Renaming of Elastica_Status_Index to Elastica_Index_Status => API Change! +- IndexSettings added for improved bulk updating http://www.elasticsearch.org/blog/2011/03/23/update-settings.html + +2011-03-21 +- Node object added +- Node_Info and Node_Stats added +- Refactoring of Cluster object + +2011-03-13 +- changes.txt introduced +- getResponse in Elastica_Response renamed to getData. getResponse now deprecated +- Index status objects added +- getIndexName in Elastica_Index renamed to getName. getIndexName is deprecated diff --git a/vendor/ruflin/elastica/composer.json b/vendor/ruflin/elastica/composer.json new file mode 100644 index 00000000..70c2832a --- /dev/null +++ b/vendor/ruflin/elastica/composer.json @@ -0,0 +1,40 @@ +{ + "name": "ruflin/elastica", + "description": "Elasticsearch Client", + "keywords": ["search","client"], + "homepage": "http://elastica.io/", + "type": "library", + "license": "Apache 2.0", + "authors": [ + { + "name": "Nicolas Ruflin", + "homepage": "http://ruflin.com/" + } + ], + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "munkie/elasticsearch-thrift-php": "1.4.*", + "phpunit/phpunit": "4.1.*", + "satooshi/php-coveralls": "dev-master" + }, + "suggest": { + "munkie/elasticsearch-thrift-php": "Allow using thrift transport", + "guzzlehttp/guzzle": "Allow using guzzle 4.x as the http transport (requires php 5.4)", + "psr/log": "for logging", + "monolog/monolog": "Logging request" + }, + "autoload": { + "psr-0": { + "Elastica": "lib/", + "Elastica\\Test": "test/lib/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/AbstractUpdateAction.php b/vendor/ruflin/elastica/lib/Elastica/AbstractUpdateAction.php new file mode 100644 index 00000000..883284ae --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/AbstractUpdateAction.php @@ -0,0 +1,544 @@ +<?php + +namespace Elastica; + +/** + * Base class for things that can be sent to the update api (Document and + * Script). + * + * @category Xodoa + * @package Elastica + * @author Nik Everett <nik9000@gmail.com> + */ +class AbstractUpdateAction extends Param +{ + /** + * @var \Elastica\Document + */ + protected $_upsert; + + /** + * Sets the id of the document. + * + * @param string $id + * @return \Elastica\Document + */ + public function setId($id) + { + return $this->setParam('_id', $id); + } + + /** + * Returns document id + * + * @return string|int Document id + */ + public function getId() + { + return ($this->hasParam('_id')) ? $this->getParam('_id') : null; + } + + /** + * @return bool + */ + public function hasId() + { + return '' !== (string) $this->getId(); + } + + /** + * Sets lifetime of document + * + * @param string $ttl + * @return \Elastica\Document + */ + public function setTtl($ttl) + { + return $this->setParam('_ttl', $ttl); + } + + /** + * @return string + */ + public function getTtl() + { + return $this->getParam('_ttl'); + } + + /** + * @return bool + */ + public function hasTtl() + { + return $this->hasParam('_ttl'); + } + + /** + * Sets the document type name + * + * @param string $type Type name + * @return \Elastica\Document Current object + */ + public function setType($type) + { + if ($type instanceof Type) { + $this->setIndex($type->getIndex()); + $type = $type->getName(); + } + return $this->setParam('_type', $type); + } + + /** + * Return document type name + * + * @return string Document type name + * @throws \Elastica\Exception\InvalidException + */ + public function getType() + { + return $this->getParam('_type'); + } + + /** + * Sets the document index name + * + * @param string $index Index name + * @return \Elastica\Document Current object + */ + public function setIndex($index) + { + if ($index instanceof Index) { + $index = $index->getName(); + } + return $this->setParam('_index', $index); + } + + /** + * Get the document index name + * + * @return string Index name + * @throws \Elastica\Exception\InvalidException + */ + public function getIndex() + { + return $this->getParam('_index'); + } + + /** + * Sets the version of a document for use with optimistic concurrency control + * + * @param int $version Document version + * @return \Elastica\Document Current object + * @link http://www.elasticsearch.org/blog/2011/02/08/versioning.html + */ + public function setVersion($version) + { + return $this->setParam('_version', (int) $version); + } + + /** + * Returns document version + * + * @return string|int Document version + */ + public function getVersion() + { + return $this->getParam('_version'); + } + + /** + * @return bool + */ + public function hasVersion() + { + return $this->hasParam('_version'); + } + + /** + * Sets the version_type of a document + * Default in ES is internal, but you can set to external to use custom versioning + * + * @param int $versionType Document version type + * @return \Elastica\Document Current object + * @link http://www.elasticsearch.org/guide/reference/api/index_.html + */ + public function setVersionType($versionType) + { + return $this->setParam('_version_type', $versionType); + } + + /** + * Returns document version type + * + * @return string|int Document version type + */ + public function getVersionType() + { + return $this->getParam('_version_type'); + } + + /** + * @return bool + */ + public function hasVersionType() + { + return $this->hasParam('_version_type'); + } + + /** + * Sets parent document id + * + * @param string|int $parent Parent document id + * @return \Elastica\Document Current object + * @link http://www.elasticsearch.org/guide/reference/mapping/parent-field.html + */ + public function setParent($parent) + { + return $this->setParam('_parent', $parent); + } + + /** + * Returns the parent document id + * + * @return string|int Parent document id + */ + public function getParent() + { + return $this->getParam('_parent'); + } + + /** + * @return bool + */ + public function hasParent() + { + return $this->hasParam('_parent'); + } + + /** + * Set operation type + * + * @param string $opType Only accept create + * @return \Elastica\Document Current object + */ + public function setOpType($opType) + { + return $this->setParam('_op_type', $opType); + } + + /** + * Get operation type + * @return string + */ + public function getOpType() + { + return $this->getParam('_op_type'); + } + + /** + * @return bool + */ + public function hasOpType() + { + return $this->hasParam('_op_type'); + } + + /** + * Set percolate query param + * + * @param string $value percolator filter + * @return \Elastica\Document + */ + public function setPercolate($value = '*') + { + return $this->setParam('_percolate', $value); + } + + /** + * Get percolate parameter + * + * @return string + */ + public function getPercolate() + { + return $this->getParam('_percolate'); + } + + /** + * @return bool + */ + public function hasPercolate() + { + return $this->hasParam('_percolate'); + } + + /** + * Set routing query param + * + * @param string $value routing + * @return \Elastica\Document + */ + public function setRouting($value) + { + return $this->setParam('_routing', $value); + } + + /** + * Get routing parameter + * + * @return string + */ + public function getRouting() + { + return $this->getParam('_routing'); + } + + /** + * @return bool + */ + public function hasRouting() + { + return $this->hasParam('_routing'); + } + + /** + * @param array|string $fields + * @return \Elastica\Document + */ + public function setFields($fields) + { + if (is_array($fields)) { + $fields = implode(',', $fields); + } + return $this->setParam('_fields', (string) $fields); + } + + /** + * @return \Elastica\Document + */ + public function setFieldsSource() + { + return $this->setFields('_source'); + } + + /** + * @return string + */ + public function getFields() + { + return $this->getParam('_fields'); + } + + /** + * @return bool + */ + public function hasFields() + { + return $this->hasParam('_fields'); + } + + /** + * @param int $num + * @return \Elastica\Document + */ + public function setRetryOnConflict($num) + { + return $this->setParam('_retry_on_conflict', (int) $num); + } + + /** + * @return int + */ + public function getRetryOnConflict() + { + return $this->getParam('_retry_on_conflict'); + } + + /** + * @return bool + */ + public function hasRetryOnConflict() + { + return $this->hasParam('_retry_on_conflict'); + } + + /** + * @param string $timestamp + * @return \Elastica\Document + */ + public function setTimestamp($timestamp) + { + return $this->setParam('_timestamp', $timestamp); + } + + /** + * @return int + */ + public function getTimestamp() + { + return $this->getParam('_timestamp'); + } + + /** + * @return bool + */ + public function hasTimestamp() + { + return $this->hasParam('_timestamp'); + } + + /** + * @param bool $refresh + * @return \Elastica\Document + */ + public function setRefresh($refresh = true) + { + return $this->setParam('_refresh', (bool) $refresh); + } + + /** + * @return bool + */ + public function getRefresh() + { + return $this->getParam('_refresh'); + } + + /** + * @return bool + */ + public function hasRefresh() + { + return $this->hasParam('_refresh'); + } + + /** + * @param string $timeout + * @return \Elastica\Document + */ + public function setTimeout($timeout) + { + return $this->setParam('_timeout', $timeout); + } + + /** + * @return bool + */ + public function getTimeout() + { + return $this->getParam('_timeout'); + } + + /** + * @return string + */ + public function hasTimeout() + { + return $this->hasParam('_timeout'); + } + + /** + * @param string $timeout + * @return \Elastica\Document + */ + public function setConsistency($timeout) + { + return $this->setParam('_consistency', $timeout); + } + + /** + * @return string + */ + public function getConsistency() + { + return $this->getParam('_consistency'); + } + + /** + * @return string + */ + public function hasConsistency() + { + return $this->hasParam('_consistency'); + } + + /** + * @param string $timeout + * @return \Elastica\Document + */ + public function setReplication($timeout) + { + return $this->setParam('_replication', $timeout); + } + + /** + * @return string + */ + public function getReplication() + { + return $this->getParam('_replication'); + } + + /** + * @return bool + */ + public function hasReplication() + { + return $this->hasParam('_replication'); + } + + /** + * @param \Elastica\Document|array $data + * @return \Elastica\Document + */ + public function setUpsert($data) + { + $document = Document::create($data); + $this->_upsert = $document; + + return $this; + } + + /** + * @return \Elastica\Document + */ + public function getUpsert() + { + return $this->_upsert; + } + + /** + * @return bool + */ + public function hasUpsert() + { + return null !== $this->_upsert; + } + + /** + * @param array $fields if empty array all options will be returned, field names can be either with underscored either without, i.e. _percolate, routing + * @param bool $withUnderscore should option keys contain underscore prefix + * @return array + */ + public function getOptions(array $fields = array(), $withUnderscore = false) + { + if (!empty($fields)) { + $data = array(); + foreach ($fields as $field) { + $key = '_' . ltrim($field, '_'); + if ($this->hasParam($key) && '' !== (string) $this->getParam($key)) { + $data[$key] = $this->getParam($key); + } + } + } else { + $data = $this->getParams(); + } + if (!$withUnderscore) { + foreach ($data as $key => $value) { + $data[ltrim($key, '_')] = $value; + unset($data[$key]); + } + } + return $data; + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/AbstractAggregation.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/AbstractAggregation.php new file mode 100644 index 00000000..5ad5b17e --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/AbstractAggregation.php @@ -0,0 +1,88 @@ +<?php + +namespace Elastica\Aggregation; + +use Elastica\Param; +use Elastica\Exception\InvalidException; + +abstract class AbstractAggregation extends Param +{ + /** + * The name of this aggregation + * @var string + */ + protected $_name; + + /** + * Subaggregations belonging to this aggregation + * @var array + */ + protected $_aggs = array(); + + /** + * @param string $name the name of this aggregation + */ + public function __construct($name) + { + $this->setName($name); + } + + /** + * Set the name of this aggregation + * @param string $name + */ + public function setName($name) + { + $this->_name = $name; + } + + /** + * Retrieve the name of this aggregation + * @return string + */ + public function getName() + { + return $this->_name; + } + + /** + * Retrieve all subaggregations belonging to this aggregation + * @return array + */ + public function getAggs() + { + return $this->_aggs; + } + + /** + * Add a sub-aggregation + * @param AbstractAggregation $aggregation + * @throws \Elastica\Exception\InvalidException + * @return AbstractAggregation + */ + public function addAggregation(AbstractAggregation $aggregation) + { + if(is_a($aggregation, 'Elastica\Aggregation\GlobalAggregation')) { + throw new InvalidException('Global aggregators can only be placed as top level aggregators'); + } + + $this->_aggs[$aggregation->getName()] = $aggregation->toArray(); + return $this; + } + + /** + * @return array + */ + public function toArray() + { + $array = parent::toArray(); + if (array_key_exists('global_aggregation', $array)) { + // compensate for class name GlobalAggregation + $array = array('global' => new \stdClass); + } + if (sizeof($this->_aggs)) { + $array['aggs'] = $this->_aggs; + } + return $array; + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/AbstractSimpleAggregation.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/AbstractSimpleAggregation.php new file mode 100644 index 00000000..af7c1940 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/AbstractSimpleAggregation.php @@ -0,0 +1,33 @@ +<?php + +namespace Elastica\Aggregation; + + +use Elastica\Script; + +abstract class AbstractSimpleAggregation extends AbstractAggregation +{ + /** + * Set the field for this aggregation + * @param string $field the name of the document field on which to perform this aggregation + * @return AbstractSimpleAggregation + */ + public function setField($field) + { + return $this->setParam('field', $field); + } + + /** + * Set a script for this aggregation + * @param string|Script $script + * @return AbstractSimpleAggregation + */ + public function setScript($script) + { + if ($script instanceof Script) { + $this->setParam('params', $script->getParams()); + $script = $script->getScript(); + } + return $this->setParam('script', $script); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/Avg.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Avg.php new file mode 100644 index 00000000..0d601910 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Avg.php @@ -0,0 +1,14 @@ +<?php + +namespace Elastica\Aggregation; + + +/** + * Class Avg + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-metrics-avg-aggregation.html + */ +class Avg extends AbstractSimpleAggregation +{ + +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/Cardinality.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Cardinality.php new file mode 100644 index 00000000..061ddafa --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Cardinality.php @@ -0,0 +1,14 @@ +<?php + +namespace Elastica\Aggregation; + + +/** + * Class Cardinality + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations-metrics-cardinality-aggregation.html + */ +class Cardinality extends AbstractSimpleAggregation +{ + +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/DateHistogram.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/DateHistogram.php new file mode 100644 index 00000000..889fa429 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/DateHistogram.php @@ -0,0 +1,82 @@ +<?php + +namespace Elastica\Aggregation; + +/** + * Class DateHistogram + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-bucket-datehistogram-aggregation.html + */ +class DateHistogram extends Histogram +{ + /** + * Set pre-rounding based on interval + * @param string $preZone + * @return DateHistogram + */ + public function setPreZone($preZone) + { + return $this->setParam("pre_zone", $preZone); + } + + /** + * Set post-rounding based on interval + * @param string $postZone + * @return DateHistogram + */ + public function setPostZone($postZone) + { + return $this->setParam("post_zone", $postZone); + } + + /** + * Set pre-zone adjustment for larger time intervals (day and above) + * @param string $adjust + * @return DateHistogram + */ + public function setPreZoneAdjustLargeInterval($adjust) + { + return $this->setParam("pre_zone_adjust_large_interval", $adjust); + } + + /** + * Adjust for granularity of date data + * @param int $factor set to 1000 if date is stored in seconds rather than milliseconds + * @return DateHistogram + */ + public function setFactor($factor) + { + return $this->setParam("factor", $factor); + } + + /** + * Set the offset for pre-rounding + * @param string $offset "1d", for example + * @return DateHistogram + */ + public function setPreOffset($offset) + { + return $this->setParam("pre_offset", $offset); + } + + /** + * Set the offset for post-rounding + * @param string $offset "1d", for example + * @return DateHistogram + */ + public function setPostOffset($offset) + { + return $this->setParam("post_offset", $offset); + } + + /** + * Set the format for returned bucket key_as_string values + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-bucket-daterange-aggregation.html#date-format-pattern + * @param string $format see link for formatting options + * @return DateHistogram + */ + public function setFormat($format) + { + return $this->setParam("format", $format); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/DateRange.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/DateRange.php new file mode 100644 index 00000000..37aca87b --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/DateRange.php @@ -0,0 +1,21 @@ +<?php + +namespace Elastica\Aggregation; + +/** + * Class DateRange + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-bucket-daterange-aggregation.html + */ +class DateRange extends Range +{ + /** + * Set the formatting for the returned date values + * @param string $format see documentation for formatting options + * @return Range + */ + public function setFormat($format) + { + return $this->setParam('format', $format); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/ExtendedStats.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/ExtendedStats.php new file mode 100644 index 00000000..4aef8a32 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/ExtendedStats.php @@ -0,0 +1,13 @@ +<?php + +namespace Elastica\Aggregation; + +/** + * Class ExtendedStats + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-metrics-extendedstats-aggregation.html + */ +class ExtendedStats extends AbstractSimpleAggregation +{ + +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/Filter.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Filter.php new file mode 100644 index 00000000..c2326ffe --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Filter.php @@ -0,0 +1,41 @@ +<?php + +namespace Elastica\Aggregation; + + +use Elastica\Filter\AbstractFilter; + +/** + * Class Filter + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-bucket-filter-aggregation.html + */ +class Filter extends AbstractAggregation +{ + /** + * Set the filter for this aggregation + * @param AbstractFilter $filter + * @return Filter + */ + public function setFilter(AbstractFilter $filter) + { + return $this->setParam("filter", $filter->toArray()); + } + + /** + * @return array + */ + public function toArray() + { + $array = array( + "filter" => $this->getParam("filter") + ); + + if($this->_aggs) + { + $array['aggs'] = $this->_aggs; + } + + return $array; + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/GeoDistance.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/GeoDistance.php new file mode 100644 index 00000000..76c871ea --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/GeoDistance.php @@ -0,0 +1,90 @@ +<?php + +namespace Elastica\Aggregation; + +use Elastica\Exception\InvalidException; + +/** + * Class GeoDistance + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-bucket-geodistance-aggregation.html + */ +class GeoDistance extends AbstractAggregation +{ + const DISTANCE_TYPE_SLOPPY_ARC = "sloppy_arc"; + const DISTANCE_TYPE_ARC = "arc"; + const DISTANCE_TYPE_PLANE = "plane"; + + /** + * @param string $name the name if this aggregation + * @param string $field the field on which to perform this aggregation + * @param string|array $origin the point from which distances will be calculated + */ + public function __construct($name, $field, $origin) + { + parent::__construct($name); + $this->setField($field)->setOrigin($origin); + } + + /** + * Set the field for this aggregation + * @param string $field the name of the document field on which to perform this aggregation + * @return GeoDistance + */ + public function setField($field) + { + return $this->setParam('field', $field); + } + + /** + * Set the origin point from which distances will be calculated + * @param string|array $origin valid formats are array("lat" => 52.3760, "lon" => 4.894), "52.3760, 4.894", and array(4.894, 52.3760) + * @return GeoDistance + */ + public function setOrigin($origin) + { + return $this->setParam("origin", $origin); + } + + /** + * Add a distance range to this aggregation + * @param int $fromValue a distance + * @param int $toValue a distance + * @return GeoDistance + * @throws \Elastica\Exception\InvalidException + */ + public function addRange($fromValue = null, $toValue = null) + { + if (is_null($fromValue) && is_null($toValue)) { + throw new InvalidException("Either fromValue or toValue must be set. Both cannot be null."); + } + $range = array(); + if (!is_null($fromValue)) { + $range['from'] = $fromValue; + } + if (!is_null($toValue)) { + $range['to'] = $toValue; + } + return $this->addParam("ranges", $range); + } + + /** + * Set the unit of distance measure for this aggregation + * @param string $unit defaults to km + * @return GeoDistance + */ + public function setUnit($unit) + { + return $this->setParam("unit", $unit); + } + + /** + * Set the method by which distances will be calculated + * @param string $distanceType see DISTANCE_TYPE_* constants for options. Defaults to sloppy_arc. + * @return GeoDistance + */ + public function setDistanceType($distanceType) + { + return $this->setParam("distance_type", $distanceType); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/GeohashGrid.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/GeohashGrid.php new file mode 100644 index 00000000..840198c3 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/GeohashGrid.php @@ -0,0 +1,61 @@ +<?php + +namespace Elastica\Aggregation; + +/** + * Class GeohashGrid + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-bucket-geohashgrid-aggregation.html + */ +class GeohashGrid extends AbstractAggregation +{ + /** + * @param string $name the name of this aggregation + * @param string $field the field on which to perform this aggregation + */ + public function __construct($name, $field) + { + parent::__construct($name); + $this->setField($field); + } + + /** + * Set the field for this aggregation + * @param string $field the name of the document field on which to perform this aggregation + * @return GeohashGrid + */ + public function setField($field) + { + return $this->setParam('field', $field); + } + + /** + * Set the precision for this aggregation + * @param int $precision an integer between 1 and 12, inclusive. Defaults to 5. + * @return GeohashGrid + */ + public function setPrecision($precision) + { + return $this->setParam("precision", $precision); + } + + /** + * Set the maximum number of buckets to return + * @param int $size defaults to 10,000 + * @return GeohashGrid + */ + public function setSize($size) + { + return $this->setParam("size", $size); + } + + /** + * Set the number of results returned from each shard + * @param int $shardSize + * @return GeohashGrid + */ + public function setShardSize($shardSize) + { + return $this->setParam("shard_size", $shardSize); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/GlobalAggregation.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/GlobalAggregation.php new file mode 100644 index 00000000..72b56880 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/GlobalAggregation.php @@ -0,0 +1,13 @@ +<?php + +namespace Elastica\Aggregation; + +/** + * Class GlobalAggregation + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-bucket-global-aggregation.html + */ +class GlobalAggregation extends AbstractAggregation +{ + +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/Histogram.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Histogram.php new file mode 100644 index 00000000..26fa7c44 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Histogram.php @@ -0,0 +1,55 @@ +<?php + +namespace Elastica\Aggregation; + +/** + * Class Histogram + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-bucket-histogram-aggregation.html + */ +class Histogram extends AbstractSimpleAggregation +{ + /** + * @param string $name the name of this aggregation + * @param string $field the name of the field on which to perform the aggregation + * @param int $interval the interval by which documents will be bucketed + */ + public function __construct($name, $field, $interval) + { + parent::__construct($name); + $this->setField($field); + $this->setInterval($interval); + } + + + /** + * Set the interval by which documents will be bucketed + * @param int $interval + * @return Histogram + */ + public function setInterval($interval) + { + return $this->setParam("interval", $interval); + } + + /** + * Set the bucket sort order + * @param string $order "_count", "_term", or the name of a sub-aggregation or sub-aggregation response field + * @param string $direction "asc" or "desc" + * @return Histogram + */ + public function setOrder($order, $direction) + { + return $this->setParam("order", array($order => $direction)); + } + + /** + * Set the minimum number of documents which must fall into a bucket in order for the bucket to be returned + * @param int $count set to 0 to include empty buckets + * @return Histogram + */ + public function setMinimumDocumentCount($count) + { + return $this->setParam("min_doc_count", $count); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/IpRange.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/IpRange.php new file mode 100644 index 00000000..18e60bfb --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/IpRange.php @@ -0,0 +1,66 @@ +<?php + +namespace Elastica\Aggregation; + + +use Elastica\Exception\InvalidException; + +/** + * Class IpRange + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-bucket-iprange-aggregation.html + */ +class IpRange extends AbstractAggregation +{ + /** + * @param string $name the name of this aggregation + * @param string $field the field on which to perform this aggregation + */ + public function __construct($name, $field) + { + parent::__construct($name); + $this->setField($field); + } + + /** + * Set the field for this aggregation + * @param string $field the name of the document field on which to perform this aggregation + * @return IpRange + */ + public function setField($field) + { + return $this->setParam('field', $field); + } + + /** + * Add an ip range to this aggregation + * @param string $fromValue a valid ipv4 address. Low end of this range, exclusive (greater than) + * @param string $toValue a valid ipv4 address. High end of this range, exclusive (less than) + * @return IpRange + * @throws \Elastica\Exception\InvalidException + */ + public function addRange($fromValue = null, $toValue = null) + { + if (is_null($fromValue) && is_null($toValue)) { + throw new InvalidException("Either fromValue or toValue must be set. Both cannot be null."); + } + $range = array(); + if (!is_null($fromValue)) { + $range['from'] = $fromValue; + } + if (!is_null($toValue)) { + $range['to'] = $toValue; + } + return $this->addParam('ranges', $range); + } + + /** + * Add an ip range in the form of a CIDR mask + * @param string $mask a valid CIDR mask + * @return IpRange + */ + public function addMaskRange($mask) + { + return $this->addParam("ranges", array("mask" => $mask)); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/Max.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Max.php new file mode 100644 index 00000000..25031b04 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Max.php @@ -0,0 +1,13 @@ +<?php + +namespace Elastica\Aggregation; + +/** + * Class Max + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-metrics-max-aggregation.html + */ +class Max extends AbstractSimpleAggregation +{ + +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/Min.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Min.php new file mode 100644 index 00000000..60aabb56 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Min.php @@ -0,0 +1,13 @@ +<?php + +namespace Elastica\Aggregation; + +/** + * Class Min + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-metrics-min-aggregation.html + */ +class Min extends AbstractSimpleAggregation +{ + +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/Missing.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Missing.php new file mode 100644 index 00000000..b882aba0 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Missing.php @@ -0,0 +1,31 @@ +<?php + +namespace Elastica\Aggregation; + +/** + * Class Missing + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-bucket-missing-aggregation.html + */ +class Missing extends AbstractAggregation +{ + /** + * @param string $name the name of this aggregation + * @param string $field the field on which to perform this aggregation + */ + public function __construct($name, $field) + { + parent::__construct($name); + $this->setField($field); + } + + /** + * Set the field for this aggregation + * @param string $field the name of the document field on which to perform this aggregation + * @return Missing + */ + public function setField($field) + { + return $this->setParam('field', $field); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/Nested.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Nested.php new file mode 100644 index 00000000..afbb8373 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Nested.php @@ -0,0 +1,31 @@ +<?php + +namespace Elastica\Aggregation; + +/** + * Class Nested + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-bucket-nested-aggregation.html + */ +class Nested extends AbstractAggregation +{ + /** + * @param string $name the name of this aggregation + * @param string $path the nested path for this aggregation + */ + public function __construct($name, $path) + { + parent::__construct($name); + $this->setPath($path); + } + + /** + * Set the nested path for this aggregation + * @param string $path + * @return Nested + */ + public function setPath($path) + { + return $this->setParam("path", $path); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/Range.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Range.php new file mode 100644 index 00000000..ab70c5e4 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Range.php @@ -0,0 +1,45 @@ +<?php +namespace Elastica\Aggregation; + + +use Elastica\Exception\InvalidException; + +/** + * Class Range + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-bucket-range-aggregation.html + */ +class Range extends AbstractSimpleAggregation +{ + /** + * Add a range to this aggregation + * @param int|float $fromValue low end of this range, exclusive (greater than) + * @param int|float $toValue high end of this range, exclusive (less than) + * @return Range + * @throws \Elastica\Exception\InvalidException + */ + public function addRange($fromValue = null, $toValue = null) + { + if (is_null($fromValue) && is_null($toValue)) { + throw new InvalidException("Either fromValue or toValue must be set. Both cannot be null."); + } + $range = array(); + if (!is_null($fromValue)) { + $range['from'] = $fromValue; + } + if (!is_null($toValue)) { + $range['to'] = $toValue; + } + return $this->addParam('ranges', $range); + } + + /** + * If set to true, a unique string key will be associated with each bucket, and ranges will be returned as an associative array + * @param bool $keyed + * @return Range + */ + public function setKeyedResponse($keyed = true) + { + return $this->setParam('keyed', (bool)$keyed); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/ReverseNested.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/ReverseNested.php new file mode 100644 index 00000000..d4056f13 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/ReverseNested.php @@ -0,0 +1,50 @@ +<?php + +namespace Elastica\Aggregation; + +/** + * Reversed Nested Aggregation + * + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations-bucket-reverse-nested-aggregation.html + */ +class ReverseNested extends AbstractAggregation +{ + /** + * @param string $name The name of this aggregation + * @param string $path Optional path to the nested object for this aggregation. Defaults to the root of the main document. + */ + public function __construct($name, $path = null) + { + parent::__construct($name); + + if ($path !== null) { + $this->setPath($path); + } + } + + /** + * Set the nested path for this aggregation + * + * @param string $path + * @return ReverseNested + */ + public function setPath($path) + { + return $this->setParam("path", $path); + } + + /** + * {@inheritDoc} + */ + public function toArray() + { + $array = parent::toArray(); + + // ensure we have an object for the reverse_nested key. + // if we don't have a path, then this would otherwise get encoded as an empty array, which is invalid. + $array['reverse_nested'] = (object)$array['reverse_nested']; + + return $array; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/Stats.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Stats.php new file mode 100644 index 00000000..18c903e9 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Stats.php @@ -0,0 +1,13 @@ +<?php + +namespace Elastica\Aggregation; + +/** + * Class Stats + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-metrics-stats-aggregation.html + */ +class Stats extends AbstractSimpleAggregation +{ + +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/Sum.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Sum.php new file mode 100644 index 00000000..4d1ef4de --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Sum.php @@ -0,0 +1,13 @@ +<?php + +namespace Elastica\Aggregation; + +/** + * Class Sum + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-metrics-sum-aggregation.html + */ +class Sum extends AbstractSimpleAggregation +{ + +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/Terms.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Terms.php new file mode 100644 index 00000000..9ede855c --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/Terms.php @@ -0,0 +1,97 @@ +<?php + +namespace Elastica\Aggregation; + +/** + * Class Terms + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-bucket-terms-aggregation.html + */ +class Terms extends AbstractSimpleAggregation +{ + /** + * Set the bucket sort order + * @param string $order "_count", "_term", or the name of a sub-aggregation or sub-aggregation response field + * @param string $direction "asc" or "desc" + * @return Terms + */ + public function setOrder($order, $direction) + { + return $this->setParam("order", array($order => $direction)); + } + + /** + * Set the minimum number of documents in which a term must appear in order to be returned in a bucket + * @param int $count + * @return Terms + */ + public function setMinimumDocumentCount($count) + { + return $this->setParam("min_doc_count", $count); + } + + /** + * Filter documents to include based on a regular expression + * @param string $pattern a regular expression + * @param string $flags Java Pattern flags + * @return Terms + */ + public function setInclude($pattern, $flags = null) + { + if (is_null($flags)) { + return $this->setParam("include", $pattern); + } + return $this->setParam("include", array( + "pattern" => $pattern, + "flags" => $flags + )); + } + + /** + * Filter documents to exclude based on a regular expression + * @param string $pattern a regular expression + * @param string $flags Java Pattern flags + * @return Terms + */ + public function setExclude($pattern, $flags = null) + { + if (is_null($flags)) { + return $this->setParam("exclude", $pattern); + } + return $this->setParam("exclude", array( + "pattern" => $pattern, + "flags" => $flags + )); + } + + /** + * Sets the amount of terms to be returned. + * @param int $size The amount of terms to be returned. + * @return \Elastica\Aggregation\Terms + */ + public function setSize($size) + { + return $this->setParam('size', $size); + } + + /** + * Sets how many terms the coordinating node will request from each shard. + * @param int $shard_size The amount of terms to be returned. + * @return \Elastica\Aggregation\Terms + */ + public function setShardSize($shard_size) + { + return $this->setParam('shard_size', $shard_size); + } + + /** + * Instruct Elasticsearch to use direct field data or ordinals of the field values to execute this aggregation. + * The execution hint will be ignored if it is not applicable. + * @param string $hint map or ordinals + * @return Terms + */ + public function setExecutionHint($hint) + { + return $this->setParam("execution_hint", $hint); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Aggregation/ValueCount.php b/vendor/ruflin/elastica/lib/Elastica/Aggregation/ValueCount.php new file mode 100644 index 00000000..36fb2a2c --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Aggregation/ValueCount.php @@ -0,0 +1,31 @@ +<?php + +namespace Elastica\Aggregation; + +/** + * Class ValueCount + * @package Elastica\Aggregation + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-aggregations-metrics-valuecount-aggregation.html + */ +class ValueCount extends AbstractAggregation +{ + /** + * @param string $name the name of this aggregation + * @param string $field the field on which to perform this aggregation + */ + public function __construct($name, $field) + { + parent::__construct($name); + $this->setField($field); + } + + /** + * Set the field for this aggregation + * @param string $field the name of the document field on which to perform this aggregation + * @return ValueCount + */ + public function setField($field) + { + return $this->setParam('field', $field); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Bulk.php b/vendor/ruflin/elastica/lib/Elastica/Bulk.php new file mode 100644 index 00000000..439fa566 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Bulk.php @@ -0,0 +1,423 @@ +<?php + +namespace Elastica; + +use Elastica\Document; +use Elastica\Exception\Bulk\ResponseException as BulkResponseException; +use Elastica\Exception\Bulk\UdpException; +use Elastica\Exception\InvalidException; +use Elastica\Request; +use Elastica\Response; +use Elastica\Client; +use Elastica\Index; +use Elastica\Type; +use Elastica\Bulk\Action; +use Elastica\Bulk\Action\AbstractDocument as AbstractDocumentAction; +use Elastica\Bulk\ResponseSet; +use Elastica\Bulk\Response as BulkResponse; + +class Bulk +{ + const DELIMITER = "\n"; + + const UDP_DEFAULT_HOST = 'localhost'; + const UDP_DEFAULT_PORT = 9700; + + /** + * @var \Elastica\Client + */ + protected $_client; + + /** + * @var \Elastica\Bulk\Action[] + */ + protected $_actions = array(); + + /** + * @var string + */ + protected $_index = ''; + + /** + * @var string + */ + protected $_type = ''; + + /** + * @var array request parameters to the bulk api + */ + protected $_requestParams = array(); + + /** + * @param \Elastica\Client $client + */ + public function __construct(Client $client) + { + $this->_client = $client; + } + + /** + * @param string|\Elastica\Index $index + * @return \Elastica\Bulk + */ + public function setIndex($index) + { + if ($index instanceof Index) { + $index = $index->getName(); + } + + $this->_index = (string) $index; + + return $this; + } + + /** + * @return string + */ + public function getIndex() + { + return $this->_index; + } + + /** + * @return bool + */ + public function hasIndex() + { + return '' !== $this->getIndex(); + } + + /** + * @param string|\Elastica\Type $type + * @return \Elastica\Bulk + */ + public function setType($type) + { + if ($type instanceof Type) { + $this->setIndex($type->getIndex()->getName()); + $type = $type->getName(); + } + + $this->_type = (string) $type; + + return $this; + } + + /** + * @return string + */ + public function getType() + { + return $this->_type; + } + + /** + * @return bool + */ + public function hasType() + { + return '' !== $this->_type; + } + + /** + * @return string + */ + public function getPath() + { + $path = ''; + if ($this->hasIndex()) { + $path .= $this->getIndex() . '/'; + if ($this->hasType()) { + $path .= $this->getType() . '/'; + } + } + $path .= '_bulk'; + return $path; + } + + /** + * @param \Elastica\Bulk\Action $action + * @return \Elastica\Bulk + */ + public function addAction(Action $action) + { + $this->_actions[] = $action; + return $this; + } + + /** + * @param \Elastica\Bulk\Action[] $actions + * @return \Elastica\Bulk + */ + public function addActions(array $actions) + { + foreach ($actions as $action) { + $this->addAction($action); + } + + return $this; + } + + /** + * @return \Elastica\Bulk\Action[] + */ + public function getActions() + { + return $this->_actions; + } + + /** + * @param \Elastica\Document $document + * @param string $opType + * @return \Elastica\Bulk + */ + public function addDocument(Document $document, $opType = null) + { + $action = AbstractDocumentAction::create($document, $opType); + + return $this->addAction($action); + } + + /** + * @param \Elastica\Document[] $documents + * @param string $opType + * @return \Elastica\Bulk + */ + public function addDocuments(array $documents, $opType = null) + { + foreach ($documents as $document) { + $this->addDocument($document, $opType); + } + + return $this; + } + + /** + * @param \Elastica\Script $data + * @param string $opType + * @return \Elastica\Bulk + */ + public function addScript(Script $script, $opType = null) + { + $action = AbstractDocumentAction::create($script, $opType); + + return $this->addAction($action); + } + + /** + * @param \Elastica\Document[] $scripts + * @param string $opType + * @return \Elastica\Bulk + */ + public function addScripts(array $scripts, $opType = null) + { + foreach ($scripts as $document) { + $this->addScript($document, $opType); + } + + return $this; + } + + /** + * @param \Elastica\Script|\Elastica\Document\array $data + * @param string $opType + * @return \Elastica\Bulk + */ + public function addData($data, $opType = null) + { + if(!is_array($data)){ + $data = array($data); + } + + foreach ($data as $actionData){ + + if ($actionData instanceOf Script) { + $this->addScript($actionData, $opType); + }else if ($actionData instanceof Document) { + $this->addDocument($actionData, $opType); + }else{ + throw new \InvalidArgumentException("Data should be a Document, a Script or an array containing Documents and/or Scripts"); + } + } + + return $this; + } + + /** + * @param array $data + * @return \Elastica\Bulk + * @throws \Elastica\Exception\InvalidException + */ + public function addRawData(array $data) + { + foreach ($data as $row) { + if (is_array($row)) { + $opType = key($row); + $metadata = reset($row); + if (Action::isValidOpType($opType)) { + // add previous action + if (isset($action)) { + $this->addAction($action); + } + $action = new Action($opType, $metadata); + } elseif (isset($action)) { + $action->setSource($row); + $this->addAction($action); + $action = null; + } else { + throw new InvalidException('Invalid bulk data, source must follow action metadata'); + } + } else { + throw new InvalidException('Invalid bulk data, should be array of array, Document or Bulk/Action'); + } + } + + // add last action if available + if (isset($action)) { + $this->addAction($action); + } + + return $this; + } + + /** + * Set a url parameter on the request bulk request. + * @var string $name name of the parameter + * @var string $value value of the parameter + */ + public function setRequestParam($name, $value) { + $this->_requestParams[ $name ] = $value; + } + + /** + * Set the amount of time that the request will wait the shards to come on line. + * Requires Elasticsearch version >= 0.90.8. + * @var string $time timeout in Elasticsearch time format + */ + public function setShardTimeout($time) { + $this->setRequestParam( 'timeout', $time ); + } + + /** + * @return string + */ + public function __toString() + { + return $this->toString(); + } + + /** + * @return string + */ + public function toString() + { + $data = ''; + foreach ($this->getActions() as $action) { + $data.= $action->toString(); + } + return $data; + } + + /** + * @return array + */ + public function toArray() + { + $data = array(); + foreach ($this->getActions() as $action) { + foreach ($action->toArray() as $row) { + $data[] = $row; + } + } + return $data; + } + + /** + * @return \Elastica\Bulk\ResponseSet + */ + public function send() + { + $path = $this->getPath(); + $data = $this->toString(); + + $response = $this->_client->request($path, Request::PUT, $data, $this->_requestParams); + + return $this->_processResponse($response); + } + + /** + * @param \Elastica\Response $response + * @throws Exception\Bulk\ResponseException + * @throws Exception\InvalidException + * @return \Elastica\Bulk\ResponseSet + */ + protected function _processResponse(Response $response) + { + $responseData = $response->getData(); + + $actions = $this->getActions(); + + $bulkResponses = array(); + + if (isset($responseData['items']) && is_array($responseData['items'])) { + foreach ($responseData['items'] as $key => $item) { + + if (!isset($actions[$key])) { + throw new InvalidException('No response found for action #' . $key); + } + + $action = $actions[$key]; + + $opType = key($item); + $bulkResponseData = reset($item); + + if ($action instanceof AbstractDocumentAction) { + $data = $action->getData(); + if ($data instanceof Document && $data->isAutoPopulate() + || $this->_client->getConfigValue(array('document', 'autoPopulate'), false) + ) { + if (!$data->hasId() && isset($bulkResponseData['_id'])) { + $data->setId($bulkResponseData['_id']); + } + if (isset($bulkResponseData['_version'])) { + $data->setVersion($bulkResponseData['_version']); + } + } + } + + $bulkResponses[] = new BulkResponse($bulkResponseData, $action, $opType); + } + } + + $bulkResponseSet = new ResponseSet($response, $bulkResponses); + + if ($bulkResponseSet->hasError()) { + throw new BulkResponseException($bulkResponseSet); + } + + return $bulkResponseSet; + } + + /** + * @param string $host + * @param int $port + * @throws \Elastica\Exception\Bulk\UdpException + */ + public function sendUdp($host = null, $port = null) + { + if (null === $host) { + $host = $this->_client->getConfigValue(array('udp', 'host'), self::UDP_DEFAULT_HOST); + } + if (null === $port) { + $port = $this->_client->getConfigValue(array('udp', 'port'), self::UDP_DEFAULT_PORT); + } + + $message = $this->toString(); + $socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); + $result = socket_sendto($socket, $message, strlen($message), 0, $host, $port); + socket_close($socket); + if (false === $result) { + throw new UdpException('UDP request failed'); + } + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Bulk/Action.php b/vendor/ruflin/elastica/lib/Elastica/Bulk/Action.php new file mode 100644 index 00000000..7922ec13 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Bulk/Action.php @@ -0,0 +1,219 @@ +<?php + +namespace Elastica\Bulk; + +use Elastica\Bulk; +use Elastica\JSON; +use Elastica\Index; +use Elastica\Type; + +class Action +{ + const OP_TYPE_CREATE = 'create'; + const OP_TYPE_INDEX = 'index'; + const OP_TYPE_DELETE = 'delete'; + const OP_TYPE_UPDATE = 'update'; + + /** + * @var array + */ + public static $opTypes = array( + self::OP_TYPE_CREATE, + self::OP_TYPE_INDEX, + self::OP_TYPE_DELETE, + self::OP_TYPE_UPDATE + ); + + /** + * @var string + */ + protected $_opType; + + /** + * @var array + */ + protected $_metadata = array(); + + /** + * @var array + */ + protected $_source = array(); + + /** + * @param string $opType + * @param array $metadata + * @param array $source + */ + public function __construct($opType = self::OP_TYPE_INDEX, array $metadata = array(), array $source = array()) + { + $this->setOpType($opType); + $this->setMetadata($metadata); + $this->setSource($source); + } + + /** + * @param string $type + * @return \Elastica\Bulk\Action + */ + public function setOpType($type) + { + $this->_opType = $type; + + return $this; + } + + /** + * @return string + */ + public function getOpType() + { + return $this->_opType; + } + + /** + * @param array $metadata + * @return \Elastica\Bulk\Action + */ + public function setMetadata(array $metadata) + { + $this->_metadata = $metadata; + + return $this; + } + + /** + * @return array + */ + public function getMetadata() + { + return $this->_metadata; + } + + /** + * @return array + */ + public function getActionMetadata() + { + return array($this->_opType => $this->getMetadata()); + } + + /** + * @param array $source + * @return \Elastica\Bulk\Action + */ + public function setSource($source) + { + $this->_source = $source; + + return $this; + } + + /** + * @return array + */ + public function getSource() + { + return $this->_source; + } + + /** + * @return bool + */ + public function hasSource() + { + return !empty($this->_source); + } + + /** + * @param string|\Elastica\Index $index + * @return \Elastica\Bulk\Action + */ + public function setIndex($index) + { + if ($index instanceof Index) { + $index = $index->getName(); + } + $this->_metadata['_index'] = $index; + + return $this; + } + + /** + * @param string|\Elastica\Type $type + * @return \Elastica\Bulk\Action + */ + public function setType($type) + { + if ($type instanceof Type) { + $this->setIndex($type->getIndex()->getName()); + $type = $type->getName(); + } + $this->_metadata['_type'] = $type; + + return $this; + } + + /** + * @param string $id + * @return \Elastica\Bulk\Action + */ + public function setId($id) + { + $this->_metadata['_id'] = $id; + + return $this; + } + + /** + * @param string $routing + * @return \Elastica\Bulk\Action + */ + public function setRouting($routing) + { + $this->_metadata['_routing'] = $routing; + + return $this; + } + + /** + * @return array + */ + public function toArray() + { + $data[] = $this->getActionMetadata(); + if ($this->hasSource()) { + $data[] = $this->getSource(); + } + return $data; + } + + /** + * @return string + */ + public function toString() + { + $string = JSON::stringify($this->getActionMetadata(), JSON_FORCE_OBJECT) . Bulk::DELIMITER; + if ($this->hasSource()) { + $source = $this->getSource(); + if (is_string($source)) { + $string.= $source; + } elseif (is_array($source) && array_key_exists('doc', $source) && is_string($source['doc'])) { + $docAsUpsert = (isset($source['doc_as_upsert'])) ? ', "doc_as_upsert": '.$source['doc_as_upsert'] : ''; + $string.= '{"doc": '.$source['doc'].$docAsUpsert.'}'; + } else { + $string.= JSON::stringify($source, 'JSON_ELASTICSEARCH'); + } + $string.= Bulk::DELIMITER; + } + return $string; + } + + /** + * @param string $opType + * @return bool + */ + public static function isValidOpType($opType) + { + return in_array($opType, self::$opTypes); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Bulk/Action/AbstractDocument.php b/vendor/ruflin/elastica/lib/Elastica/Bulk/Action/AbstractDocument.php new file mode 100644 index 00000000..545e695c --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Bulk/Action/AbstractDocument.php @@ -0,0 +1,162 @@ +<?php + +namespace Elastica\Bulk\Action; + +use Elastica\AbstractUpdateAction; +use Elastica\Bulk\Action; +use Elastica\Document; +use Elastica\Script; + +abstract class AbstractDocument extends Action +{ + /** + * @var \Elastica\Document|\Elastica\Script + */ + protected $_data; + + /** + * @param \Elastica\Document|\Elastica\Script $document + */ + public function __construct($document) + { + $this->setData($document); + } + + /** + * @param \Elastica\Document $document + * @return \Elastica\Bulk\Action\AbstractDocument + */ + public function setDocument(Document $document) + { + $this->_data = $document; + + $metadata = $this->_getMetadata($document); + + $this->setMetadata($metadata); + + return $this; + } + + /** + * @param \Elastica\Script $script + * @return \Elastica\Bulk\Action\AbstractDocument + */ + public function setScript(Script $script) + { + if (!($this instanceof UpdateDocument)) { + throw new \BadMethodCallException("setScript() can only be used for UpdateDocument"); + } + + $this->_data = $script; + + $metadata = $this->_getMetadata($script); + $this->setMetadata($metadata); + + return $this; + } + + /** + * @param \Elastica\Script|\Elastica\Document $data + * @throws \InvalidArgumentException + * @return \Elastica\Bulk\Action\AbstractDocument + */ + public function setData($data) + { + if ($data instanceof Script) { + + $this->setScript($data); + + }else if ($data instanceof Document) { + + $this->setDocument($data); + + }else{ + throw new \InvalidArgumentException("Data should be a Document or a Script."); + } + + return $this; + } + + /** + * Note: This is for backwards compatibility. + * @return \Elastica\Document + */ + public function getDocument() + { + if ($this->_data instanceof Document) { + return $this->_data; + } + + return null; + } + + /** + * Note: This is for backwards compatibility. + * @return \Elastica\Script + */ + public function getScript() + { + if ($this->_data instanceof Script) { + return $this->_data; + } + + return null; + } + + /** + * @return \Elastica\Document|\Elastica\Script + */ + public function getData() + { + return $this->_data; + } + + /** + * @param \Elastica\AbstractUpdateAction $source + * @return array + */ + abstract protected function _getMetadata(AbstractUpdateAction $source); + + /** + * @param \Elastica\Document|\Elastica\Script $data + * @param string $opType + * @return \Elastica\Bulk\Action\AbstractDocument + */ + public static function create($data, $opType = null) + { + //Check type + if (!($data instanceof Document) && !($data instanceof Script)) { + throw new \InvalidArgumentException("The data needs to be a Document or a Script."); + } + + if (null === $opType && $data->hasOpType()) { + $opType = $data->getOpType(); + } + + //Check that scripts can only be used for updates + if ($data instanceof Script) { + if ($opType === null) { + $opType = self::OP_TYPE_UPDATE; + } else if ($opType != self::OP_TYPE_UPDATE) { + throw new \InvalidArgumentException("Scripts can only be used with the update operation type."); + } + } + + switch ($opType) { + case self::OP_TYPE_DELETE: + $action = new DeleteDocument($data); + break; + case self::OP_TYPE_CREATE: + $action = new CreateDocument($data); + break; + case self::OP_TYPE_UPDATE: + $action = new UpdateDocument($data); + break; + case self::OP_TYPE_INDEX: + default: + $action = new IndexDocument($data); + break; + } + return $action; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Bulk/Action/CreateDocument.php b/vendor/ruflin/elastica/lib/Elastica/Bulk/Action/CreateDocument.php new file mode 100644 index 00000000..ae868b49 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Bulk/Action/CreateDocument.php @@ -0,0 +1,11 @@ +<?php + +namespace Elastica\Bulk\Action; + +class CreateDocument extends IndexDocument +{ + /** + * @var string + */ + protected $_opType = self::OP_TYPE_CREATE; +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Bulk/Action/DeleteDocument.php b/vendor/ruflin/elastica/lib/Elastica/Bulk/Action/DeleteDocument.php new file mode 100644 index 00000000..572f80b6 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Bulk/Action/DeleteDocument.php @@ -0,0 +1,33 @@ +<?php + +namespace Elastica\Bulk\Action; + +use Elastica\AbstractUpdateAction; + +class DeleteDocument extends AbstractDocument +{ + /** + * @var string + */ + protected $_opType = self::OP_TYPE_DELETE; + + /** + * @param \Elastica\AbstractUpdateAction $action + * @return array + */ + protected function _getMetadata(AbstractUpdateAction $action) + { + $params = array( + 'index', + 'type', + 'id', + 'version', + 'version_type', + 'routing', + 'parent' + ); + $metadata = $action->getOptions($params, true); + + return $metadata; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Bulk/Action/IndexDocument.php b/vendor/ruflin/elastica/lib/Elastica/Bulk/Action/IndexDocument.php new file mode 100644 index 00000000..d405563e --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Bulk/Action/IndexDocument.php @@ -0,0 +1,52 @@ +<?php + +namespace Elastica\Bulk\Action; + +use Elastica\AbstractUpdateAction; +use Elastica\Bulk\Action; +use Elastica\Document; + +class IndexDocument extends AbstractDocument +{ + /** + * @var string + */ + protected $_opType = self::OP_TYPE_INDEX; + + /** + * @param \Elastica\Document $document + * @return \Elastica\Bulk\Action\IndexDocument + */ + public function setDocument(Document $document) + { + parent::setDocument($document); + + $this->setSource($document->getData()); + + return $this; + } + + /** + * @param \Elastica\AbstractUpdateAction $source + * @return array + */ + protected function _getMetadata(AbstractUpdateAction $action) + { + $params = array( + 'index', + 'type', + 'id', + 'version', + 'version_type', + 'routing', + 'percolate', + 'parent', + 'ttl', + 'timestamp', + 'retry_on_conflict', + ); + $metadata = $action->getOptions($params, true); + + return $metadata; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Bulk/Action/UpdateDocument.php b/vendor/ruflin/elastica/lib/Elastica/Bulk/Action/UpdateDocument.php new file mode 100644 index 00000000..4c1dbaa4 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Bulk/Action/UpdateDocument.php @@ -0,0 +1,69 @@ +<?php + +namespace Elastica\Bulk\Action; + +use Elastica\Document; +use Elastica\Script; + +/** + * @package Elastica\Bulk\Action + * @link http://www.elasticsearch.org/guide/reference/api/bulk/ + */ +class UpdateDocument extends IndexDocument +{ + /** + * @var string + */ + protected $_opType = self::OP_TYPE_UPDATE; + + /** + * Set the document for this bulk update action. + * @param \Elastica\Document $document + * @return \Elastica\Bulk\Action\UpdateDocument + */ + public function setDocument(Document $document) + { + parent::setDocument($document); + + $source = array('doc' => $document->getData()); + + if ($document->getDocAsUpsert()) { + $source['doc_as_upsert'] = true; + + }else if ($document->hasUpsert()) { + + $upsert = $document->getUpsert()->getData(); + + if (!empty($upsert)) { + $source['upsert'] = $upsert; + } + } + + $this->setSource($source); + + return $this; + } + + /** + * @param \Elastica\Script $script + * @return \Elastica\Bulk\Action\AbstractDocument + */ + public function setScript(Script $script) + { + parent::setScript($script); + + $source = $script->toArray(); + + if ($script->hasUpsert()) { + $upsert = $script->getUpsert()->getData(); + + if (!empty($upsert)) { + $source['upsert'] = $upsert; + } + } + + $this->setSource($source); + + return $this; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Bulk/Response.php b/vendor/ruflin/elastica/lib/Elastica/Bulk/Response.php new file mode 100644 index 00000000..5abd1850 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Bulk/Response.php @@ -0,0 +1,47 @@ +<?php + +namespace Elastica\Bulk; + +use Elastica\Response as BaseResponse; + +class Response extends BaseResponse +{ + /** + * @var \Elastica\Bulk\Action + */ + protected $_action; + + /** + * @var string + */ + protected $_opType; + + /** + * @param array|string $responseData + * @param \Elastica\Bulk\Action $action + * @param string $opType + */ + public function __construct($responseData, Action $action, $opType) + { + parent::__construct($responseData); + + $this->_action = $action; + $this->_opType = $opType; + } + + /** + * @return \Elastica\Bulk\Action + */ + public function getAction() + { + return $this->_action; + } + + /** + * @return string + */ + public function getOpType() + { + return $this->_opType; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Bulk/ResponseSet.php b/vendor/ruflin/elastica/lib/Elastica/Bulk/ResponseSet.php new file mode 100644 index 00000000..9fd835e4 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Bulk/ResponseSet.php @@ -0,0 +1,142 @@ +<?php + +namespace Elastica\Bulk; + +use Elastica\Response as BaseResponse; + +class ResponseSet extends BaseResponse implements \Iterator, \Countable +{ + /** + * @var \Elastica\Bulk\Response[] + */ + protected $_bulkResponses = array(); + + /** + * @var int + */ + protected $_position = 0; + + /** + * @param \Elastica\Response $response + * @param \Elastica\Bulk\Response[] $bulkResponses + */ + public function __construct(BaseResponse $response, array $bulkResponses) + { + parent::__construct($response->getData()); + + $this->_bulkResponses = $bulkResponses; + } + + /** + * @return \Elastica\Bulk\Response[] + */ + public function getBulkResponses() + { + return $this->_bulkResponses; + } + + /** + * Returns first found error + * + * @return string + */ + public function getError() + { + $error = ''; + + foreach ($this->getBulkResponses() as $bulkResponse) { + if ($bulkResponse->hasError()) { + $error = $bulkResponse->getError(); + break; + } + } + + return $error; + } + + /** + * @return bool + */ + public function isOk() + { + $return = true; + + foreach ($this->getBulkResponses() as $bulkResponse) { + if (!$bulkResponse->isOk()) { + $return = false; + break; + } + } + + return $return; + } + + /** + * @return bool + */ + public function hasError() + { + $return = false; + + foreach ($this->getBulkResponses() as $bulkResponse) { + if ($bulkResponse->hasError()) { + $return = true; + break; + } + } + + return $return; + } + + /** + * @return bool|\Elastica\Bulk\Response + */ + public function current() + { + if ($this->valid()) { + return $this->_bulkResponses[$this->key()]; + } else { + return false; + } + } + + /** + * + */ + public function next() + { + $this->_position++; + } + + /** + * @return int + */ + public function key() + { + return $this->_position; + } + + /** + * @return bool + */ + public function valid() + { + return isset($this->_bulkResponses[$this->key()]); + } + + /** + * + */ + public function rewind() + { + $this->_position = 0; + } + + /** + * @return int + */ + public function count() + { + return count($this->_bulkResponses); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Client.php b/vendor/ruflin/elastica/lib/Elastica/Client.php new file mode 100644 index 00000000..a5821180 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Client.php @@ -0,0 +1,691 @@ +<?php + +namespace Elastica; + +use Elastica\Bulk; +use Elastica\Bulk\Action; +use Elastica\Exception\ResponseException; +use Elastica\Exception\ClientException; +use Elastica\Exception\ConnectionException; +use Elastica\Exception\InvalidException; +use Elastica\Exception\RuntimeException; +use Psr\Log\LoggerInterface; + +/** + * Client to connect the the elasticsearch server + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class Client +{ + /** + * Config with defaults + * + * log: Set to true, to enable logging, set a string to log to a specific file + * retryOnConflict: Use in \Elastica\Client::updateDocument + * + * @var array + */ + protected $_config = array( + 'host' => null, + 'port' => null, + 'path' => null, + 'url' => null, + 'proxy' => null, + 'transport' => null, + 'persistent' => true, + 'timeout' => null, + 'connections' => array(), // host, port, path, timeout, transport, persistent, timeout, config -> (curl, headers, url) + 'roundRobin' => false, + 'log' => false, + 'retryOnConflict' => 0, + ); + + /** + * @var \Elastica\Connection[] List of connections + */ + protected $_connections = array(); + + /** + * @var callback + */ + protected $_callback = null; + + /** + * @var \Elastica\Request + */ + protected $_lastRequest; + + /** + * @var \Elastica\Response + */ + protected $_lastResponse; + + /** + * @var LoggerInterface + */ + protected $_logger = null; + + /** + * Creates a new Elastica client + * + * @param array $config OPTIONAL Additional config options + * @param callback $callback OPTIONAL Callback function which can be used to be notified about errors (for example connection down) + */ + public function __construct(array $config = array(), $callback = null) + { + $this->setConfig($config); + $this->_callback = $callback; + $this->_initConnections(); + } + + /** + * Inits the client connections + */ + protected function _initConnections() + { + $connections = $this->getConfig('connections'); + + foreach ($connections as $connection) { + $this->_connections[] = Connection::create($this->_prepareConnectionParams($connection)); + } + + if (isset($this->_config['servers'])) { + foreach ($this->getConfig('servers') as $server) { + $this->_connections[] = Connection::create($this->_prepareConnectionParams($server)); + } + } + + // If no connections set, create default connection + if (empty($this->_connections)) { + $this->_connections[] = Connection::create($this->_prepareConnectionParams($this->getConfig())); + } + } + + /** + * Creates a Connection params array from a Client or server config array. + * + * @param array $config + * @return array + */ + protected function _prepareConnectionParams(array $config) + { + $params = array(); + $params['config'] = array(); + foreach ($config as $key => $value) { + if (in_array($key, array('curl', 'headers', 'url'))) { + $params['config'][$key] = $value; + } else { + $params[$key] = $value; + } + } + + return $params; + } + + /** + * Sets specific config values (updates and keeps default values) + * + * @param array $config Params + * @return \Elastica\Client + */ + public function setConfig(array $config) + { + foreach ($config as $key => $value) { + $this->_config[$key] = $value; + } + + return $this; + } + + /** + * Returns a specific config key or the whole + * config array if not set + * + * @param string $key Config key + * @throws \Elastica\Exception\InvalidException + * @return array|string Config value + */ + public function getConfig($key = '') + { + if (empty($key)) { + return $this->_config; + } + + if (!array_key_exists($key, $this->_config)) { + throw new InvalidException('Config key is not set: ' . $key); + } + + return $this->_config[$key]; + } + + /** + * Sets / overwrites a specific config value + * + * @param string $key Key to set + * @param mixed $value Value + * @return \Elastica\Client Client object + */ + public function setConfigValue($key, $value) + { + return $this->setConfig(array($key => $value)); + } + + /** + * @param array|string $keys config key or path of config keys + * @param mixed $default default value will be returned if key was not found + * @return mixed + */ + public function getConfigValue($keys, $default = null) + { + $value = $this->_config; + foreach ((array) $keys as $key) { + if (isset($value[$key])) { + $value = $value[$key]; + } else { + return $default; + } + } + return $value; + } + + /** + * Returns the index for the given connection + * + * @param string $name Index name to create connection to + * @return \Elastica\Index Index for the given name + */ + public function getIndex($name) + { + return new Index($this, $name); + } + + /** + * Adds a HTTP Header + * + * @param string $header The HTTP Header + * @param string $headerValue The HTTP Header Value + * @throws \Elastica\Exception\InvalidException If $header or $headerValue is not a string + */ + public function addHeader($header, $headerValue) + { + if (is_string($header) && is_string($headerValue)) { + $this->_config['headers'][$header] = $headerValue; + } else { + throw new InvalidException('Header must be a string'); + } + } + + /** + * Remove a HTTP Header + * + * @param string $header The HTTP Header to remove + * @throws \Elastica\Exception\InvalidException IF $header is not a string + */ + public function removeHeader($header) + { + if (is_string($header)) { + if (array_key_exists($header, $this->_config['headers'])) { + unset($this->_config['headers'][$header]); + } + } else { + throw new InvalidException('Header must be a string'); + } + } + + /** + * Uses _bulk to send documents to the server + * + * Array of \Elastica\Document as input. Index and type has to be + * set inside the document, because for bulk settings documents, + * documents can belong to any type and index + * + * @param array|\Elastica\Document[] $docs Array of Elastica\Document + * @return \Elastica\Bulk\ResponseSet Response object + * @throws \Elastica\Exception\InvalidException If docs is empty + * @link http://www.elasticsearch.org/guide/reference/api/bulk.html + */ + public function updateDocuments(array $docs) { + if (empty($docs)) { + throw new InvalidException('Array has to consist of at least one element'); + } + + $bulk = new Bulk($this); + + $bulk->addDocuments($docs, \Elastica\Bulk\Action::OP_TYPE_UPDATE); + + return $bulk->send(); + } + + /** + * Uses _bulk to send documents to the server + * + * Array of \Elastica\Document as input. Index and type has to be + * set inside the document, because for bulk settings documents, + * documents can belong to any type and index + * + * @param array|\Elastica\Document[] $docs Array of Elastica\Document + * @return \Elastica\Bulk\ResponseSet Response object + * @throws \Elastica\Exception\InvalidException If docs is empty + * @link http://www.elasticsearch.org/guide/reference/api/bulk.html + */ + public function addDocuments(array $docs) + { + if (empty($docs)) { + throw new InvalidException('Array has to consist of at least one element'); + } + + $bulk = new Bulk($this); + + $bulk->addDocuments($docs); + + return $bulk->send(); + } + + /** + * Update document, using update script. Requires elasticsearch >= 0.19.0 + * + * @param int $id document id + * @param array|\Elastica\Script|\Elastica\Document $data raw data for request body + * @param string $index index to update + * @param string $type type of index to update + * @param array $options array of query params to use for query. For possible options check es api + * @return \Elastica\Response + * @link http://www.elasticsearch.org/guide/reference/api/update.html + */ + public function updateDocument($id, $data, $index, $type, array $options = array()) + { + $path = $index . '/' . $type . '/' . $id . '/_update'; + + if ($data instanceof Script) { + $requestData = $data->toArray(); + + } elseif ($data instanceof Document) { + + $requestData = array('doc' => $data->getData()); + + if ($data->getDocAsUpsert()) { + $requestData['doc_as_upsert'] = true; + } + + $docOptions = $data->getOptions( + array( + 'version', + 'version_type', + 'routing', + 'percolate', + 'parent', + 'fields', + 'retry_on_conflict', + 'consistency', + 'replication', + 'refresh', + 'timeout', + ) + ); + $options += $docOptions; + // set fields param to source only if options was not set before + if ($data instanceof Document && ($data->isAutoPopulate() + || $this->getConfigValue(array('document', 'autoPopulate'), false)) + && !isset($options['fields']) + ) { + $options['fields'] = '_source'; + } + } else { + $requestData = $data; + } + + //If an upsert document exists + if ($data instanceof Script || $data instanceof Document) { + + if ($data->hasUpsert()) { + $requestData['upsert'] = $data->getUpsert()->getData(); + } + } + + if (!isset($options['retry_on_conflict'])) { + $retryOnConflict = $this->getConfig("retryOnConflict"); + $options['retry_on_conflict'] = $retryOnConflict; + } + + $response = $this->request($path, Request::POST, $requestData, $options); + + if ($response->isOk() + && $data instanceof Document + && ($data->isAutoPopulate() || $this->getConfigValue(array('document', 'autoPopulate'), false)) + ) { + $responseData = $response->getData(); + if (isset($responseData['_version'])) { + $data->setVersion($responseData['_version']); + } + if (isset($options['fields'])) { + $this->_populateDocumentFieldsFromResponse($response, $data, $options['fields']); + } + } + + return $response; + } + + /** + * @param \Elastica\Response $response + * @param \Elastica\Document $document + * @param string $fields Array of field names to be populated or '_source' if whole document data should be updated + */ + protected function _populateDocumentFieldsFromResponse(Response $response, Document $document, $fields) + { + $responseData = $response->getData(); + if ('_source' == $fields) { + if (isset($responseData['get']['_source']) && is_array($responseData['get']['_source'])) { + $document->setData($responseData['get']['_source']); + } + } else { + $keys = explode(',', $fields); + $data = $document->getData(); + foreach ($keys as $key) { + if (isset($responseData['get']['fields'][$key])) { + $data[$key] = $responseData['get']['fields'][$key]; + } elseif (isset($data[$key])) { + unset($data[$key]); + } + } + $document->setData($data); + } + } + + /** + * Bulk deletes documents + * + * @param array|\Elastica\Document[] $docs + * @return \Elastica\Bulk\ResponseSet + * @throws \Elastica\Exception\InvalidException + */ + public function deleteDocuments(array $docs) + { + if (empty($docs)) { + throw new InvalidException('Array has to consist of at least one element'); + } + + $bulk = new Bulk($this); + $bulk->addDocuments($docs, Action::OP_TYPE_DELETE); + + return $bulk->send(); + } + + /** + * Returns the status object for all indices + * + * @return \Elastica\Status Status object + */ + public function getStatus() + { + return new Status($this); + } + + /** + * Returns the current cluster + * + * @return \Elastica\Cluster Cluster object + */ + public function getCluster() + { + return new Cluster($this); + } + + /** + * @param \Elastica\Connection $connection + * @return \Elastica\Client + */ + public function addConnection(Connection $connection) + { + $this->_connections[] = $connection; + + return $this; + } + + /** + * Determines whether a valid connection is available for use. + * + * @return bool + */ + public function hasConnection() + { + foreach ($this->_connections as $connection) + { + if ($connection->isEnabled()) + { + return true; + } + } + + return false; + } + + /** + * @throws \Elastica\Exception\ClientException + * @return \Elastica\Connection + */ + public function getConnection() + { + $enabledConnection = null; + + foreach ($this->_connections as $connection) { + if ($connection->isEnabled()) { + $enabledConnection = $connection; + break; + } + } + + if (empty($enabledConnection)) { + throw new ClientException('No enabled connection'); + } + + return $enabledConnection; + } + + /** + * @return \Elastica\Connection[] + */ + public function getConnections() + { + return $this->_connections; + } + + /** + * @param \Elastica\Connection[] $connections + * @return \Elastica\Client + */ + public function setConnections(array $connections) + { + $this->_connections = $connections; + + return $this; + } + + /** + * Deletes documents with the given ids, index, type from the index + * + * @param array $ids Document ids + * @param string|\Elastica\Index $index Index name + * @param string|\Elastica\Type $type Type of documents + * @param string|false $routing Optional routing key for all ids + * @throws \Elastica\Exception\InvalidException + * @return \Elastica\Bulk\ResponseSet Response object + * @link http://www.elasticsearch.org/guide/reference/api/bulk.html + */ + public function deleteIds(array $ids, $index, $type, $routing = false) + { + if (empty($ids)) { + throw new InvalidException('Array has to consist of at least one id'); + } + + $bulk = new Bulk($this); + $bulk->setIndex($index); + $bulk->setType($type); + + foreach ($ids as $id) { + $action = new Action(Action::OP_TYPE_DELETE); + $action->setId($id); + + if (!empty($routing)) { + $action->setRouting($routing); + } + + $bulk->addAction($action); + } + + return $bulk->send(); + } + + /** + * Bulk operation + * + * Every entry in the params array has to exactly on array + * of the bulk operation. An example param array would be: + * + * array( + * array('index' => array('_index' => 'test', '_type' => 'user', '_id' => '1')), + * array('user' => array('name' => 'hans')), + * array('delete' => array('_index' => 'test', '_type' => 'user', '_id' => '2')) + * ); + * + * @param array $params Parameter array + * @throws \Elastica\Exception\ResponseException + * @throws \Elastica\Exception\InvalidException + * @return \Elastica\Bulk\ResponseSet Response object + * @link http://www.elasticsearch.org/guide/reference/api/bulk.html + */ + public function bulk(array $params) + { + if (empty($params)) { + throw new InvalidException('Array has to consist of at least one param'); + } + + $bulk = new Bulk($this); + + $bulk->addRawData($params); + + return $bulk->send(); + } + + /** + * Makes calls to the elasticsearch server based on this index + * + * It's possible to make any REST query directly over this method + * + * @param string $path Path to call + * @param string $method Rest method to use (GET, POST, DELETE, PUT) + * @param array $data OPTIONAL Arguments as array + * @param array $query OPTIONAL Query params + * @throws Exception\ConnectionException|\Exception + * @return \Elastica\Response Response object + */ + public function request($path, $method = Request::GET, $data = array(), array $query = array()) + { + $connection = $this->getConnection(); + try { + $request = new Request($path, $method, $data, $query, $connection); + + $this->_log($request); + + $response = $request->send(); + + $this->_lastRequest = $request; + $this->_lastResponse = $response; + + return $response; + + } catch (ConnectionException $e) { + $connection->setEnabled(false); + + // Calls callback with connection as param to make it possible to persist invalid connections + if ($this->_callback) { + call_user_func($this->_callback, $connection, $e, $this); + } + + // In case there is no valid connection left, throw exception which caused the disabling of the connection. + if (!$this->hasConnection()) + { + throw $e; + } + return $this->request($path, $method, $data, $query); + } + } + + /** + * Optimizes all search indices + * + * @param array $args OPTIONAL Optional arguments + * @return \Elastica\Response Response object + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-optimize.html + */ + public function optimizeAll($args = array()) + { + return $this->request('_optimize', Request::POST, array(), $args); + } + + /** + * Refreshes all search indices + * + * @return \Elastica\Response Response object + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-refresh.html + */ + public function refreshAll() + { + return $this->request('_refresh', Request::POST); + } + + /** + * logging + * + * @param string|\Elastica\Request $context + * @throws Exception\RuntimeException + */ + protected function _log($context) + { + $log = $this->getConfig('log'); + if ($log && !class_exists('Psr\Log\AbstractLogger')) { + throw new RuntimeException('Class Psr\Log\AbstractLogger not found'); + } elseif (!$this->_logger && $log) { + $this->setLogger(new Log($this->getConfig('log'))); + } + if ($this->_logger) { + if ($context instanceof Request) { + $data = $context->toArray(); + } else { + $data = array('message' => $context); + } + $this->_logger->debug('logging Request', $data); + } + } + + /** + * @return \Elastica\Request + */ + public function getLastRequest() + { + return $this->_lastRequest; + } + + /** + * @return \Elastica\Response + */ + public function getLastResponse() + { + return $this->_lastResponse; + } + + /** + * set Logger + * + * @param LoggerInterface $logger + * @return $this + */ + public function setLogger(LoggerInterface $logger) + { + $this->_logger = $logger; + + return $this; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Cluster.php b/vendor/ruflin/elastica/lib/Elastica/Cluster.php new file mode 100644 index 00000000..ac5acf76 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Cluster.php @@ -0,0 +1,181 @@ +<?php + +namespace Elastica; +use Elastica\Cluster\Health; +use Elastica\Cluster\Settings; +use Elastica\Exception\NotImplementedException; + +/** + * Cluster informations for elasticsearch + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/api/ + */ +class Cluster +{ + /** + * Client + * + * @var \Elastica\Client Client object + */ + protected $_client = null; + + /** + * Cluster state response. + * + * @var \Elastica\Response + */ + protected $_response; + + /** + * Cluster state data. + * + * @var array + */ + protected $_data; + + /** + * Creates a cluster object + * + * @param \Elastica\Client $client Connection client object + */ + public function __construct(Client $client) + { + $this->_client = $client; + $this->refresh(); + } + + /** + * Refreshes all cluster information (state) + */ + public function refresh() + { + $path = '_cluster/state'; + $this->_response = $this->_client->request($path, Request::GET); + $this->_data = $this->getResponse()->getData(); + } + + /** + * Returns the response object + * + * @return \Elastica\Response Response object + */ + public function getResponse() + { + return $this->_response; + } + + /** + * Return list of index names + * + * @return array List of index names + */ + public function getIndexNames() + { + $metaData = $this->_data['metadata']['indices']; + + $indices = array(); + foreach ($metaData as $key => $value) { + $indices[] = $key; + } + + return $indices; + } + + /** + * Returns the full state of the cluster + * + * @return array State array + * @link http://www.elasticsearch.org/guide/reference/api/admin-cluster-state.html + */ + public function getState() + { + return $this->_data; + } + + /** + * Returns a list of existing node names + * + * @return array List of node names + */ + public function getNodeNames() + { + $data = $this->getState(); + + return array_keys($data['routing_nodes']['nodes']); + } + + /** + * Returns all nodes of the cluster + * + * @return \Elastica\Node[] + */ + public function getNodes() + { + $nodes = array(); + foreach ($this->getNodeNames() as $name) { + $nodes[] = new Node($name, $this->getClient()); + } + + return $nodes; + } + + /** + * Returns the client object + * + * @return \Elastica\Client Client object + */ + public function getClient() + { + return $this->_client; + } + + /** + * Returns the cluster information (not implemented yet) + * + * @param array $args Additional arguments + * @throws \Elastica\Exception\NotImplementedException + * @link http://www.elasticsearch.org/guide/reference/api/admin-cluster-nodes-info.html + */ + public function getInfo(array $args) + { + throw new NotImplementedException('not implemented yet'); + } + + /** + * Return Cluster health + * + * @return \Elastica\Cluster\Health + * @link http://www.elasticsearch.org/guide/reference/api/admin-cluster-health.html + */ + public function getHealth() + { + return new Health($this->getClient()); + } + + /** + * Return Cluster settings + * + * @return \Elastica\Cluster\Settings + */ + public function getSettings() + { + return new Settings($this->getClient()); + } + + /** + * Shuts down the complete cluster + * + * @param string $delay OPTIONAL Seconds to shutdown cluster after (default = 1s) + * @return \Elastica\Response + * @link http://www.elasticsearch.org/guide/reference/api/admin-cluster-nodes-shutdown.html + */ + public function shutdown($delay = '1s') + { + $path = '_shutdown?delay=' . $delay; + + return $this->_client->request($path, Request::POST); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Cluster/Health.php b/vendor/ruflin/elastica/lib/Elastica/Cluster/Health.php new file mode 100644 index 00000000..18c77cfc --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Cluster/Health.php @@ -0,0 +1,189 @@ +<?php + +namespace Elastica\Cluster; +use Elastica\Client; +use Elastica\Cluster\Health\Index; +use Elastica\Request; + +/** + * Elastic cluster health. + * + * @package Elastica + * @author Ray Ward <ray.ward@bigcommerce.com> + * @link http://www.elasticsearch.org/guide/reference/api/admin-cluster-health.html + */ +class Health +{ + /** + * Elastica client. + * + * @var \Elastica\Client Client object + */ + protected $_client = null; + + /** + * The cluster health data. + * + * @var array + */ + protected $_data = null; + + /** + * @param \Elastica\Client $client The Elastica client. + */ + public function __construct(Client $client) + { + $this->_client = $client; + $this->refresh(); + } + + /** + * Retrieves the health data from the cluster. + * + * @return array + */ + protected function _retrieveHealthData() + { + $path = '_cluster/health?level=shards'; + $response = $this->_client->request($path, Request::GET); + + return $response->getData(); + } + + /** + * Gets the health data. + * + * @return array + */ + public function getData() + { + return $this->_data; + } + + /** + * Refreshes the health data for the cluster. + * + * @return \Elastica\Cluster\Health + */ + public function refresh() + { + $this->_data = $this->_retrieveHealthData(); + + return $this; + } + + /** + * Gets the name of the cluster. + * + * @return string + */ + public function getClusterName() + { + return $this->_data['cluster_name']; + } + + /** + * Gets the status of the cluster. + * + * @return string green, yellow or red. + */ + public function getStatus() + { + return $this->_data['status']; + } + + /** + * TODO determine the purpose of this. + * + * @return bool + */ + public function getTimedOut() + { + return $this->_data['timed_out']; + } + + /** + * Gets the number of nodes in the cluster. + * + * @return int + */ + public function getNumberOfNodes() + { + return $this->_data['number_of_nodes']; + } + + /** + * Gets the number of data nodes in the cluster. + * + * @return int + */ + public function getNumberOfDataNodes() + { + return $this->_data['number_of_data_nodes']; + } + + /** + * Gets the number of active primary shards. + * + * @return int + */ + public function getActivePrimaryShards() + { + return $this->_data['active_primary_shards']; + } + + /** + * Gets the number of active shards. + * + * @return int + */ + public function getActiveShards() + { + return $this->_data['active_shards']; + } + + /** + * Gets the number of relocating shards. + * + * @return int + */ + public function getRelocatingShards() + { + return $this->_data['relocating_shards']; + } + + /** + * Gets the number of initializing shards. + * + * @return int + */ + public function getInitializingShards() + { + return $this->_data['initializing_shards']; + } + + /** + * Gets the number of unassigned shards. + * + * @return int + */ + public function getUnassignedShards() + { + return $this->_data['unassigned_shards']; + } + + /** + * Gets the status of the indices. + * + * @return \Elastica\Cluster\Health\Index[] + */ + public function getIndices() + { + $indices = array(); + foreach ($this->_data['indices'] as $indexName => $index) { + $indices[] = new Index($indexName, $index); + } + + return $indices; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Cluster/Health/Index.php b/vendor/ruflin/elastica/lib/Elastica/Cluster/Health/Index.php new file mode 100644 index 00000000..c39e94c3 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Cluster/Health/Index.php @@ -0,0 +1,142 @@ +<?php + +namespace Elastica\Cluster\Health; + +/** + * Wraps status information for an index. + * + * @package Elastica + * @author Ray Ward <ray.ward@bigcommerce.com> + * @link http://www.elasticsearch.org/guide/reference/api/admin-cluster-health.html + */ +class Index +{ + /** + * The name of the index. + * + * @var string + */ + protected $_name; + + /** + * The index health data. + * + * @var array + */ + protected $_data; + + /** + * @param string $name The name of the index. + * @param array $data The index health data. + */ + public function __construct($name, $data) + { + $this->_name = $name; + $this->_data = $data; + } + + /** + * Gets the name of the index. + * + * @return string + */ + public function getName() + { + return $this->_name; + } + + /** + * Gets the status of the index. + * + * @return string green, yellow or red. + */ + public function getStatus() + { + return $this->_data['status']; + } + + /** + * Gets the number of nodes in the index. + * + * @return int + */ + public function getNumberOfShards() + { + return $this->_data['number_of_shards']; + } + + /** + * Gets the number of data nodes in the index. + * + * @return int + */ + public function getNumberOfReplicas() + { + return $this->_data['number_of_replicas']; + } + + /** + * Gets the number of active primary shards. + * + * @return int + */ + public function getActivePrimaryShards() + { + return $this->_data['active_primary_shards']; + } + + /** + * Gets the number of active shards. + * + * @return int + */ + public function getActiveShards() + { + return $this->_data['active_shards']; + } + + /** + * Gets the number of relocating shards. + * + * @return int + */ + public function getRelocatingShards() + { + return $this->_data['relocating_shards']; + } + + /** + * Gets the number of initializing shards. + * + * @return int + */ + public function getInitializingShards() + { + return $this->_data['initializing_shards']; + } + + /** + * Gets the number of unassigned shards. + * + * @return int + */ + public function getUnassignedShards() + { + return $this->_data['unassigned_shards']; + } + + /** + * Gets the health of the shards in this index. + * + * @return \Elastica\Cluster\Health\Shard[] + */ + public function getShards() + { + $shards = array(); + foreach ($this->_data['shards'] as $shardNumber => $shard) { + $shards[] = new Shard($shardNumber, $shard); + } + + return $shards; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Cluster/Health/Shard.php b/vendor/ruflin/elastica/lib/Elastica/Cluster/Health/Shard.php new file mode 100644 index 00000000..a5da08ae --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Cluster/Health/Shard.php @@ -0,0 +1,107 @@ +<?php + +namespace Elastica\Cluster\Health; + +/** + * Wraps status information for a shard. + * + * @package Elastica + * @author Ray Ward <ray.ward@bigcommerce.com> + * @link http://www.elasticsearch.org/guide/reference/api/admin-cluster-health.html + */ +class Shard +{ + /** + * The shard index/number. + * + * @var int + */ + protected $_shardNumber; + + /** + * The shard health data. + * + * @var array + */ + protected $_data; + + /** + * @param int $shardNumber The shard index/number. + * @param array $data The shard health data. + */ + public function __construct($shardNumber, $data) + { + $this->_shardNumber = $shardNumber; + $this->_data = $data; + } + + /** + * Gets the index/number of this shard. + * + * @return int + */ + public function getShardNumber() + { + return $this->_shardNumber; + } + + /** + * Gets the status of this shard. + * + * @return string green, yellow or red. + */ + public function getStatus() + { + return $this->_data['status']; + } + + /** + * Is the primary active? + * + * @return bool + */ + public function isPrimaryActive() + { + return $this->_data['primary_active']; + } + + /** + * Is this shard active? + * + * @return bool + */ + public function isActive() + { + return $this->_data['active_shards'] == 1; + } + + /** + * Is this shard relocating? + * + * @return bool + */ + public function isRelocating() + { + return $this->_data['relocating_shards'] == 1; + } + + /** + * Is this shard initialized? + * + * @return bool + */ + public function isInitialized() + { + return $this->_data['initializing_shards'] == 1; + } + + /** + * Is this shard unassigned? + * + * @return bool + */ + public function isUnassigned() + { + return $this->_data['unassigned_shards'] == 1; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Cluster/Settings.php b/vendor/ruflin/elastica/lib/Elastica/Cluster/Settings.php new file mode 100644 index 00000000..8166dda3 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Cluster/Settings.php @@ -0,0 +1,197 @@ +<?php + +namespace Elastica\Cluster; + +use Elastica\Client; +use Elastica\Request; + +/** + * Cluster settings + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/api/admin-cluster-update-settings.html + */ +class Settings +{ + /** + * Client + * + * @var \Elastica\Client Client object + */ + protected $_client = null; + + /** + * Creates a cluster object + * + * @param \Elastica\Client $client Connection client object + */ + public function __construct(Client $client) + { + $this->_client = $client; + } + + /** + * Returns settings data + * + * @return array Settings data (persistent and transient) + */ + public function get() + { + return $this->request()->getData(); + } + + /** + * Returns the current persistent settings of the cluster + * + * If param is set, only specified setting is return. + * + * @param string $setting OPTIONAL Setting name to return + * @return array|string|null Settings data + */ + public function getPersistent($setting = '') + { + $data = $this->get(); + $settings = $data['persistent']; + + if (!empty($setting)) { + if (isset($settings[$setting])) { + return $settings[$setting]; + } else { + return null; + } + } + + return $settings; + } + + /** + * Returns the current transient settings of the cluster + * + * If param is set, only specified setting is return. + * + * @param string $setting OPTIONAL Setting name to return + * @return array|string|null Settings data + */ + public function getTransient($setting = '') + { + $data = $this->get(); + $settings = $data['transient']; + + if (!empty($setting)) { + if (isset($settings[$setting])) { + return $settings[$setting]; + } else { + if (strpos($setting, '.') !== false) { + // convert dot notation to nested arrays + $keys = explode('.', $setting); + foreach ($keys as $key) { + if (isset($settings[$key])) { + $settings = $settings[$key]; + } else { + return null; + } + } + return $settings; + } + return null; + } + } + + return $settings; + } + + /** + * Sets persistent setting + * + * @param string $key + * @param string $value + * @return \Elastica\Response + */ + public function setPersistent($key, $value) + { + return $this->set( + array( + 'persistent' => array( + $key => $value + ) + ) + ); + } + + /** + * Sets transient settings + * + * @param string $key + * @param string $value + * @return \Elastica\Response + */ + public function setTransient($key, $value) + { + return $this->set( + array( + 'transient' => array( + $key => $value + ) + ) + ); + } + + /** + * Sets the cluster to read only + * + * Second param can be used to set it persistent + * + * @param bool $readOnly + * @param bool $persistent + * @return \Elastica\Response $response + */ + public function setReadOnly($readOnly = true, $persistent = false) + { + $key = 'cluster.blocks.read_only'; + + if ($persistent) { + $response = $this->setPersistent($key, $readOnly); + } else { + $response = $this->setTransient($key, $readOnly); + } + + return $response; + } + + /** + * Set settings for cluster + * + * @param array $settings Raw settings (including persistent or transient) + * @return \Elastica\Response + */ + public function set(array $settings) + { + return $this->request($settings, Request::PUT); + } + + /** + * Get the client + * + * @return \Elastica\Client + */ + public function getClient() + { + return $this->_client; + } + + /** + * Sends settings request + * + * @param array $data OPTIONAL Data array + * @param string $method OPTIONAL Transfer method (default = \Elastica\Request::GET) + * @return \Elastica\Response Response object + */ + public function request(array $data = array(), $method = Request::GET) + { + $path = '_cluster/settings'; + + return $this->getClient()->request($path, $method, $data); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Connection.php b/vendor/ruflin/elastica/lib/Elastica/Connection.php new file mode 100644 index 00000000..b9d910c9 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Connection.php @@ -0,0 +1,274 @@ +<?php + +namespace Elastica; +use Elastica\Exception\InvalidException; +use Elastica\Transport\AbstractTransport; + +/** + * Elastica connection instance to an elasticasearch node + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class Connection extends Param +{ + /** + * Default elastic search port + */ + const DEFAULT_PORT = 9200; + + /** + * Default host + */ + const DEFAULT_HOST = 'localhost'; + + /** + * Default transport + * + * @var string + */ + const DEFAULT_TRANSPORT = 'Http'; + + /** + * Number of seconds after a timeout occurs for every request + * If using indexing of file large value necessary. + */ + const TIMEOUT = 300; + + /** + * Creates a new connection object. A connection is enabled by default + * + * @param array $params OPTIONAL Connection params: host, port, transport, timeout. All are optional + */ + public function __construct(array $params = array()) + { + $this->setParams($params); + $this->setEnabled(true); + + // Set empty config param if not exists + if (!$this->hasParam('config')) { + $this->setParam('config', array()); + } + } + + /** + * @return int Server port + */ + public function getPort() + { + return $this->hasParam('port')?$this->getParam('port'):self::DEFAULT_PORT; + } + + /** + * @param int $port + * @return \Elastica\Connection + */ + public function setPort($port) + { + return $this->setParam('port', (int) $port); + } + + /** + * @return string Host + */ + public function getHost() + { + return $this->hasParam('host')?$this->getParam('host'):self::DEFAULT_HOST; + } + + /** + * @param string $host + * @return \Elastica\Connection + */ + public function setHost($host) + { + return $this->setParam('host', $host); + } + + /** + * @return string|null Host + */ + public function getProxy() + { + return $this->hasParam('proxy')?$this->getParam('proxy'):null; + } + + /** + * Set proxy for http connections. Null is for environmental proxy, + * empty string to disable proxy and proxy string to set actual http proxy. + * + * @see http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTPROXY + * @param string|null $proxy + * @return \Elastica\Connection + */ + public function setProxy($proxy) + { + return $this->setParam('proxy', $proxy); + } + + /** + * @return string|array + */ + public function getTransport() + { + return $this->hasParam('transport')?$this->getParam('transport'):self::DEFAULT_TRANSPORT; + } + + /** + * @param string|array $transport + * @return \Elastica\Connection + */ + public function setTransport($transport) + { + return $this->setParam('transport', $transport); + } + + /** + * @return string + */ + public function getPath() + { + return $this->hasParam('path')?$this->getParam('path'):''; + } + + /** + * @param string $path + * @return \Elastica\Connection + */ + public function setPath($path) + { + return $this->setParam('path', $path); + } + + /** + * @param int $timeout Timeout in seconds + * @return \Elastica\Connection + */ + public function setTimeout($timeout) + { + return $this->setParam('timeout', $timeout); + } + + /** + * @return int Connection timeout in seconds + */ + public function getTimeout() + { + return (int) $this->hasParam('timeout')?$this->getParam('timeout'):self::TIMEOUT; + } + + /** + * Enables a connection + * + * @param bool $enabled OPTIONAL (default = true) + * @return \Elastica\Connection + */ + public function setEnabled($enabled = true) + { + return $this->setParam('enabled', $enabled); + } + + /** + * @return bool True if enabled + */ + public function isEnabled() + { + return (bool) $this->getParam('enabled'); + } + + /** + * Returns an instance of the transport type + * + * @return \Elastica\Transport\AbstractTransport Transport object + * @throws \Elastica\Exception\InvalidException If invalid transport type + */ + public function getTransportObject() + { + $transport = $this->getTransport(); + + return AbstractTransport::create($transport, $this); + } + + /** + * @return bool Returns true if connection is persistent. True by default + */ + public function isPersistent() + { + return (bool) $this->hasParam('persistent')?$this->getParam('persistent'):true; + } + + /** + * @param array $config + * @return \Elastica\Connection + */ + public function setConfig(array $config) + { + return $this->setParam('config', $config); + } + + /** + * @param string $key + * @param mixed $value + * @return \Elastica\Connection + */ + public function addConfig($key, $value) + { + $this->_params['config'][$key] = $value; + + return $this; + } + + /** + * @param string $key + * @return bool + */ + public function hasConfig($key) + { + $config = $this->getConfig(); + + return isset($config[$key]); + } + + /** + * Returns a specific config key or the whole + * config array if not set + * + * @param string $key Config key + * @throws \Elastica\Exception\InvalidException + * @return array|string Config value + */ + public function getConfig($key = '') + { + $config = $this->getParam('config'); + if (empty($key)) { + return $config; + } + + if (!array_key_exists($key, $config)) { + throw new InvalidException('Config key is not set: ' . $key); + } + + return $config[$key]; + } + + /** + * @param \Elastica\Connection|array $params Params to create a connection + * @throws Exception\InvalidException + * @return \Elastica\Connection + */ + public static function create($params = array()) + { + $connection = null; + + if ($params instanceof Connection) { + $connection = $params; + } elseif (is_array($params)) { + $connection = new Connection($params); + } else { + throw new InvalidException('Invalid data type'); + } + + return $connection; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Document.php b/vendor/ruflin/elastica/lib/Elastica/Document.php new file mode 100644 index 00000000..3f6b88de --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Document.php @@ -0,0 +1,334 @@ +<?php + +namespace Elastica; + +use Elastica\Exception\InvalidException; +use Elastica\Bulk\Action; +use Elastica\Filter\Bool; +use Elastica\Exception\NotImplementedException; + +/** + * Single document stored in elastic search + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class Document extends AbstractUpdateAction +{ + const OP_TYPE_CREATE = Action::OP_TYPE_CREATE; + + /** + * Document data + * + * @var array Document data + */ + protected $_data = array(); + + /** + * Whether to use this document to upsert if the document does not exist. + * + * @var boolean + */ + protected $_docAsUpsert = false; + + /** + * @var boolean + */ + protected $_autoPopulate = false; + + /** + * Creates a new document + * + * @param int|string $id OPTIONAL $id Id is create if empty + * @param array|string $data OPTIONAL Data array + * @param string $type OPTIONAL Type name + * @param string $index OPTIONAL Index name + */ + public function __construct($id = '', $data = array(), $type = '', $index = '') + { + $this->setId($id); + $this->setData($data); + $this->setType($type); + $this->setIndex($index); + } + + /** + * @param string $key + * @return mixed + */ + public function __get($key) + { + return $this->get($key); + } + + /** + * @param string $key + * @param mixed $value + */ + public function __set($key, $value) + { + $this->set($key, $value); + } + + /** + * @param string $key + * @return bool + */ + public function __isset($key) + { + return $this->has($key) && null !== $this->get($key); + } + + /** + * @param string $key + */ + public function __unset($key) + { + $this->remove($key); + } + + /** + * @param string $key + * @return mixed + * @throws \Elastica\Exception\InvalidException + */ + public function get($key) + { + if (!$this->has($key)) { + throw new InvalidException("Field {$key} does not exist"); + } + return $this->_data[$key]; + } + + /** + * @param string $key + * @param mixed $value + * @throws \Elastica\Exception\InvalidException + * @return \Elastica\Document + */ + public function set($key, $value) + { + if (!is_array($this->_data)) { + throw new InvalidException('Document data is serialized data. Data creation is forbidden.'); + } + $this->_data[$key] = $value; + + return $this; + } + + /** + * @param string $key + * @return bool + */ + public function has($key) + { + return is_array($this->_data) && array_key_exists($key, $this->_data); + } + + /** + * @param string $key + * @throws \Elastica\Exception\InvalidException + * @return \Elastica\Document + */ + public function remove($key) + { + if (!$this->has($key)) { + throw new InvalidException("Field {$key} does not exist"); + } + unset($this->_data[$key]); + + return $this; + } + + /** + * Adds the given key/value pair to the document + * + * @deprecated + * @param string $key Document entry key + * @param mixed $value Document entry value + * @return \Elastica\Document + */ + public function add($key, $value) + { + return $this->set($key, $value); + } + + /** + * Adds a file to the index + * + * To use this feature you have to call the following command in the + * elasticsearch directory: + * <code> + * ./bin/plugin -install elasticsearch/elasticsearch-mapper-attachments/1.6.0 + * </code> + * This installs the tika file analysis plugin. More infos about supported formats + * can be found here: {@link http://tika.apache.org/0.7/formats.html} + * + * @param string $key Key to add the file to + * @param string $filepath Path to add the file + * @param string $mimeType OPTIONAL Header mime type + * @return \Elastica\Document + */ + public function addFile($key, $filepath, $mimeType = '') + { + $value = base64_encode(file_get_contents($filepath)); + + if (!empty($mimeType)) { + $value = array('_content_type' => $mimeType, '_name' => $filepath, 'content' => $value,); + } + + $this->set($key, $value); + + return $this; + } + + /** + * Add file content + * + * @param string $key Document key + * @param string $content Raw file content + * @return \Elastica\Document + */ + public function addFileContent($key, $content) + { + return $this->set($key, base64_encode($content)); + } + + /** + * Adds a geopoint to the document + * + * Geohashes are not yet supported + * + * @param string $key Field key + * @param float $latitude Latitude value + * @param float $longitude Longitude value + * @link http://www.elasticsearch.org/guide/reference/mapping/geo-point-type.html + * @return \Elastica\Document + */ + public function addGeoPoint($key, $latitude, $longitude) + { + $value = array('lat' => $latitude, 'lon' => $longitude,); + + $this->set($key, $value); + + return $this; + } + + /** + * Overwrites the current document data with the given data + * + * @param array|string $data Data array + * @return \Elastica\Document + */ + public function setData($data) + { + $this->_data = $data; + + return $this; + } + + /** + * Returns the document data + * + * @return array|string Document data + */ + public function getData() + { + return $this->_data; + } + + /** + * @param \Elastica\Script $data + * @throws NotImplementedException + * @deprecated + */ + public function setScript($data) + { + throw new NotImplementedException("setScript() is no longer available as of 0.90.2. See http://elastica.io/migration/0.90.2/upsert.html to migrate"); + } + + /** + * @throws NotImplementedException + * @deprecated + */ + public function getScript() + { + throw new NotImplementedException("getScript() is no longer available as of 0.90.2. See http://elastica.io/migration/0.90.2/upsert.html to migrate"); + } + + /** + * @throws NotImplementedException + * @deprecated + */ + public function hasScript() + { + throw new NotImplementedException("hasScript() is no longer available as of 0.90.2. See http://elastica.io/migration/0.90.2/upsert.html to migrate"); + } + + /** + * @param bool $value + * @return \Elastica\Document + */ + public function setDocAsUpsert($value) + { + $this->_docAsUpsert = (bool) $value; + + return $this; + } + + /** + * @return boolean + */ + public function getDocAsUpsert() + { + return $this->_docAsUpsert; + } + + /** + * @param bool $autoPopulate + * @return $this + */ + public function setAutoPopulate($autoPopulate = true) + { + $this->_autoPopulate = (bool) $autoPopulate; + + return $this; + } + + /** + * @return bool + */ + public function isAutoPopulate() + { + return $this->_autoPopulate; + } + + /** + * Returns the document as an array + * @return array + */ + public function toArray() + { + $doc = $this->getParams(); + $doc['_source'] = $this->getData(); + + return $doc; + } + + /** + * @param array|\Elastica\Document $data + * @throws \Elastica\Exception\InvalidException + * @return \Elastica\Document + */ + public static function create($data) + { + if ($data instanceof self) { + return $data; + } elseif (is_array($data)) { + return new self('', $data); + } else { + throw new InvalidException('Failed to create document. Invalid data passed.'); + } + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Exception/Bulk/Response/ActionException.php b/vendor/ruflin/elastica/lib/Elastica/Exception/Bulk/Response/ActionException.php new file mode 100644 index 00000000..6500e040 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Exception/Bulk/Response/ActionException.php @@ -0,0 +1,66 @@ +<?php + +namespace Elastica\Exception\Bulk\Response; + +use Elastica\Exception\BulkException; +use Elastica\Bulk\Action; +use Elastica\Bulk\Response; + +class ActionException extends BulkException +{ + /** + * @var \Elastica\Response + */ + protected $_response; + + /** + * @param \Elastica\Bulk\Response $response + */ + public function __construct(Response $response) + { + $this->_response = $response; + + parent::__construct($this->getErrorMessage($response)); + } + + /** + * @return \Elastica\Bulk\Action + */ + public function getAction() + { + return $this->getResponse()->getAction(); + } + + /** + * @return \Elastica\Bulk\Response + */ + public function getResponse() + { + return $this->_response; + } + + /** + * @param \Elastica\Bulk\Response $response + * @return string + */ + public function getErrorMessage(Response $response) + { + $error = $response->getError(); + $opType = $response->getOpType(); + $data = $response->getData(); + + $path = ''; + if (isset($data['_index'])) { + $path.= '/' . $data['_index']; + } + if (isset($data['_type'])) { + $path.= '/' . $data['_type']; + } + if (isset($data['_id'])) { + $path.= '/' . $data['_id']; + } + $message = "$opType: $path caused $error"; + + return $message; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Exception/Bulk/ResponseException.php b/vendor/ruflin/elastica/lib/Elastica/Exception/Bulk/ResponseException.php new file mode 100644 index 00000000..9df1b3e8 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Exception/Bulk/ResponseException.php @@ -0,0 +1,103 @@ +<?php + +namespace Elastica\Exception\Bulk; + +use Elastica\Bulk\ResponseSet; +use Elastica\Exception\Bulk\Response\ActionException; +use Elastica\Exception\BulkException; + +/** + * Bulk Response exception + * + * @category Xodoa + * @package Elastica + */ +class ResponseException extends BulkException +{ + /** + * Response + * + * @var \Elastica\Bulk\ResponseSet ResponseSet object + */ + protected $_responseSet; + + /** + * @var \Elastica\Exception\Bulk\Response\ActionException[] + */ + protected $_actionExceptions = array(); + + /** + * Construct Exception + * + * @param \Elastica\Bulk\ResponseSet $responseSet + */ + public function __construct(ResponseSet $responseSet) + { + $this->_init($responseSet); + + $message = 'Error in one or more bulk request actions:' . PHP_EOL . PHP_EOL; + $message.= $this->getActionExceptionsAsString(); + + parent::__construct($message); + } + + /** + * @param \Elastica\Bulk\ResponseSet $responseSet + */ + protected function _init(ResponseSet $responseSet) + { + $this->_responseSet = $responseSet; + + foreach ($responseSet->getBulkResponses() as $bulkResponse) { + if ($bulkResponse->hasError()) { + $this->_actionExceptions[] = new ActionException($bulkResponse); + } + } + } + + /** + * Returns bulk response set object + * + * @return \Elastica\Bulk\ResponseSet + */ + public function getResponseSet() + { + return $this->_responseSet; + } + + /** + * Returns array of failed actions + * + * @return array Array of failed actions + */ + public function getFailures() + { + $errors = array(); + + foreach ($this->getActionExceptions() as $actionException) { + $errors[] = $actionException->getMessage(); + } + + return $errors; + } + + /** + * @return \Elastica\Exception\Bulk\Response\ActionException[] + */ + public function getActionExceptions() + { + return $this->_actionExceptions; + } + + /** + * @return string + */ + public function getActionExceptionsAsString() + { + $message = ''; + foreach ($this->getActionExceptions() as $actionException) { + $message.= $actionException->getMessage() . PHP_EOL; + } + return $message; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Exception/Bulk/UdpException.php b/vendor/ruflin/elastica/lib/Elastica/Exception/Bulk/UdpException.php new file mode 100644 index 00000000..0b2d4d2e --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Exception/Bulk/UdpException.php @@ -0,0 +1,9 @@ +<?php + +namespace Elastica\Exception\Bulk; + +use Elastica\Exception\BulkException; + +class UdpException extends BulkException +{ +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Exception/BulkException.php b/vendor/ruflin/elastica/lib/Elastica/Exception/BulkException.php new file mode 100644 index 00000000..6d384556 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Exception/BulkException.php @@ -0,0 +1,7 @@ +<?php + +namespace Elastica\Exception; + +class BulkException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Exception/ClientException.php b/vendor/ruflin/elastica/lib/Elastica/Exception/ClientException.php new file mode 100644 index 00000000..00efd67d --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Exception/ClientException.php @@ -0,0 +1,14 @@ +<?php + +namespace Elastica\Exception; + +/** + * Client exception + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class ClientException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Exception/Connection/GuzzleException.php b/vendor/ruflin/elastica/lib/Elastica/Exception/Connection/GuzzleException.php new file mode 100644 index 00000000..645c0eff --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Exception/Connection/GuzzleException.php @@ -0,0 +1,51 @@ +<?php + +namespace Elastica\Exception\Connection; + +use Elastica\Exception\ConnectionException; +use Elastica\Request; +use Elastica\Response; +use GuzzleHttp\Exception\TransferException; + +/** + * Transport exception + * + * @package Elastica + * @author Milan Magudia <milan@magudia.com> + */ +class GuzzleException extends ConnectionException +{ + /** + * @var TransferException + */ + protected $_guzzleException; + + /** + * @param \GuzzleHttp\Exception\TransferException $guzzleException + * @param \Elastica\Request $request + * @param \Elastica\Response $response + */ + public function __construct(TransferException $guzzleException, Request $request = null, Response $response = null) + { + $this->_guzzleException = $guzzleException; + $message = $this->getErrorMessage($this->getGuzzleException()); + parent::__construct($message, $request, $response); + } + + /** + * @param \GuzzleHttp\Exception\TransferException $guzzleException + * @return string + */ + public function getErrorMessage(TransferException $guzzleException) + { + return $guzzleException->getMessage(); + } + + /** + * @return TransferException + */ + public function getGuzzleException() + { + return $this->_guzzleException; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Exception/Connection/HttpException.php b/vendor/ruflin/elastica/lib/Elastica/Exception/Connection/HttpException.php new file mode 100644 index 00000000..2a36fe48 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Exception/Connection/HttpException.php @@ -0,0 +1,88 @@ +<?php + +namespace Elastica\Exception\Connection; + +use Elastica\Exception\ConnectionException; +use Elastica\Request; +use Elastica\Response; + +/** + * Connection exception + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class HttpException extends ConnectionException +{ + /** + * Error code / message + * + * @var string Error code / message + */ + protected $_error = 0; + + /** + * Construct Exception + * + * @param string $error Error + * @param \Elastica\Request $request + * @param \Elastica\Response $response + */ + public function __construct($error, Request $request = null, Response $response = null) + { + $this->_error = $error; + + $message = $this->getErrorMessage($this->getError()); + parent::__construct($message, $request, $response); + } + + /** + * Returns the error message corresponding to the error code + * cUrl error code reference can be found here {@link http://curl.haxx.se/libcurl/c/libcurl-errors.html} + * + * @param string $error Error code + * @return string Error message + */ + public function getErrorMessage($error) + { + switch ($error) { + case CURLE_UNSUPPORTED_PROTOCOL: + $error = "Unsupported protocol"; + break; + case CURLE_FAILED_INIT: + $error = "Internal cUrl error?"; + break; + case CURLE_URL_MALFORMAT: + $error = "Malformed URL"; + break; + case CURLE_COULDNT_RESOLVE_PROXY: + $error = "Couldn't resolve proxy"; + break; + case CURLE_COULDNT_RESOLVE_HOST: + $error = "Couldn't resolve host"; + break; + case CURLE_COULDNT_CONNECT: + $error = "Couldn't connect to host, Elasticsearch down?"; + break; + case 28: + $error = "Operation timed out"; + break; + default: + $error = "Unknown error:" . $error; + break; + } + + return $error; + } + + /** + * Return Error code / message + * + * @return string Error code / message + */ + public function getError() + { + return $this->_error; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Exception/Connection/ThriftException.php b/vendor/ruflin/elastica/lib/Elastica/Exception/Connection/ThriftException.php new file mode 100644 index 00000000..0ca331c7 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Exception/Connection/ThriftException.php @@ -0,0 +1,51 @@ +<?php + +namespace Elastica\Exception\Connection; + +use Elastica\Exception\ConnectionException; +use Elastica\Request; +use Elastica\Response; +use Thrift\Exception\TException; + +/** + * Transport exception + * + * @category Xodoa + * @package Elastica + * @author Mikhail Shamin <munk13@gmail.com> + */ +class ThriftException extends ConnectionException +{ + /** + * @var TException + */ + protected $_thriftException; + + /** + * @param \Thrift\Exception\TException $thriftException + * @param \Elastica\Request $request + * @param \Elastica\Response $response + */ + public function __construct(TException $thriftException, Request $request = null, Response $response = null) + { + $this->_thriftException = $thriftException; + $message = $this->getErrorMessage($this->getThriftException()); + parent::__construct($message, $request, $response); + } + + /** + * @param \Thrift\Exception\TException $thriftException + * @return string + */ + public function getErrorMessage(TException $thriftException) + { + return $thriftException->getMessage(); + } + /** + * @return TException + */ + public function getThriftException() + { + return $this->_thriftException; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Exception/ConnectionException.php b/vendor/ruflin/elastica/lib/Elastica/Exception/ConnectionException.php new file mode 100644 index 00000000..35d60472 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Exception/ConnectionException.php @@ -0,0 +1,65 @@ +<?php + +namespace Elastica\Exception; + +use Elastica\Request; +use Elastica\Response; + +/** + * Connection exception + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class ConnectionException extends \RuntimeException implements ExceptionInterface +{ + /** + * Request + * + * @var \Elastica\Request Request object + */ + protected $_request; + + /** + * Response + * + * @var \Elastica\Response Response object + */ + protected $_response; + + /** + * Construct Exception + * + * @param string $message Message + * @param \Elastica\Request $request + * @param \Elastica\Response $response + */ + public function __construct($message, Request $request = null, Response $response = null) + { + $this->_request = $request; + $this->_response = $response; + + parent::__construct($message); + } + + /** + * Returns request object + * + * @return \Elastica\Request Request object + */ + public function getRequest() + { + return $this->_request; + } + + /** + * Returns response object + * + * @return \Elastica\Response Response object + */ + public function getResponse() + { + return $this->_response; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Exception/ElasticsearchException.php b/vendor/ruflin/elastica/lib/Elastica/Exception/ElasticsearchException.php new file mode 100644 index 00000000..0f7509f9 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Exception/ElasticsearchException.php @@ -0,0 +1,99 @@ +<?php + +namespace Elastica\Exception; + +/** + * Elasticsearch exception + * + * @category Xodoa + * @package Elastica + * @author Ian Babrou <ibobrik@gmail.com> + */ +class ElasticsearchException extends \Exception +{ + + const REMOTE_TRANSPORT_EXCEPTION = 'RemoteTransportException'; + + /** + * Elasticsearch exception name + * + * @var string|null + */ + private $_exception; + + /** + * Whether exception was local to server node or remote + * + * @var bool + */ + private $_isRemote = false; + + /** + * Constructs elasticsearch exception + * + * @param int $code Error code + * @param string $error Error message from elasticsearch + */ + public function __construct($code, $error) + { + $this->_parseError($error); + parent::__construct($error, $code); + } + + /** + * Parse error message from elasticsearch + * + * @param string $error Error message + */ + protected function _parseError($error) + { + $errors = explode(']; nested: ', $error); + + if (count($errors) == 1) { + $this->_exception = $this->_extractException($errors[0]); + } else { + if ($this->_extractException($errors[0]) == self::REMOTE_TRANSPORT_EXCEPTION) { + $this->_isRemote = true; + $this->_exception = $this->_extractException($errors[1]); + } else { + $this->_exception = $this->_extractException($errors[0]); + } + } + } + + /** + * Extract exception name from error response + * + * @param string $error + * @return null|string + */ + protected function _extractException($error) + { + if (preg_match('/^(\w+)\[.*\]/', $error, $matches)) { + return $matches[1]; + } else { + return null; + } + } + + /** + * Returns elasticsearch exception name + * + * @return string|null + */ + public function getExceptionName() + { + return $this->_exception; + } + + /** + * Returns whether exception was local to server node or remote + * + * @return bool + */ + public function isRemoteTransportException() + { + return $this->_isRemote; + } + +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Exception/ExceptionInterface.php b/vendor/ruflin/elastica/lib/Elastica/Exception/ExceptionInterface.php new file mode 100644 index 00000000..746c9c81 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Exception/ExceptionInterface.php @@ -0,0 +1,14 @@ +<?php + +namespace Elastica\Exception; + +/** + * General Elastica exception interface + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +interface ExceptionInterface +{ +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Exception/InvalidException.php b/vendor/ruflin/elastica/lib/Elastica/Exception/InvalidException.php new file mode 100644 index 00000000..ff4a4cd3 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Exception/InvalidException.php @@ -0,0 +1,14 @@ +<?php + +namespace Elastica\Exception; + +/** + * Invalid exception + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class InvalidException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Exception/JSONParseException.php b/vendor/ruflin/elastica/lib/Elastica/Exception/JSONParseException.php new file mode 100644 index 00000000..3cf39911 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Exception/JSONParseException.php @@ -0,0 +1,12 @@ +<?php + +namespace Elastica\Exception; + +/** + * JSON Parse exception + * + * @package Elastica + */ +class JSONParseException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Exception/NotFoundException.php b/vendor/ruflin/elastica/lib/Elastica/Exception/NotFoundException.php new file mode 100644 index 00000000..539b01c2 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Exception/NotFoundException.php @@ -0,0 +1,14 @@ +<?php + +namespace Elastica\Exception; + +/** + * Not found exception + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class NotFoundException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Exception/NotImplementedException.php b/vendor/ruflin/elastica/lib/Elastica/Exception/NotImplementedException.php new file mode 100644 index 00000000..49d3918b --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Exception/NotImplementedException.php @@ -0,0 +1,16 @@ +<?php + +namespace Elastica\Exception; + +/** + * Not implemented exception + * + * Is thrown if a function or feature is not implemented yet + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class NotImplementedException extends \BadMethodCallException implements ExceptionInterface +{ +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Exception/PartialShardFailureException.php b/vendor/ruflin/elastica/lib/Elastica/Exception/PartialShardFailureException.php new file mode 100644 index 00000000..f853bf96 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Exception/PartialShardFailureException.php @@ -0,0 +1,33 @@ +<?php + +namespace Elastica\Exception; + +use Elastica\JSON; +use Elastica\Request; +use Elastica\Response; + +/** + * Partial shard failure exception + * + * @category Xodoa + * @package Elastica + * @author Ian Babrou <ibobrik@gmail.com> + */ +class PartialShardFailureException extends ResponseException +{ + + /** + * Construct Exception + * + * @param \Elastica\Request $request + * @param \Elastica\Response $response + */ + public function __construct(Request $request, Response $response) + { + parent::__construct($request, $response); + + $shardsStatistics = $response->getShardsStatistics(); + $this->message = JSON::stringify($shardsStatistics['failed']); + } + +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Exception/ResponseException.php b/vendor/ruflin/elastica/lib/Elastica/Exception/ResponseException.php new file mode 100644 index 00000000..63244487 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Exception/ResponseException.php @@ -0,0 +1,76 @@ +<?php + +namespace Elastica\Exception; + +use Elastica\Request; +use Elastica\Response; + +/** + * Response exception + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class ResponseException extends \RuntimeException implements ExceptionInterface +{ + /** + * Request + * + * @var \Elastica\Request Request object + */ + protected $_request = null; + + /** + * Response + * + * @var \Elastica\Response Response object + */ + protected $_response = null; + + /** + * Construct Exception + * + * @param \Elastica\Request $request + * @param \Elastica\Response $response + */ + public function __construct(Request $request, Response $response) + { + $this->_request = $request; + $this->_response = $response; + parent::__construct($response->getError()); + } + + /** + * Returns request object + * + * @return \Elastica\Request Request object + */ + public function getRequest() + { + return $this->_request; + } + + /** + * Returns response object + * + * @return \Elastica\Response Response object + */ + public function getResponse() + { + return $this->_response; + } + + /** + * Returns elasticsearch exception + * + * @return ElasticsearchException + */ + public function getElasticsearchException() { + $response = $this->getResponse(); + $transfer = $response->getTransferInfo(); + $code = array_key_exists('http_code', $transfer) ? $transfer['http_code'] : 0; + + return new ElasticsearchException($code, $response->getError()); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Exception/RuntimeException.php b/vendor/ruflin/elastica/lib/Elastica/Exception/RuntimeException.php new file mode 100644 index 00000000..5ee420e1 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Exception/RuntimeException.php @@ -0,0 +1,14 @@ +<?php + +namespace Elastica\Exception; + +/** + * Client exception + * + * @category Xodoa + * @package Elastica + * @author Mikhail Shamin <munk13@gmail.com> + */ +class RuntimeException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Facet/AbstractFacet.php b/vendor/ruflin/elastica/lib/Elastica/Facet/AbstractFacet.php new file mode 100644 index 00000000..25cee812 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Facet/AbstractFacet.php @@ -0,0 +1,141 @@ +<?php + +namespace Elastica\Facet; + +use Elastica\Param; +use Elastica\Filter\AbstractFilter; +use Elastica\Exception\InvalidException; + +/** + * Abstract facet object. Should be extended by all facet types + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @author Jasper van Wanrooy <jasper@vanwanrooy.net> + */ +abstract class AbstractFacet extends Param +{ + /** + * Holds the name of the facet. + * @var string + */ + protected $_name = ''; + + /** + * Holds all facet parameters. + * @var array + */ + protected $_facet = array(); + + /** + * Constructs a Facet object. + * + * @param string $name The name of the facet. + */ + public function __construct($name) + { + $this->setName($name); + } + + /** + * Sets the name of the facet. It is automatically set by + * the constructor. + * + * @param string $name The name of the facet. + * @throws \Elastica\Exception\InvalidException + * @return \Elastica\Facet\AbstractFacet + */ + public function setName($name) + { + if (empty($name)) { + throw new InvalidException('Facet name has to be set'); + } + $this->_name = $name; + + return $this; + } + + /** + * Gets the name of the facet. + * + * @return string + */ + public function getName() + { + return $this->_name; + } + + /** + * Sets a filter for this facet. + * + * @param \Elastica\Filter\AbstractFilter $filter A filter to apply on the facet. + * @return \Elastica\Facet\AbstractFacet + */ + public function setFilter(AbstractFilter $filter) + { + return $this->_setFacetParam('facet_filter', $filter->toArray()); + } + + /** + * Sets the flag to either run the facet globally or bound to the + * current search query. When not set, it defaults to the + * Elasticsearch default value. + * + * @param bool $global Flag to either run the facet globally. + * @return \Elastica\Facet\AbstractFacet + */ + public function setGlobal($global = true) + { + return $this->_setFacetParam('global', (bool) $global); + } + + /** + * Sets the path to the nested document + * + * @param string $nestedPath Nested path + * @return \Elastica\Facet\AbstractFacet + */ + public function setNested($nestedPath) + { + return $this->_setFacetParam('nested', $nestedPath); + } + + /** + * Sets the scope + * + * @param string $scope Scope + * @return \Elastica\Facet\AbstractFacet + */ + public function setScope($scope) + { + return $this->_setFacetParam('scope', $scope); + } + + /** + * Basic definition of all specs of the facet. Each implementation + * should override this function in order to set it's specific + * settings. + * + * @return array + */ + public function toArray() + { + return $this->_facet; + } + + /** + * Sets a param for the facet. Each facet implementation needs to take + * care of handling their own params. + * + * @param string $key The key of the param to set. + * @param mixed $value The value of the param. + * @return \Elastica\Facet\AbstractFacet + */ + protected function _setFacetParam($key, $value) + { + $this->_facet[$key] = $value; + + return $this; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Facet/DateHistogram.php b/vendor/ruflin/elastica/lib/Elastica/Facet/DateHistogram.php new file mode 100644 index 00000000..803f54a3 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Facet/DateHistogram.php @@ -0,0 +1,44 @@ +<?php + +namespace Elastica\Facet; + +/** + * Implements the Date Histogram facet. + * + * @category Xodoa + * @package Elastica + * @author Raul Martinez Jr <juneym@gmail.com> + * @link http://www.elasticsearch.org/guide/reference/api/search/facets/date-histogram-facet.html + * @link https://github.com/elasticsearch/elasticsearch/issues/591 + */ +class DateHistogram extends Histogram +{ + /** + * Set the time_zone parameter + * + * @param string $tzOffset + * @return \Elastica\Facet\DateHistogram + */ + public function setTimezone($tzOffset) + { + return $this->setParam('time_zone', $tzOffset); + } + + /** + * Creates the full facet definition, which includes the basic + * facet definition of the parent. + * + * @see \Elastica\Facet\AbstractFacet::toArray() + * @throws \Elastica\Exception\InvalidException When the right fields haven't been set. + * @return array + */ + public function toArray() + { + /** + * Set the range in the abstract as param. + */ + $this->_setFacetParam('date_histogram', $this->_params); + + return $this->_facet; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Facet/Filter.php b/vendor/ruflin/elastica/lib/Elastica/Facet/Filter.php new file mode 100644 index 00000000..ed6f28b7 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Facet/Filter.php @@ -0,0 +1,27 @@ +<?php + +namespace Elastica\Facet; + +use Elastica\Filter\AbstractFilter; + +/** + * Filter facet + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/api/search/facets/filter-facet.html + */ +class Filter extends AbstractFacet +{ + /** + * Set the filter for the facet. + * + * @param \Elastica\Filter\AbstractFilter $filter + * @return \Elastica\Facet\Filter + */ + public function setFilter(AbstractFilter $filter) + { + return $this->_setFacetParam('filter', $filter->toArray()); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Facet/GeoCluster.php b/vendor/ruflin/elastica/lib/Elastica/Facet/GeoCluster.php new file mode 100644 index 00000000..a6f5e9ed --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Facet/GeoCluster.php @@ -0,0 +1,54 @@ +<?php + +namespace Elastica\Facet; + +/** + * Implements the Geo Cluster facet. + * + * @category Xodoa + * @package Elastica + * @author Konstantin Nikiforov <konstantin.nikiforov@gmail.com> + * @link https://github.com/zenobase/geocluster-facet + */ +class GeoCluster extends AbstractFacet { + + /** + * @param string $fieldName + * @return $this + */ + public function setField($fieldName) { + $this->setParam('field', $fieldName); + return $this; + } + + /** + * @param double $factor + * @return $this + */ + public function setFactor($factor){ + $this->setParam('factor', $factor); + return $this; + } + + /** + * @param boolean $showIds + * @return $this + */ + public function setShowIds($showIds) { + $this->setParam('showIds', $showIds); + return $this; + } + + /** + * Creates the full facet definition, which includes the basic + * facet definition of the parent. + * + * @see \Elastica\Facet\AbstractFacet::toArray() + * @throws \Elastica\Exception\InvalidException When the right fields haven't been set. + * @return array + */ + public function toArray(){ + $this->_setFacetParam ('geo_cluster', $this->_params); + return parent::toArray(); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Facet/GeoDistance.php b/vendor/ruflin/elastica/lib/Elastica/Facet/GeoDistance.php new file mode 100644 index 00000000..35537986 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Facet/GeoDistance.php @@ -0,0 +1,66 @@ +<?php + +namespace Elastica\Facet; + +/** + * Implements the Geo Distance facet. + * + * @category Xodoa + * @package Elastica + * @author Gerard A. Matthew <gerard.matthew@gmail.com> + * @link http://www.elasticsearch.org/guide/reference/api/search/facets/geo-distance-facet.html + */ +class GeoDistance extends AbstractFacet +{ + /** + * Sets the ranges for the facet all at once. + * Sample ranges: + * array ( + * array('to' => 50), + * array('from' => 20, 'to' => 70), + * array('from' => 70, 'to' => 120), + * array('from' => 150) + * ) + * + * @param array $ranges Numerical array with range definitions. + * @return \Elastica\Facet\GeoDistance + */ + public function setRanges(array $ranges) + { + return $this->setParam('ranges', $ranges); + } + + /** + * Set the relative GeoPoint for the facet. + * + * @param string $typeField index type and field e.g foo.bar + * @param float $latitude + * @param float $longitude + * @return \Elastica\Facet\GeoDistance + */ + public function setGeoPoint($typeField, $latitude, $longitude) + { + return $this->setParam($typeField, array( + "lat" => $latitude, + "lon" => $longitude, + )); + } + + /** + * Creates the full facet definition, which includes the basic + * facet definition of the parent. + * + * @see \Elastica\Facet\AbstractFacet::toArray() + * @throws \Elastica\Exception\InvalidException When the right fields haven't been set. + * @return array + */ + public function toArray() + { + /** + * Set the geo_distance in the abstract as param. + */ + $this->_setFacetParam ('geo_distance', $this->_params); + + return parent::toArray(); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Facet/Histogram.php b/vendor/ruflin/elastica/lib/Elastica/Facet/Histogram.php new file mode 100644 index 00000000..68be6757 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Facet/Histogram.php @@ -0,0 +1,90 @@ +<?php + +namespace Elastica\Facet; + +/** + * Implements the Histogram facet. + * + * @category Xodoa + * @package Elastica + * @author Raul Martinez Jr <juneym@gmail.com> + * @link http://www.elasticsearch.org/guide/reference/api/search/facets/histogram-facet.html + */ +class Histogram extends AbstractFacet +{ + /** + * Sets the field for histogram + * + * @param string $field The name of the field for the histogram + * @return \Elastica\Facet\Histogram + */ + public function setField($field) + { + return $this->setParam('field', $field); + } + + /** + * Set the value for interval + * + * @param string $interval + * @return \Elastica\Facet\Histogram + */ + public function setInterval($interval) + { + return $this->setParam('interval', $interval); + } + + /** + * Set the fields for key_field and value_field + * + * @param string $keyField Key field + * @param string $valueField Value field + * @return \Elastica\Facet\Histogram + */ + public function setKeyValueFields($keyField, $valueField) + { + return $this->setParam('key_field', $keyField)->setParam('value_field', $valueField); + } + + /** + * Sets the key and value for this facet by script. + * + * @param string $keyScript Script to check whether it falls into the range. + * @param string $valueScript Script to use for statistical calculations. + * @return \Elastica\Facet\Histogram + */ + public function setKeyValueScripts($keyScript, $valueScript) + { + return $this->setParam('key_script', $keyScript) + ->setParam('value_script', $valueScript); + } + + /** + * Set the "params" essential to the a script + * + * @param array $params Associative array (key/value pair) + * @return \Elastica\Facet\Histogram + */ + public function setScriptParams(array $params) + { + return $this->setParam('params', $params); + } + + /** + * Creates the full facet definition, which includes the basic + * facet definition of the parent. + * + * @see \Elastica\Facet\AbstractFacet::toArray() + * @throws \Elastica\Exception\InvalidException When the right fields haven't been set. + * @return array + */ + public function toArray() + { + /** + * Set the range in the abstract as param. + */ + $this->_setFacetParam('histogram', $this->_params); + + return parent::toArray(); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Facet/Query.php b/vendor/ruflin/elastica/lib/Elastica/Facet/Query.php new file mode 100644 index 00000000..d43a2375 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Facet/Query.php @@ -0,0 +1,27 @@ +<?php + +namespace Elastica\Facet; + +use Elastica\Query\AbstractQuery; + +/** + * Query facet + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/api/search/facets/query-facet.html + */ +class Query extends AbstractFacet +{ + /** + * Set the query for the facet. + * + * @param \Elastica\Query\AbstractQuery $query + * @return \Elastica\Facet\Query + */ + public function setQuery(AbstractQuery $query) + { + return $this->_setFacetParam('query', $query->toArray()); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Facet/Range.php b/vendor/ruflin/elastica/lib/Elastica/Facet/Range.php new file mode 100644 index 00000000..194f611a --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Facet/Range.php @@ -0,0 +1,138 @@ +<?php + +namespace Elastica\Facet; + +use Elastica\Exception\InvalidException; + +/** + * Implements the range facet. + * + * @category Xodoa + * @package Elastica + * @author Jasper van Wanrooy <jasper@vanwanrooy.net> + * @link http://www.elasticsearch.org/guide/reference/api/search/facets/range-facet.html + */ +class Range extends AbstractFacet +{ + /** + * Sets the field for the range. + * + * @param string $field The name of the field for range. + * @return \Elastica\Facet\Range + */ + public function setField($field) + { + return $this->setParam('field', $field); + } + + /** + * Sets the fields by their separate key and value fields. + * + * @param string $keyField The key_field param for the range. + * @param string $valueField The key_value param for the range. + * @return \Elastica\Facet\Range + */ + public function setKeyValueFields($keyField, $valueField) + { + return $this->setParam('key_field', $keyField) + ->setParam('value_field', $valueField); + } + + /** + * Sets the key and value for this facet by script. + * + * @param string $keyScript Script to check whether it falls into the range. + * @param string $valueScript Script to use for statistical calculations. + * + * @return \Elastica\Facet\Range + */ + public function setKeyValueScripts($keyScript, $valueScript) + { + return $this->setParam('key_script', $keyScript) + ->setParam('value_script', $valueScript); + } + + /** + * Sets the ranges for the facet all at once. Sample ranges: + * array ( + * array('to' => 50), + * array('from' => 20, 'to' 70), + * array('from' => 70, 'to' => 120), + * array('from' => 150) + * ) + * + * @param array $ranges Numerical array with range definitions. + * @return \Elastica\Facet\Range + */ + public function setRanges(array $ranges) + { + return $this->setParam('ranges', $ranges); + } + + /** + * Adds a range to the range facet. + * + * @param mixed $from The from for the range. + * @param mixed $to The to for the range. + * @return \Elastica\Facet\Range + */ + public function addRange($from = null, $to = null) + { + if (!isset($this->_params['ranges']) || !is_array($this->_params['ranges'])) { + $this->_params['ranges'] = array(); + } + + $range = array(); + if (isset($from)) { + $range['from'] = $from; + } + if (isset($to)) { + $range['to'] = $to; + } + $this->_params['ranges'][] = $range; + + return $this; + } + + /** + * Creates the full facet definition, which includes the basic + * facet definition of the parent. + * + * @see \Elastica\Facet\AbstractFacet::toArray() + * @throws \Elastica\Exception\InvalidException When the right fields haven't been set. + * @return array + */ + public function toArray() + { + /** + * Check the facet for validity. + * There are three ways to set the key and value field for the range: + * - a single field for both key and value; or + * - separate fields for key and value; or + * - separate scripts for key and value. + */ + $fieldTypesSet = 0; + if (isset($this->_params['field'])) { + $fieldTypesSet++; + } + if (isset($this->_params['key_field'])) { + $fieldTypesSet++; + } + if (isset($this->_params['key_script'])) { + $fieldTypesSet++; + } + + if ($fieldTypesSet === 0) { + throw new InvalidException('Neither field, key_field nor key_script is set.'); + } elseif ($fieldTypesSet > 1) { + throw new InvalidException('Either field, key_field and key_value or key_script and value_script should be set.'); + } + + /** + * Set the range in the abstract as param. + */ + $this->_setFacetParam('range', $this->_params); + + return parent::toArray(); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Facet/Statistical.php b/vendor/ruflin/elastica/lib/Elastica/Facet/Statistical.php new file mode 100644 index 00000000..71507b8f --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Facet/Statistical.php @@ -0,0 +1,61 @@ +<?php + +namespace Elastica\Facet; + +/** + * Implements the statistical facet. + * + * @category Xodoa + * @package Elastica + * @author Robert Katzki <robert@katzki.de> + * @link http://www.elasticsearch.org/guide/reference/api/search/facets/statistical-facet.html + */ +class Statistical extends AbstractFacet +{ + /** + * Sets the field for the statistical query. + * + * @param string $field The field name for the statistical query. + * @return \Elastica\Facet\Statistical + */ + public function setField($field) + { + return $this->setParam('field', $field); + } + + /** + * Sets multiple fields for the statistical query. + * + * @param array $fields Numerical array with the fields for the statistical query. + * @return \Elastica\Facet\Statistical + */ + public function setFields(array $fields) + { + return $this->setParam('fields', $fields); + } + + /** + * Sets a script to calculate statistical information + * + * @param string $script The script to do calculations on the statistical values + * @return \Elastica\Facet\Statistical + */ + public function setScript($script) + { + return $this->setParam('script', $script); + } + + /** + * Creates the full facet definition, which includes the basic + * facet definition of the parent. + * + * @see \Elastica\Facet\AbstractFacet::toArray() + * @return array + */ + public function toArray() + { + $this->_setFacetParam('statistical', $this->_params); + + return parent::toArray(); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Facet/Terms.php b/vendor/ruflin/elastica/lib/Elastica/Facet/Terms.php new file mode 100644 index 00000000..c1dab800 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Facet/Terms.php @@ -0,0 +1,129 @@ +<?php + +namespace Elastica\Facet; + +use Elastica\Exception\InvalidException; +use Elastica\Script; + +/** + * Implements the terms facet. + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @author Jasper van Wanrooy <jasper@vanwanrooy.net> + * @link http://www.elasticsearch.org/guide/reference/api/search/facets/terms-facet.html + */ +class Terms extends AbstractFacet +{ + /** + * Holds the types of ordering which are allowed + * by Elasticsearch. + * + * @var array + */ + protected $_orderTypes = array('count', 'term', 'reverse_count', 'reverse_term'); + + /** + * Sets the field for the terms. + * + * @param string $field The field name for the terms. + * @return \Elastica\Facet\Terms + */ + public function setField($field) + { + return $this->setParam('field', $field); + } + + /** + * Sets the script for the term. + * + * @param string $script The script for the term. + * @return \Elastica\Facet\Terms + */ + public function setScript($script) + { + $script = Script::create($script); + foreach ($script->toArray() as $param => $value) { + $this->setParam($param, $value); + } + + return $this; + } + + /** + * Sets multiple fields for the terms. + * + * @param array $fields Numerical array with the fields for the terms. + * @return \Elastica\Facet\Terms + */ + public function setFields(array $fields) + { + return $this->setParam('fields', $fields); + } + + /** + * Sets the flag to return all available terms. When they + * don't have a hit, they have a count of zero. + * + * @param bool $allTerms Flag to fetch all terms. + * @return \Elastica\Facet\Terms + */ + public function setAllTerms($allTerms) + { + return $this->setParam('all_terms', (bool) $allTerms); + } + + /** + * Sets the ordering type for this facet. Elasticsearch + * internal default is count. + * + * @param string $type The order type to set use for sorting of the terms. + * @throws \Elastica\Exception\InvalidException When an invalid order type was set. + * @return \Elastica\Facet\Terms + */ + public function setOrder($type) + { + if (!in_array($type, $this->_orderTypes)) { + throw new InvalidException('Invalid order type: ' . $type); + } + + return $this->setParam('order', $type); + } + + /** + * Set an array with terms which are omitted in the search. + * + * @param array $exclude Numerical array which includes all terms which needs to be ignored. + * @return \Elastica\Facet\Terms + */ + public function setExclude(array $exclude) + { + return $this->setParam('exclude', $exclude); + } + + /** + * Sets the amount of terms to be returned. + * + * @param int $size The amount of terms to be returned. + * @return \Elastica\Facet\Terms + */ + public function setSize($size) + { + return $this->setParam('size', (int) $size); + } + + /** + * Creates the full facet definition, which includes the basic + * facet definition of the parent. + * + * @see \Elastica\Facet\AbstractFacet::toArray() + * @return array + */ + public function toArray() + { + $this->_setFacetParam('terms', $this->_params); + + return parent::toArray(); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Facet/TermsStats.php b/vendor/ruflin/elastica/lib/Elastica/Facet/TermsStats.php new file mode 100644 index 00000000..61c6b39e --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Facet/TermsStats.php @@ -0,0 +1,103 @@ +<?php + +namespace Elastica\Facet; + +use Elastica\Exception\InvalidException; + +/** + * Implements the statistical facet on a per term basis. + * + * @category Xodoa + * @package Elastica + * @author Tom Michaelis <tom.michaelis@gmail.com> + * @link http://www.elasticsearch.org/guide/reference/api/search/facets/terms-stats-facet.html + */ +class TermsStats extends AbstractFacet +{ + + /** + * Holds the types of ordering which are allowed + * by Elasticsearch. + * + * @var array + */ + protected $_orderTypes = array('term', 'reverse_term', 'count', 'reverse_count', + 'total', 'reverse_total', 'min', 'reverse_min', 'max', 'reverse_max', 'mean', + 'reverse_mean'); + + /** + * Sets the key field for the query. + * + * @param string $keyField The key field name for the query. + * @return \Elastica\Facet\TermsStats + */ + public function setKeyField( $keyField ) + { + return $this->setParam( 'key_field', $keyField ); + } + + /** + * Sets a script to calculate statistical information on a per term basis + * + * @param string $valueScript The script to do calculations on the statistical values + * @return \Elastica\Facet\TermsStats + */ + public function setValueScript( $valueScript ) + { + return $this->setParam( 'value_script', $valueScript ); + } + + /** + * Sets the ordering type for this facet. Elasticsearch + * internal default is count. + * + * @param string $type The order type to set use for sorting of the terms. + * @throws \Elastica\Exception\InvalidException When an invalid order type was set. + * @return \Elastica\Facet\TermsStats + */ + public function setOrder($type) + { + if (!in_array($type, $this->_orderTypes)) { + throw new InvalidException('Invalid order type: ' . $type); + } + + return $this->setParam('order', $type); + } + + /** + * Sets a field to compute basic statistical results on + * + * @param string $valueField The field to compute statistical values for + * @return \Elastica\Facet\TermsStats + */ + public function setValueField( $valueField ) + { + return $this->setParam( 'value_field', $valueField ); + } + + /** + * Sets the amount of terms to be returned. + * + * @param int $size The amount of terms to be returned. + * @return \Elastica\Facet\Terms + */ + public function setSize($size) + { + return $this->setParam('size', (int) $size); + } + + /** + * Creates the full facet definition, which includes the basic + * facet definition of the parent. + * + * @see \Elastica\Facet\AbstractFacet::toArray() + * @return array + */ + public function toArray() + { + $this->_setFacetParam( 'terms_stats', $this->_params ); + + return parent::toArray(); + } + +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/AbstractFilter.php b/vendor/ruflin/elastica/lib/Elastica/Filter/AbstractFilter.php new file mode 100644 index 00000000..665f155f --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/AbstractFilter.php @@ -0,0 +1,57 @@ +<?php + +namespace Elastica\Filter; + +use Elastica\Exception\InvalidException; +use Elastica\Param; + +/** + * Abstract filter object. Should be extended by all filter types + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/ + */ +abstract class AbstractFilter extends Param +{ + /** + * Sets the filter cache + * + * @param boolean $cached Cached + * @return \Elastica\Filter\AbstractFilter + */ + public function setCached($cached = true) + { + return $this->setParam('_cache', (bool) $cached); + } + + /** + * Sets the filter cache key + * + * @param string $cacheKey Cache key + * @throws \Elastica\Exception\InvalidException + * @return \Elastica\Filter\AbstractFilter + */ + public function setCacheKey($cacheKey) + { + $cacheKey = (string) $cacheKey; + + if (empty($cacheKey)) { + throw new InvalidException('Invalid parameter. Has to be a non empty string'); + } + + return $this->setParam('_cache_key', (string) $cacheKey); + } + + /** + * Sets the filter name + * + * @param string $name Name + * @return \Elastica\Filter\AbstractFilter + */ + public function setName($name) + { + return $this->setParam('_name', $name); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/AbstractGeoDistance.php b/vendor/ruflin/elastica/lib/Elastica/Filter/AbstractGeoDistance.php new file mode 100644 index 00000000..997ceab7 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/AbstractGeoDistance.php @@ -0,0 +1,190 @@ +<?php + +namespace Elastica\Filter; + +use Elastica\Exception\InvalidException; + +/** + * Geo distance filter + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/geo-distance-filter.html + */ +abstract class AbstractGeoDistance extends AbstractFilter +{ + + const LOCATION_TYPE_GEOHASH = 'geohash'; + const LOCATION_TYPE_LATLON = 'latlon'; + + /** + * Location type + * + * Decides if this filter uses latitude/longitude or geohash for the location. + * Values are "latlon" or "geohash". + * + * @var string + */ + protected $_locationType = null; + + /** + * Key + * + * @var string + */ + protected $_key = null; + + /** + * Latitude + * + * @var float + */ + protected $_latitude = null; + + /** + * Longitude + * + * @var float + */ + protected $_longitude = null; + + /** + * Geohash + * + * @var string + */ + protected $_geohash = null; + + /** + * Create GeoDistance object + * + * @param string $key Key + * @param array|string $location Location as array or geohash: array('lat' => 48.86, 'lon' => 2.35) OR 'drm3btev3e86' + * @internal param string $distance Distance + */ + public function __construct($key, $location) + { + // Key + $this->setKey($key); + $this->setLocation($location); + } + + /** + * @param string $key + * @return \Elastica\Filter\AbstractGeoDistance current filter + */ + public function setKey($key) + { + $this->_key = $key; + + return $this; + } + + /** + * @param array|string $location + * @return \Elastica\Filter\AbstractGeoDistance + * @throws \Elastica\Exception\InvalidException + */ + public function setLocation($location) + { + // Location + if (is_array($location)) { // Latitude/Longitude + // Latitude + if (isset($location['lat'])) { + $this->setLatitude($location['lat']); + } else { + throw new InvalidException('$location[\'lat\'] has to be set'); + } + + // Longitude + if (isset($location['lon'])) { + $this->setLongitude($location['lon']); + } else { + throw new InvalidException('$location[\'lon\'] has to be set'); + } + } elseif (is_string($location)) { // Geohash + $this->setGeohash($location); + } else { // Invalid location + throw new InvalidException('$location has to be an array (latitude/longitude) or a string (geohash)'); + } + + return $this; + } + + /** + * @param float $latitude + * @return \Elastica\Filter\AbstractGeoDistance current filter + */ + public function setLatitude($latitude) + { + $this->_latitude = (float) $latitude; + $this->_locationType = self::LOCATION_TYPE_LATLON; + + return $this; + } + + /** + * @param float $longitude + * @return \Elastica\Filter\AbstractGeoDistance current filter + */ + public function setLongitude($longitude) + { + $this->_longitude = (float) $longitude; + $this->_locationType = self::LOCATION_TYPE_LATLON; + + return $this; + } + + /** + * @param string $geohash + * @return \Elastica\Filter\AbstractGeoDistance current filter + */ + public function setGeohash($geohash) + { + $this->_geohash = $geohash; + $this->_locationType = self::LOCATION_TYPE_GEOHASH; + + return $this; + } + + /** + * @return array|string + * @throws \Elastica\Exception\InvalidException + */ + protected function _getLocationData() + { + if ($this->_locationType === self::LOCATION_TYPE_LATLON) { // Latitude/longitude + $location = array(); + + if (isset($this->_latitude)) { // Latitude + $location['lat'] = $this->_latitude; + } else { + throw new InvalidException('Latitude has to be set'); + } + + if (isset($this->_longitude)) { // Geohash + $location['lon'] = $this->_longitude; + } else { + throw new InvalidException('Longitude has to be set'); + } + } elseif ($this->_locationType === self::LOCATION_TYPE_GEOHASH) { // Geohash + $location = $this->_geohash; + } else { // Invalid location type + throw new InvalidException('Invalid location type'); + } + + return $location; + } + + /** + * @see \Elastica\Param::toArray() + * @throws \Elastica\Exception\InvalidException + */ + public function toArray() + { + $this->setParam($this->_key, $this->_getLocationData()); + + return parent::toArray(); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/AbstractGeoShape.php b/vendor/ruflin/elastica/lib/Elastica/Filter/AbstractGeoShape.php new file mode 100644 index 00000000..3585293b --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/AbstractGeoShape.php @@ -0,0 +1,50 @@ +<?php + +namespace Elastica\Filter; + +/** + * geo_shape filter + * + * Filter pre-indexed shape definitions + * + * @category Xodoa + * @package Elastica + * @author Bennie Krijger <benniekrijger@gmail.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/geo-shape-filter/ + */ +abstract class AbstractGeoShape extends AbstractFilter +{ + const RELATION_INTERSECT = 'intersects'; + const RELATION_DISJOINT = 'disjoint'; + const RELATION_CONTAINS = 'within'; + + /** + * @var string $_path + * + * elasticsearch path of the pre-indexed shape + */ + protected $_path; + + /** + * @var string $_relation + * + * the relation of the 2 shaped: intersects, disjoint, within + */ + protected $_relation = self::RELATION_INTERSECT; + + /** + * @param string $relation + */ + public function setRelation($relation) + { + $this->_relation = $relation; + } + + /** + * @return string + */ + public function getRelation() + { + return $this->_relation; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/AbstractMulti.php b/vendor/ruflin/elastica/lib/Elastica/Filter/AbstractMulti.php new file mode 100644 index 00000000..53ef74cf --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/AbstractMulti.php @@ -0,0 +1,77 @@ +<?php + +namespace Elastica\Filter; + +/** + * Multi Abstract filter object. Should be extended by filter types composed of an array of sub filters + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +abstract class AbstractMulti extends AbstractFilter +{ + /** + * Filters + * @var array + */ + protected $_filters = array(); + + /** + * Add filter + * + * @param \Elastica\Filter\AbstractFilter $filter + * @return \Elastica\Filter\AbstractMulti + */ + public function addFilter(AbstractFilter $filter) + { + $this->_filters[] = $filter->toArray(); + + return $this; + } + + /** + * Set filters + * + * @param array $filters + * @return \Elastica\Filter\AbstractMulti + */ + public function setFilters(array $filters) + { + $this->_filters = array(); + + foreach ($filters as $filter) { + $this->addFilter($filter); + } + + return $this; + } + + /** + * @return array Filters + */ + public function getFilters() + { + return $this->_filters; + } + + /** + * @see \Elastica\Param::toArray() + */ + public function toArray() + { + $data = parent::toArray(); + $name = $this->_getBaseName(); + $filterData = $data[$name]; + + if (empty($filterData)) { + $filterData = $this->_filters; + } else { + $filterData['filters'] = $this->_filters; + } + + $data[$name] = $filterData; + + return $data; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/Bool.php b/vendor/ruflin/elastica/lib/Elastica/Filter/Bool.php new file mode 100644 index 00000000..aff708f8 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/Bool.php @@ -0,0 +1,146 @@ +<?php + +namespace Elastica\Filter; + +use Elastica\Exception\InvalidException; + +/** + * Bool Filter + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/bool-query.html + */ +class Bool extends AbstractFilter +{ + /** + * @var float + */ + protected $_boost = 1.0; + + /** + * Must + * + * @var array + */ + protected $_must = array(); + + /** + * Should + * + * @var array + */ + protected $_should = array(); + + /** + * Must not + * + * @var array + */ + protected $_mustNot = array(); + + /** + * Adds should filter + * + * @param array|\Elastica\Filter\AbstractFilter $args Filter data + * @return \Elastica\Filter\Bool Current object + */ + public function addShould($args) + { + return $this->_addFilter('should', $args); + } + + /** + * Adds must filter + * + * @param array|\Elastica\Filter\AbstractFilter $args Filter data + * @return \Elastica\Filter\Bool Current object + */ + public function addMust($args) + { + return $this->_addFilter('must', $args); + } + + /** + * Adds mustNot filter + * + * @param array|\Elastica\Filter\AbstractFilter $args Filter data + * @return \Elastica\Filter\Bool Current object + */ + public function addMustNot($args) + { + return $this->_addFilter('mustNot', $args); + } + + /** + * Adds general filter based on type + * + * @param string $type Filter type + * @param array|\Elastica\Filter\AbstractFilter $args Filter data + * @throws \Elastica\Exception\InvalidException + * @return \Elastica\Filter\Bool Current object + */ + protected function _addFilter($type, $args) + { + if ($args instanceof AbstractFilter) { + $args = $args->toArray(); + } + else if (!is_array($args)) { + throw new InvalidException('Invalid parameter. Has to be array or instance of Elastica\Filter'); + } + else{ + $parsedArgs = array(); + foreach($args as $filter){ + if($filter instanceof AbstractFilter){ + $parsedArgs[] = $filter->toArray(); + } + } + $args = $parsedArgs; + } + + $varName = '_' . $type; + $this->{$varName}[] = $args; + + return $this; + } + + /** + * Converts bool filter to array + * + * @see \Elastica\Filter\AbstractFilter::toArray() + * @return array Filter array + */ + public function toArray() + { + $args = array(); + + if (!empty($this->_must)) { + $args['bool']['must'] = $this->_must; + } + + if (!empty($this->_should)) { + $args['bool']['should'] = $this->_should; + } + + if (!empty($this->_mustNot)) { + $args['bool']['must_not'] = $this->_mustNot; + } + + return $args; + } + + /** + * Sets the boost value for this filter + * + * @param float $boost Boost + * @return \Elastica\Filter\Bool Current object + */ + public function setBoost($boost) + { + $this->_boost = $boost; + + return $this; + } + +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/BoolAnd.php b/vendor/ruflin/elastica/lib/Elastica/Filter/BoolAnd.php new file mode 100644 index 00000000..2fd19f8e --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/BoolAnd.php @@ -0,0 +1,22 @@ +<?php + +namespace Elastica\Filter; + +/** + * And Filter + * + * @category Xodoa + * @package Elastica + * @author Lee Parker, Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/and-filter.html + */ +class BoolAnd extends AbstractMulti +{ + /** + * @return string + */ + protected function _getBaseName() + { + return 'and'; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/BoolNot.php b/vendor/ruflin/elastica/lib/Elastica/Filter/BoolNot.php new file mode 100644 index 00000000..1778997b --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/BoolNot.php @@ -0,0 +1,43 @@ +<?php + +namespace Elastica\Filter; + +/** + * Not Filter + * + * @category Xodoa + * @package Elastica + * @author Lee Parker, Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/not-filter.html + */ +class BoolNot extends AbstractFilter +{ + /** + * Creates Not filter query + * + * @param \Elastica\Filter\AbstractFilter $filter Filter object + */ + public function __construct(AbstractFilter $filter) + { + $this->setFilter($filter); + } + + /** + * Set filter + * + * @param \Elastica\Filter\AbstractFilter $filter + * @return \Elastica\Filter\BoolNot + */ + public function setFilter(AbstractFilter $filter) + { + return $this->setParam('filter', $filter->toArray()); + } + + /** + * @return string + */ + protected function _getBaseName() + { + return 'not'; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/BoolOr.php b/vendor/ruflin/elastica/lib/Elastica/Filter/BoolOr.php new file mode 100644 index 00000000..6f63fc30 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/BoolOr.php @@ -0,0 +1,22 @@ +<?php + +namespace Elastica\Filter; + +/** + * Or Filter + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/or-filter.html + */ +class BoolOr extends AbstractMulti +{ + /** + * @return string + */ + protected function _getBaseName() + { + return 'or'; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/Exists.php b/vendor/ruflin/elastica/lib/Elastica/Filter/Exists.php new file mode 100644 index 00000000..6fe43e3d --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/Exists.php @@ -0,0 +1,35 @@ +<?php + +namespace Elastica\Filter; + +/** + * Exists query + * + * @category Xodoa + * @package Elastica + * @author Oleg Cherniy <oleg.cherniy@gmail.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/exists-filter.html + */ +class Exists extends AbstractFilter +{ + /** + * Construct exists filter + * + * @param string $field + */ + public function __construct($field) + { + $this->setField($field); + } + + /** + * Set field + * + * @param string $field + * @return \Elastica\Filter\Exists + */ + public function setField($field) + { + return $this->setParam('field', $field); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/GeoBoundingBox.php b/vendor/ruflin/elastica/lib/Elastica/Filter/GeoBoundingBox.php new file mode 100644 index 00000000..1462e9af --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/GeoBoundingBox.php @@ -0,0 +1,49 @@ +<?php + +namespace Elastica\Filter; + +use Elastica\Exception\InvalidException; + +/** + * Geo bounding box filter + * + * @category Xodoa + * @package Elastica + * @author Fabian Vogler <fabian@equivalence.ch> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/geo-bounding-box-filter.html + */ +class GeoBoundingBox extends AbstractFilter +{ + /** + * Construct BoundingBoxFilter + * + * @param string $key Key + * @param array $coordinates Array with top left coordinate as first and bottom right coordinate as second element + */ + public function __construct($key, array $coordinates) + { + $this->addCoordinates($key, $coordinates); + } + + /** + * Add coordinates + * + * @param string $key Key + * @param array $coordinates Array with top left coordinate as first and bottom right coordinate as second element + * @throws \Elastica\Exception\InvalidException If $coordinates doesn't have two elements + * @return \Elastica\Filter\GeoBoundingBox Current object + */ + public function addCoordinates($key, array $coordinates) + { + if (!isset($coordinates[0]) || !isset($coordinates[1])) { + throw new InvalidException('expected $coordinates to be an array with two elements'); + } + + $this->setParam($key, array( + 'top_left' => $coordinates[0], + 'bottom_right' => $coordinates[1] + )); + + return $this; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/GeoDistance.php b/vendor/ruflin/elastica/lib/Elastica/Filter/GeoDistance.php new file mode 100644 index 00000000..8e875365 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/GeoDistance.php @@ -0,0 +1,73 @@ +<?php + +namespace Elastica\Filter; + +/** + * Geo distance filter + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/geo-distance-filter.html + */ +class GeoDistance extends AbstractGeoDistance +{ + const DISTANCE_TYPE_ARC = 'arc'; + const DISTANCE_TYPE_PLANE = 'plane'; + + const OPTIMIZE_BBOX_MEMORY = 'memory'; + const OPTIMIZE_BBOX_INDEXED = 'indexed'; + const OPTIMIZE_BBOX_NONE = 'none'; + + /** + * Create GeoDistance object + * + * @param string $key Key + * @param array|string $location Location as array or geohash: array('lat' => 48.86, 'lon' => 2.35) OR 'drm3btev3e86' + * @param string $distance Distance + * @throws \Elastica\Exception\InvalidException + */ + public function __construct($key, $location, $distance) + { + parent::__construct($key, $location); + + $this->setDistance($distance); + } + + /** + * @param string $distance + * @return \Elastica\Filter\GeoDistance current filter + */ + public function setDistance($distance) + { + $this->setParam('distance', $distance); + + return $this; + } + + /** + * See DISTANCE_TYPE_* constants + * + * @param string $distanceType + * @return \Elastica\Filter\GeoDistance current filter + */ + public function setDistanceType($distanceType) + { + $this->setParam('distance_type', $distanceType); + + return $this; + } + + /** + * See OPTIMIZE_BBOX_* constants + * + * @param string $optimizeBbox + * @return \Elastica\Filter\GeoDistance current filter + */ + public function setOptimizeBbox($optimizeBbox) + { + $this->setParam('optimize_bbox', $optimizeBbox); + + return $this; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/GeoDistanceRange.php b/vendor/ruflin/elastica/lib/Elastica/Filter/GeoDistanceRange.php new file mode 100644 index 00000000..230e5ebf --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/GeoDistanceRange.php @@ -0,0 +1,101 @@ +<?php + +namespace Elastica\Filter; + +use Elastica\Exception\InvalidException; + +/** + * Geo distance filter + * + * @category Xodoa + * @package Elastica + * @author munkie + * @link http://www.elasticsearch.org/guide/reference/query-dsl/geo-distance-range-filter.html + */ +class GeoDistanceRange extends AbstractGeoDistance +{ + const RANGE_FROM = 'from'; + const RANGE_TO = 'to'; + const RANGE_LT = 'lt'; + const RANGE_LTE = 'lte'; + const RANGE_GT = 'gt'; + const RANGE_GTE = 'gte'; + + const RANGE_INCLUDE_LOWER = 'include_lower'; + const RANGE_INCLUDE_UPPER = 'include_upper'; + + /** + * @var array + */ + protected $_ranges = array(); + + /** + * @param string $key + * @param array|string $location + * @param array $ranges + * @internal param string $distance + */ + public function __construct($key, $location, array $ranges = array()) + { + parent::__construct($key, $location); + + if (!empty($ranges)) { + $this->setRanges($ranges); + } + } + + /** + * @param array $ranges + * @return \Elastica\Filter\GeoDistanceRange + */ + public function setRanges(array $ranges) + { + $this->_ranges = array(); + + foreach ($ranges as $key => $value) { + $this->setRange($key, $value); + } + + return $this; + } + + /** + * @param string $key + * @param mixed $value + * @return \Elastica\Filter\GeoDistanceRange + * @throws \Elastica\Exception\InvalidException + */ + public function setRange($key, $value) + { + switch ($key) { + case self::RANGE_TO: + case self::RANGE_FROM: + case self::RANGE_GT: + case self::RANGE_GTE: + case self::RANGE_LT: + case self::RANGE_LTE: + break; + case self::RANGE_INCLUDE_LOWER: + case self::RANGE_INCLUDE_UPPER: + $value = (boolean) $value; + break; + default: + throw new InvalidException('Invalid range parameter given: ' . $key); + } + $this->_ranges[$key] = $value; + + return $this; + } + + /** + * @return array + */ + public function toArray() + { + foreach ($this->_ranges as $key => $value) { + $this->setParam($key, $value); + } + + return parent::toArray(); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/GeoPolygon.php b/vendor/ruflin/elastica/lib/Elastica/Filter/GeoPolygon.php new file mode 100644 index 00000000..fa12c035 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/GeoPolygon.php @@ -0,0 +1,59 @@ +<?php + +namespace Elastica\Filter; + +use Elastica\Filter\AbstractFilter; + +/** + * Geo polygon filter + * + * @category Xodoa + * @package Elastica + * @author Michael Maclean <mgdm@php.net> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/geo-polygon-filter.html + */ +class GeoPolygon extends AbstractFilter +{ + /** + * Key + * + * @var string Key + */ + protected $_key = ''; + + /** + * Points making up polygon + * + * @var array Points making up polygon + */ + protected $_points = array(); + + /** + * Construct polygon filter + * + * @param string $key Key + * @param array $points Points making up polygon + */ + public function __construct($key, array $points) + { + $this->_key = $key; + $this->_points = $points; + } + + /** + * Converts filter to array + * + * @see \Elastica\Filter\AbstractFilter::toArray() + * @return array + */ + public function toArray() + { + return array( + 'geo_polygon' => array( + $this->_key => array( + 'points' => $this->_points + ), + ) + ); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/GeoShapePreIndexed.php b/vendor/ruflin/elastica/lib/Elastica/Filter/GeoShapePreIndexed.php new file mode 100644 index 00000000..7e89f8a8 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/GeoShapePreIndexed.php @@ -0,0 +1,85 @@ +<?php + +namespace Elastica\Filter; + +/** + * geo_shape filter for pre-indexed shapes + * + * Filter pre-indexed shape definitions + * + * @category Xodoa + * @package Elastica + * @author Bennie Krijger <benniekrijger@gmail.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/geo-shape-filter/ + */ +class GeoShapePreIndexed extends AbstractGeoShape +{ + /** + * elasticsearch id of the pre-indexed shape + * + * @var string + */ + protected $_indexedId; + + /** + * elasticsearch type of the pre-indexed shape + * + * @var string + */ + protected $_indexedType; + + /** + * elasticsearch index of the pre-indexed shape + * + * @var string + */ + protected $_indexedIndex; + + /** + * elasticsearch path/field name of the pre-indexed shape + * + * @var string + */ + protected $_indexedPath; + + /** + * Construct geo_shape filter with a pre-indexed shape + * + * @param string $path The path/field of the shape searched + * @param string $indexedId Id of the pre-indexed shape + * @param string $indexedType Type of the pre-indexed shape + * @param string $indexedIndex Index of the pre-indexed shape + * @param string $indexedPath Path of the pre-indexed shape + */ + public function __construct($path, $indexedId, $indexedType, $indexedIndex, $indexedPath) + { + $this->_path = $path; + $this->_indexedId = $indexedId; + $this->_indexedType = $indexedType; + $this->_indexedIndex = $indexedIndex; + $this->_indexedPath = $indexedPath; + } + + /** + * Converts filter to array + * + * @see \Elastica\Filter\AbstractFilter::toArray() + * @return array + */ + public function toArray() + { + return array( + 'geo_shape' => array( + $this->_path => array( + 'indexed_shape' => array( + 'id' => $this->_indexedId, + 'type' => $this->_indexedType, + 'index' => $this->_indexedIndex, + 'path' => $this->_indexedPath + ), + 'relation' => $this->_relation + ) + ) + ); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/GeoShapeProvided.php b/vendor/ruflin/elastica/lib/Elastica/Filter/GeoShapeProvided.php new file mode 100644 index 00000000..5a88c05f --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/GeoShapeProvided.php @@ -0,0 +1,74 @@ +<?php + +namespace Elastica\Filter; + +/** + * geo_shape filter or provided shapes + * + * Filter provided shape definitions + * + * @category Xodoa + * @package Elastica + * @author BennieKrijger <benniekrijger@gmail.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/geo-shape-filter/ + */ +class GeoShapeProvided extends AbstractGeoShape +{ + const TYPE_ENVELOPE = 'envelope'; + const TYPE_MULTIPOINT = 'multipoint'; + const TYPE_POINT = 'point'; + const TYPE_MULTIPOLYGON = 'multipolygon'; + const TYPE_LINESTRING = 'linestring'; + const TYPE_POLYGON = 'polygon'; + + /** + * Type of the geo_shape + * + * @var string + */ + protected $_shapeType; + + /** + * Coordinates making up geo_shape + * + * @var array Coordinates making up geo_shape + */ + protected $_coordinates; + + /** + * Construct geo_shape filter + * + * @param string $path The path/field of the shape searched + * @param array $coordinates Points making up the shape + * @param string $shapeType Type of the geo_shape: + * point, envelope, linestring, polygon, + * multipoint or multipolygon + */ + public function __construct($path, array $coordinates, $shapeType = self::TYPE_ENVELOPE) + { + $this->_path = $path; + $this->_shapeType = $shapeType; + $this->_coordinates = $coordinates; + } + + /** + * Converts filter to array + * + * @see \Elastica\Filter\AbstractFilter::toArray() + * @return array + */ + public function toArray() + { + return array( + 'geo_shape' => array( + $this->_path => array( + 'shape' => array( + 'type' => $this->_shapeType, + 'coordinates' => $this->_coordinates + ), + 'relation' => $this->_relation + ), + ) + ); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/GeohashCell.php b/vendor/ruflin/elastica/lib/Elastica/Filter/GeohashCell.php new file mode 100644 index 00000000..d14b25fe --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/GeohashCell.php @@ -0,0 +1,45 @@ +<?php + +namespace Elastica\Filter; + + +/** + * Class GeohashCell + * @package Elastica + * @link http://www.elasticsearch.org/guide/reference/query-dsl/geohash-cell-filter/ + */ +class GeohashCell extends AbstractGeoDistance +{ + /** + * @param string $key The field on which to filter + * @param array|string $location Location as coordinates array or geohash string ['lat' => 40.3, 'lon' => 45.2] + * @param $precision Integer length of geohash prefix or distance (3, or "50m") + * @param bool $neighbors If true, filters cells next to the given cell. + */ + public function __construct($key, $location, $precision = -1, $neighbors = false) + { + parent::__construct($key, $location); + $this->setPrecision($precision); + $this->setNeighbors($neighbors); + } + + /** + * Set the precision for this filter + * @param string|int $precision Integer length of geohash prefix or distance (3, or "50m") + * @return \Elastica\Filter\GeohashCell + */ + public function setPrecision($precision) + { + return $this->setParam('precision', $precision); + } + + /** + * Set the neighbors option for this filter + * @param bool $neighbors If true, filters cells next to the given cell. + * @return \Elastica\Filter\GeohashCell + */ + public function setNeighbors($neighbors) + { + return $this->setParam('neighbors', (bool)$neighbors); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/HasChild.php b/vendor/ruflin/elastica/lib/Elastica/Filter/HasChild.php new file mode 100644 index 00000000..e8c6ab96 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/HasChild.php @@ -0,0 +1,78 @@ +<?php + +namespace Elastica\Filter; + +/** + * Returns parent documents having child docs matching the query + * + * @category Xodoa + * @package Elastica + * @author Fabian Vogler <fabian@equivalence.ch> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/has-child-filter.html + */ +class HasChild extends AbstractFilter +{ + /** + * Construct HasChild filter + * + * @param string|\Elastica\Query|\Elastica\Filter\AbstractFilter $query Query string or a Elastica\Query object or a filter + * @param string $type Parent document type + */ + public function __construct($query, $type = null) + { + $this->setType($type); + if ($query instanceof AbstractFilter) { + $this->setFilter($query); + } else { + $this->setQuery($query); + } + } + + /** + * Sets query object + * + * @param string|\Elastica\Query|\Elastica\Query\AbstractQuery $query + * @return \Elastica\Filter\HasChild Current object + */ + public function setQuery($query) + { + $query = \Elastica\Query::create($query); + $data = $query->toArray(); + + return $this->setParam('query', $data['query']); + } + + /** + * Sets the filter object + * + * @param \Elastica\Filter\AbstractFilter $filter + * @return \Elastica\Filter\HasChild Current object + */ + public function setFilter($filter) + { + $data = $filter->toArray(); + return $this->setParam('filter', $data); + } + + /** + * Set type of the parent document + * + * @param string $type Parent document type + * @return \Elastica\Filter\HasChild Current object + */ + public function setType($type) + { + return $this->setParam('type', $type); + } + + /** + * Sets the scope + * + * @param string $scope Scope + * @return \Elastica\Filter\HasChild Current object + */ + public function setScope($scope) + { + return $this->setParam('_scope', $scope); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/HasParent.php b/vendor/ruflin/elastica/lib/Elastica/Filter/HasParent.php new file mode 100644 index 00000000..de49e470 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/HasParent.php @@ -0,0 +1,77 @@ +<?php + +namespace Elastica\Filter; + +/** + * Returns child documents having parent docs matching the query + * + * @category Xodoa + * @package Elastica + * @link http://www.elasticsearch.org/guide/reference/query-dsl/has-parent-filter.html + */ +class HasParent extends AbstractFilter +{ + /** + * Construct HasParent filter + * + * @param string|\Elastica\Query|\Elastica\Filter\AbstractFilter $query Query string or a Query object or a filter + * @param string $type Parent document type + */ + public function __construct($query, $type) + { + if ($query instanceof AbstractFilter) { + $this->setFilter($query); + } else { + $this->setQuery($query); + } + $this->setType($type); + } + + /** + * Sets query object + * + * @param string|\Elastica\Query|\Elastica\Query\AbstractQuery $query + * @return \Elastica\Filter\HasParent Current object + */ + public function setQuery($query) + { + $query = \Elastica\Query::create($query); + $data = $query->toArray(); + + return $this->setParam('query', $data['query']); + } + + /** + * Sets query object + * + * @param \Elastica\Filter\AbstractFilter $filter + * @return \Elastica\Filter\HasParent Current object + */ + public function setFilter($filter) + { + $data = $filter->toArray(); + return $this->setParam('filter', $data); + } + + /** + * Set type of the parent document + * + * @param string $type Parent document type + * @return \Elastica\Filter\HasParent Current object + */ + public function setType($type) + { + return $this->setParam('type', $type); + } + + /** + * Sets the scope + * + * @param string $scope Scope + * @return \Elastica\Filter\HasParent Current object + */ + public function setScope($scope) + { + return $this->setParam('_scope', $scope); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/Ids.php b/vendor/ruflin/elastica/lib/Elastica/Filter/Ids.php new file mode 100644 index 00000000..fd1d9770 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/Ids.php @@ -0,0 +1,92 @@ +<?php + +namespace Elastica\Filter; + +use Elastica\Type as ElasticaType; + +/** + * Ids Filter + * + * @category Xodoa + * @package Elastica + * @author Lee Parker, Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/ids-filter.html + */ +class Ids extends AbstractFilter +{ + /** + * Creates filter object + * + * @param string|\Elastica\Type $type Type to filter on + * @param array $ids List of ids + */ + public function __construct($type = null, array $ids = array()) + { + $this->setType($type); + $this->setIds($ids); + } + + /** + * Adds one more filter to the and filter + * + * @param string $id Adds id to filter + * @return \Elastica\Filter\Ids Current object + */ + public function addId($id) + { + return $this->addParam('values', $id); + } + + /** + * Adds one more type to query + * + * @param string|\Elastica\Type $type Type name or object + * @return \Elastica\Filter\Ids Current object + */ + public function addType($type) + { + if ($type instanceof ElasticaType) { + $type = $type->getName(); + } elseif (empty($type) && !is_numeric($type)) { + // TODO: Shouldn't this throw an exception? + // A type can be 0, but cannot be empty + return $this; + } + + return $this->addParam('type', $type); + } + + /** + * Set type + * + * @param string|\Elastica\Type $type Type name or object + * @return \Elastica\Filter\Ids Current object + */ + public function setType($type) + { + if ($type instanceof ElasticaType) { + $type = $type->getName(); + } elseif (empty($type) && !is_numeric($type)) { + // TODO: Shouldn't this throw an exception or let handling of invalid params to ES? + // A type can be 0, but cannot be empty + return $this; + } + + return $this->setParam('type', $type); + } + + /** + * Sets the ids to filter + * + * @param array|string $ids List of ids + * @return \Elastica\Filter\Ids Current object + */ + public function setIds($ids) + { + if (!is_array($ids)) { + $ids = array($ids); + } + + return $this->setParam('values', $ids); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/Indices.php b/vendor/ruflin/elastica/lib/Elastica/Filter/Indices.php new file mode 100644 index 00000000..66ca5965 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/Indices.php @@ -0,0 +1,51 @@ +<?php + +namespace Elastica\Filter; + + +/** + * Class Indices + * @package Elastica\Filter + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/0.90/query-dsl-indices-filter.html + */ +class Indices extends AbstractFilter +{ + /** + * @param AbstractFilter $filter filter which will be applied to docs in the specified indices + * @param string[] $indices + */ + public function __construct(AbstractFilter $filter, array $indices) + { + $this->setIndices($indices)->setFilter($filter); + } + + /** + * Set the names of the indices on which this filter should be applied + * @param string[] $indices + * @return Indices + */ + public function setIndices(array $indices) + { + return $this->setParam('indices', $indices); + } + + /** + * Set the filter to be applied to docs in the specified indices + * @param AbstractFilter $filter + * @return Indices + */ + public function setFilter(AbstractFilter $filter) + { + return $this->setParam('filter', $filter->toArray()); + } + + /** + * Set the filter to be applied to docs in indices which do not match those specified in the "indices" parameter + * @param AbstractFilter $filter + * @return Indices + */ + public function setNoMatchFilter(AbstractFilter $filter) + { + return $this->setParam('no_match_filter', $filter->toArray()); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/Limit.php b/vendor/ruflin/elastica/lib/Elastica/Filter/Limit.php new file mode 100644 index 00000000..e02853ae --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/Limit.php @@ -0,0 +1,36 @@ +<?php + +namespace Elastica\Filter; + +/** + * Limit Filter + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/limit-filter.html + */ +class Limit extends AbstractFilter +{ + /** + * Construct limit filter + * + * @param int $limit Limit + * @return \Elastica\Filter\Limit + */ + public function __construct($limit) + { + $this->setLimit($limit); + } + + /** + * Set the limit + * + * @param int $limit Limit + * @return \Elastica\Filter\Limit + */ + public function setLimit($limit) + { + return $this->setParam('value', (int) $limit); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/MatchAll.php b/vendor/ruflin/elastica/lib/Elastica/Filter/MatchAll.php new file mode 100644 index 00000000..a69b65a2 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/MatchAll.php @@ -0,0 +1,22 @@ +<?php + +namespace Elastica\Filter; + +/** + * Match all filter + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/match-all-filter.html + */ +class MatchAll extends AbstractFilter +{ + /** + * Creates match all filter + */ + public function __construct() + { + $this->_params = new \stdClass(); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/Missing.php b/vendor/ruflin/elastica/lib/Elastica/Filter/Missing.php new file mode 100644 index 00000000..df8466a8 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/Missing.php @@ -0,0 +1,37 @@ +<?php + +namespace Elastica\Filter; + +/** + * Missing Filter + * + * @category Xodoa + * @package Elastica + * @author Maciej Wiercinski <maciej@wiercinski.net> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/missing-filter.html + */ +class Missing extends AbstractFilter +{ + /** + * Construct missing filter + * + * @param string $field OPTIONAL + */ + public function __construct($field = '') + { + if (strlen($field)) { + $this->setField($field); + } + } + + /** + * Set field + * + * @param string $field + * @return \Elastica\Filter\Missing + */ + public function setField($field) + { + return $this->setParam('field', (string) $field); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/Nested.php b/vendor/ruflin/elastica/lib/Elastica/Filter/Nested.php new file mode 100644 index 00000000..16293519 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/Nested.php @@ -0,0 +1,60 @@ +<?php + +namespace Elastica\Filter; + +use Elastica\Query\AbstractQuery; + +/** + * Nested filter + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/nested-filter.html + */ +class Nested extends AbstractFilter +{ + /** + * Adds field to mlt filter + * + * @param string $path Nested object path + * @return \Elastica\Filter\Nested + */ + public function setPath($path) + { + return $this->setParam('path', $path); + } + + /** + * Sets nested query + * + * @param \Elastica\Query\AbstractQuery $query + * @return \Elastica\Filter\Nested + */ + public function setQuery(AbstractQuery $query) + { + return $this->setParam('query', $query->toArray()); + } + + /** + * Sets nested filter + * + * @param \Elastica\Filter\AbstractFilter $filter + * @return \Elastica\Filter\Nested + */ + public function setFilter(AbstractFilter $filter) + { + return $this->setParam('filter', $filter->toArray()); + } + + /** + * Set score mode + * + * @param string $scoreMode Options: avg, total, max and none. + * @return \Elastica\Filter\Nested + */ + public function setScoreMode($scoreMode) + { + return $this->setParam('score_mode', $scoreMode); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/NumericRange.php b/vendor/ruflin/elastica/lib/Elastica/Filter/NumericRange.php new file mode 100644 index 00000000..5a6e2551 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/NumericRange.php @@ -0,0 +1,15 @@ +<?php + +namespace Elastica\Filter; + +/** + * Numeric Range Filter + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/numeric-range-filter.html + */ +class NumericRange extends Range +{ +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/Prefix.php b/vendor/ruflin/elastica/lib/Elastica/Filter/Prefix.php new file mode 100644 index 00000000..2caf13cb --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/Prefix.php @@ -0,0 +1,79 @@ +<?php + +namespace Elastica\Filter; + +/** + * Prefix filter + * + * @category Xodoa + * @package Elastica + * @author Jasper van Wanrooy <jasper@vanwanrooy.net> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/prefix-filter.html + */ +class Prefix extends AbstractFilter +{ + /** + * Holds the name of the field for the prefix. + * + * @var string + */ + protected $_field = ''; + + /** + * Holds the prefix string. + * + * @var string + */ + protected $_prefix = ''; + + /** + * Creates prefix filter + * + * @param string $field Field name + * @param string $prefix Prefix string + */ + public function __construct($field = '', $prefix = '') + { + $this->setField($field); + $this->setPrefix($prefix); + } + + /** + * Sets the name of the prefix field. + * + * @param string $field Field name + * @return \Elastica\Filter\Prefix + */ + public function setField($field) + { + $this->_field = $field; + + return $this; + } + + /** + * Sets the prefix string. + * + * @param string $prefix Prefix string + * @return \Elastica\Filter\Prefix + */ + public function setPrefix($prefix) + { + $this->_prefix = $prefix; + + return $this; + } + + /** + * Converts object to an array + * + * @see \Elastica\Filter\AbstractFilter::toArray() + * @return array data array + */ + public function toArray() + { + $this->setParam($this->_field, $this->_prefix); + + return parent::toArray(); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/Query.php b/vendor/ruflin/elastica/lib/Elastica/Filter/Query.php new file mode 100644 index 00000000..3f1ba2d2 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/Query.php @@ -0,0 +1,90 @@ +<?php + +namespace Elastica\Filter; + +use Elastica\Exception\InvalidException; +use Elastica\Query\AbstractQuery; + +/** + * Query filter + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/query-filter.html + */ +class Query extends AbstractFilter +{ + /** + * Query + * @var array + */ + protected $_query; + + /** + * Construct query filter + * + * @param array|\Elastica\Query\AbstractQuery $query + */ + public function __construct($query = null) + { + if (!is_null($query)) { + $this->setQuery($query); + } + } + + /** + * Set query + * + * @param array|\Elastica\Query\AbstractQuery $query + * @return \Elastica\Filter\Query Query object + * @throws \Elastica\Exception\InvalidException Invalid param + */ + public function setQuery($query) + { + if (!$query instanceof AbstractQuery && ! is_array($query)) { + throw new InvalidException('expected an array or instance of Elastica\Query\AbstractQuery'); + } + + if ($query instanceof AbstractQuery) { + $query = $query->toArray(); + } + + $this->_query = $query; + + return $this; + } + + /** + * @see \Elastica\Param::_getBaseName() + */ + protected function _getBaseName() + { + if (empty($this->_params)) { + return 'query'; + } else { + return 'fquery'; + } + } + + /** + * @see \Elastica\Param::toArray() + */ + public function toArray() + { + $data = parent::toArray(); + + $name = $this->_getBaseName(); + $filterData = $data[$name]; + + if (empty($filterData)) { + $filterData = $this->_query; + } else { + $filterData['query'] = $this->_query; + } + + $data[$name] = $filterData; + + return $data; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/Range.php b/vendor/ruflin/elastica/lib/Elastica/Filter/Range.php new file mode 100644 index 00000000..b142e674 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/Range.php @@ -0,0 +1,61 @@ +<?php + +namespace Elastica\Filter; + +/** + * Range Filter + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/range-filter.html + */ +class Range extends AbstractFilter +{ + /** + * Fields + * + * @var array Fields + */ + protected $_fields = array(); + + /** + * Construct range filter + * + * @param string|bool $fieldName Field name + * @param array $args Field arguments + */ + public function __construct($fieldName = false, array $args = array()) + { + if ($fieldName) { + $this->addField($fieldName, $args); + } + } + + /** + * Ads a field with arguments to the range query + * + * @param string $fieldName Field name + * @param array $args Field arguments + * @return \Elastica\Filter\Range + */ + public function addField($fieldName, array $args) + { + $this->_fields[$fieldName] = $args; + + return $this; + } + + /** + * Converts object to array + * + * @see \Elastica\Filter\AbstractFilter::toArray() + * @return array Filter array + */ + public function toArray() + { + $this->setParams($this->_fields); + + return parent::toArray(); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/Regexp.php b/vendor/ruflin/elastica/lib/Elastica/Filter/Regexp.php new file mode 100644 index 00000000..33c47cfd --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/Regexp.php @@ -0,0 +1,80 @@ +<?php + +namespace Elastica\Filter; + +/** + * Regexp filter + * + * @category Xodoa + * @package Elastica + * @author Timothy Lamb <trash80@gmail.com> + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-regexp-filter.html + */ +class Regexp extends AbstractFilter +{ + /** + * Holds the name of the field for the regular expression. + * + * @var string + */ + protected $_field = ''; + + /** + * Holds the regexp string. + * + * @var string + */ + protected $_regexp = ''; + + /** + * Create Regexp object + * + * @param string $field Field name + * @param string $regexp Regular expression + * @throws \Elastica\Exception\InvalidException + */ + public function __construct($field = '', $regexp = '') + { + $this->setField($field); + $this->setRegexp($regexp); + } + + /** + * Sets the name of the regexp field. + * + * @param string $field Field name + * @return \Elastica\Filter\Regexp + */ + public function setField($field) + { + $this->_field = $field; + + return $this; + } + + /** + * Sets the regular expression query string. + * + * @param string $regexp Regular expression + * @return \Elastica\Filter\Regexp + */ + public function setRegexp($regexp) + { + $this->_regexp = $regexp; + + return $this; + } + + /** + * Converts object to an array + * + * @see \Elastica\Filter\AbstractFilter::toArray() + * @return array data array + */ + public function toArray() + { + $this->setParam($this->_field, $this->_regexp); + + return parent::toArray(); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/Script.php b/vendor/ruflin/elastica/lib/Elastica/Filter/Script.php new file mode 100644 index 00000000..9b34b1ec --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/Script.php @@ -0,0 +1,49 @@ +<?php + +namespace Elastica\Filter; + +use Elastica; +use Elastica\Query\AbstractQuery; + +/** + * Script filter + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/script-filter.html + */ +class Script extends AbstractFilter +{ + /** + * Query object + * + * @var array|\Elastica\Query\AbstractQuery + */ + protected $_query = null; + + /** + * Construct script filter + * + * @param array|string|\Elastica\Script $script OPTIONAL Script + */ + public function __construct($script = null) + { + if ($script) { + $this->setScript($script); + } + } + + /** + * Sets script object + * + * @param \Elastica\Script|string|array $script + * @return \Elastica\Filter\Script + */ + public function setScript($script) + { + $script = Elastica\Script::create($script); + + return $this->setParams($script->toArray()); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/Term.php b/vendor/ruflin/elastica/lib/Elastica/Filter/Term.php new file mode 100644 index 00000000..b4773030 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/Term.php @@ -0,0 +1,47 @@ +<?php + +namespace Elastica\Filter; + +/** + * Term query + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/term-filter.html + */ +class Term extends AbstractFilter +{ + /** + * Construct term filter + * + * @param array $term Term array + */ + public function __construct(array $term = array()) + { + $this->setRawTerm($term); + } + + /** + * Sets/overwrites key and term directly + * + * @param array $term Key value pair + * @return \Elastica\Filter\Term Filter object + */ + public function setRawTerm(array $term) + { + return $this->setParams($term); + } + + /** + * Adds a term to the term query + * + * @param string $key Key to query + * @param string|array $value Values(s) for the query. Boost can be set with array + * @return \Elastica\Filter\Term Filter object + */ + public function setTerm($key, $value) + { + return $this->setRawTerm(array($key => $value)); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/Terms.php b/vendor/ruflin/elastica/lib/Elastica/Filter/Terms.php new file mode 100644 index 00000000..2f7c88e3 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/Terms.php @@ -0,0 +1,132 @@ +<?php + +namespace Elastica\Filter; + +use Elastica\Exception\InvalidException; + +/** + * Terms filter + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/terms-filter.html + */ +class Terms extends AbstractFilter +{ + /** + * Terms + * + * @var array Terms + */ + protected $_terms = array(); + + /** + * Params + * + * @var array Params + */ + protected $_params = array(); + + /** + * Terms key + * + * @var string Terms key + */ + protected $_key = ''; + + /** + * Creates terms filter + * + * @param string $key Terms key + * @param array $terms Terms values + */ + public function __construct($key = '', array $terms = array()) + { + $this->setTerms($key, $terms); + } + + /** + * Sets key and terms for the filter + * + * @param string $key Terms key + * @param array $terms Terms for the query. + * @return \Elastica\Filter\Terms + */ + public function setTerms($key, array $terms) + { + $this->_key = $key; + $this->_terms = array_values($terms); + + return $this; + } + + /** + * Set the lookup parameters for this filter + * @param string $key terms key + * @param string|\Elastica\Type $type document type from which to fetch the terms values + * @param string $id id of the document from which to fetch the terms values + * @param string $path the field from which to fetch the values for the filter + * @param string|array|\Elastica\Index $options An array of options or the index from which to fetch the terms values. Defaults to the current index. + * @return \Elastica\Filter\Terms Filter object + */ + public function setLookup($key, $type, $id, $path, $options = array()) + { + $this->_key = $key; + if ($type instanceof \Elastica\Type) { + $type = $type->getName(); + } + $this->_terms = array( + 'type' => $type, + 'id' => $id, + 'path' => $path + ); + + $index = $options; + if(is_array($options)) { + if(isset($options['index'])) { + $index = $options['index']; + unset($options['index']); + } + $this->_terms = array_merge($options, $this->_terms); + } + + if (!is_null($index)) { + if ($index instanceof \Elastica\Index) { + $index = $index->getName(); + } + $this->_terms['index'] = $index; + } + return $this; + } + + /** + * Adds an additional term to the query + * + * @param string $term Filter term + * @return \Elastica\Filter\Terms Filter object + */ + public function addTerm($term) + { + $this->_terms[] = $term; + + return $this; + } + + /** + * Converts object to an array + * + * @see \Elastica\Filter\AbstractFilter::toArray() + * @throws \Elastica\Exception\InvalidException + * @return array data array + */ + public function toArray() + { + if (empty($this->_key)) { + throw new InvalidException('Terms key has to be set'); + } + $this->_params[$this->_key] = $this->_terms; + + return array('terms' => $this->_params); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Filter/Type.php b/vendor/ruflin/elastica/lib/Elastica/Filter/Type.php new file mode 100644 index 00000000..8fb58c7d --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Filter/Type.php @@ -0,0 +1,60 @@ +<?php + +namespace Elastica\Filter; + +/** + * Type Filter + * + * @category Xodoa + * @package Elastica + * @author James Wilson <jwilson556@gmail.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/type-filter.html + */ +class Type extends AbstractFilter +{ + /** + * Type name + * + * @var string + */ + protected $_type = null; + + /** + * Construct Type Filter + * + * @param string $typeName Type name + * @return \Elastica\Filter\Type + */ + public function __construct($typeName = null) + { + if ($typeName) { + $this->setType($typeName); + } + } + + /** + * Ads a field with arguments to the range query + * + * @param string $typeName Type name + * @return \Elastica\Filter\Type current object + */ + public function setType($typeName) + { + $this->_type = $typeName; + + return $this; + } + + /** + * Convert object to array + * + * @see \Elastica\Filter\AbstractFilter::toArray() + * @return array Filter array + */ + public function toArray() + { + return array( + 'type' => array('value' => $this->_type) + ); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Index.php b/vendor/ruflin/elastica/lib/Elastica/Index.php new file mode 100644 index 00000000..5e1e7138 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Index.php @@ -0,0 +1,462 @@ +<?php + +namespace Elastica; + +use Elastica\Exception\InvalidException; +use Elastica\Exception\ResponseException; +use Elastica\Index\Settings as IndexSettings; +use Elastica\Index\Stats as IndexStats; +use Elastica\Index\Status as IndexStatus; + +/** + * Elastica index object + * + * Handles reads, deletes and configurations of an index + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class Index implements SearchableInterface +{ + /** + * Index name + * + * @var string Index name + */ + protected $_name = ''; + + /** + * Client object + * + * @var \Elastica\Client Client object + */ + protected $_client = null; + + /** + * Creates a new index object + * + * All the communication to and from an index goes of this object + * + * @param \Elastica\Client $client Client object + * @param string $name Index name + * @throws \Elastica\Exception\InvalidException + */ + public function __construct(Client $client, $name) + { + $this->_client = $client; + + if (!is_string($name)) { + throw new InvalidException('Index name should be of type string'); + } + $this->_name = $name; + } + + /** + * Returns a type object for the current index with the given name + * + * @param string $type Type name + * @return \Elastica\Type Type object + */ + public function getType($type) + { + return new Type($this, $type); + } + + /** + * Returns the current status of the index + * + * @return \Elastica\Index\Status Index status + */ + public function getStatus() + { + return new IndexStatus($this); + } + + /** + * Return Index Stats + * + * @return \Elastica\Index\Stats + */ + public function getStats() + { + return new IndexStats($this); + } + + /** + * Gets all the type mappings for an index. + * + * @return array + */ + public function getMapping() + { + $path = '_mapping'; + + $response = $this->request($path, Request::GET); + $data = $response->getData(); + + // Get first entry as if index is an Alias, the name of the mapping is the real name and not alias name + $mapping = array_shift($data); + + if (isset($mapping['mappings'])) { + return $mapping['mappings']; + } + + return array(); + } + + /** + * Returns the index settings object + * + * @return \Elastica\Index\Settings Settings object + */ + public function getSettings() + { + return new IndexSettings($this); + } + + /** + * Uses _bulk to send documents to the server + * + * @param array|\Elastica\Document[] $docs Array of Elastica\Document + * @return \Elastica\Bulk\ResponseSet + * @link http://www.elasticsearch.org/guide/reference/api/bulk.html + */ + public function updateDocuments(array $docs) + { + foreach ($docs as $doc) { + $doc->setIndex($this->getName()); + } + + return $this->getClient()->updateDocuments($docs); + } + + /** + * Uses _bulk to send documents to the server + * + * @param array|\Elastica\Document[] $docs Array of Elastica\Document + * @return \Elastica\Bulk\ResponseSet + * @link http://www.elasticsearch.org/guide/reference/api/bulk.html + */ + public function addDocuments(array $docs) + { + foreach ($docs as $doc) { + $doc->setIndex($this->getName()); + } + + return $this->getClient()->addDocuments($docs); + } + + /** + * Deletes the index + * + * @return \Elastica\Response Response object + */ + public function delete() + { + $response = $this->request('', Request::DELETE); + + return $response; + } + + /** + * Uses _bulk to delete documents from the server + * + * @param array|\Elastica\Document[] $docs Array of Elastica\Document + * @return \Elastica\Bulk\ResponseSet + * @link http://www.elasticsearch.org/guide/reference/api/bulk.html + */ + public function deleteDocuments(array $docs) + { + foreach ($docs as $doc) { + $doc->setIndex($this->getName()); + } + + return $this->getClient()->deleteDocuments($docs); + } + + /** + * Optimizes search index + * + * Detailed arguments can be found here in the link + * + * @param array $args OPTIONAL Additional arguments + * @return array Server response + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-optimize.html + */ + public function optimize($args = array()) + { + $this->request('_optimize', Request::POST, array(), $args); + } + + /** + * Refreshes the index + * + * @return \Elastica\Response Response object + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-refresh.html + */ + public function refresh() + { + return $this->request('_refresh', Request::POST, array()); + } + + /** + * Creates a new index with the given arguments + * + * @param array $args OPTIONAL Arguments to use + * @param bool|array $options OPTIONAL + * bool=> Deletes index first if already exists (default = false). + * array => Associative array of options (option=>value) + * @throws \Elastica\Exception\InvalidException + * @throws \Elastica\Exception\ResponseException + * @return array Server response + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-create-index.html + */ + public function create(array $args = array(), $options = null) + { + $path = ''; + $query = array(); + + if (is_bool($options)) { + if ($options) { + try { + $this->delete(); + } catch (ResponseException $e) { + // Table can't be deleted, because doesn't exist + } + } + } else { + if (is_array($options)) { + foreach ($options as $key => $value) { + switch ($key) { + case 'recreate' : + try { + $this->delete(); + } catch (ResponseException $e) { + // Table can't be deleted, because doesn't exist + } + break; + case 'routing' : + $query = array('routing' => $value); + break; + default: + throw new InvalidException('Invalid option ' . $key); + break; + } + } + } + } + + return $this->request($path, Request::PUT, $args, $query); + } + + /** + * Checks if the given index is already created + * + * @return bool True if index exists + */ + public function exists() + { + $response = $this->getClient()->request($this->getName(), Request::HEAD); + $info = $response->getTransferInfo(); + + return (bool)($info['http_code'] == 200); + } + + /** + * @param string $query + * @param int|array $options + * @return \Elastica\Search + */ + public function createSearch($query = '', $options = null) + { + $search = new Search($this->getClient()); + $search->addIndex($this); + $search->setOptionsAndQuery($options, $query); + + return $search; + } + + /** + * Searches in this index + * + * @param string|array|\Elastica\Query $query Array with all query data inside or a Elastica\Query object + * @param int|array $options OPTIONAL Limit or associative array of options (option=>value) + * @return \Elastica\ResultSet ResultSet with all results inside + * @see \Elastica\SearchableInterface::search + */ + public function search($query = '', $options = null) + { + $search = $this->createSearch($query, $options); + + return $search->search(); + } + + /** + * Counts results of query + * + * @param string|array|\Elastica\Query $query Array with all query data inside or a Elastica\Query object + * @return int number of documents matching the query + * @see \Elastica\SearchableInterface::count + */ + public function count($query = '') + { + $search = $this->createSearch($query); + + return $search->count(); + } + + /** + * Opens an index + * + * @return \Elastica\Response Response object + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-open-close.html + */ + public function open() + { + $this->request('_open', Request::POST); + } + + /** + * Closes the index + * + * @return \Elastica\Response Response object + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-open-close.html + */ + public function close() + { + return $this->request('_close', Request::POST); + } + + /** + * Returns the index name + * + * @return string Index name + */ + public function getName() + { + return $this->_name; + } + + /** + * Returns index client + * + * @return \Elastica\Client Index client object + */ + public function getClient() + { + return $this->_client; + } + + /** + * Adds an alias to the current index + * + * @param string $name Alias name + * @param bool $replace OPTIONAL If set, an existing alias will be replaced + * @return \Elastica\Response Response + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases.html + */ + public function addAlias($name, $replace = false) + { + $path = '_aliases'; + + $data = array('actions' => array()); + + if ($replace) { + $status = new Status($this->getClient()); + foreach ($status->getIndicesWithAlias($name) as $index) { + $data['actions'][] = array('remove' => array('index' => $index->getName(), 'alias' => $name)); + } + } + + $data['actions'][] = array('add' => array('index' => $this->getName(), 'alias' => $name)); + + return $this->getClient()->request($path, Request::POST, $data); + } + + /** + * Removes an alias pointing to the current index + * + * @param string $name Alias name + * @return \Elastica\Response Response + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases.html + */ + public function removeAlias($name) + { + $path = '_aliases'; + + $data = array('actions' => array(array('remove' => array('index' => $this->getName(), 'alias' => $name)))); + + return $this->getClient()->request($path, Request::POST, $data); + } + + /** + * Clears the cache of an index + * + * @return \Elastica\Response Response object + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-clearcache.html + */ + public function clearCache() + { + $path = '_cache/clear'; + // TODO: add additional cache clean arguments + return $this->request($path, Request::POST); + } + + /** + * Flushes the index to storage + * + * @return \Elastica\Response Response object + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-flush.html + */ + public function flush($refresh = false) + { + $path = '_flush'; + return $this->request($path, Request::POST, array(), array('refresh' => $refresh)); + } + + /** + * Can be used to change settings during runtime. One example is to use + * if for bulk updating {@link http://www.elasticsearch.org/blog/2011/03/23/update-settings.html} + * + * @param array $data Data array + * @return \Elastica\Response Response object + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-update-settings.html + */ + public function setSettings(array $data) + { + return $this->request('_settings', Request::PUT, $data); + } + + /** + * Makes calls to the elasticsearch server based on this index + * + * @param string $path Path to call + * @param string $method Rest method to use (GET, POST, DELETE, PUT) + * @param array $data OPTIONAL Arguments as array + * @param array $query OPTIONAL Query params + * @return \Elastica\Response Response object + */ + public function request($path, $method, $data = array(), array $query = array()) + { + $path = $this->getName() . '/' . $path; + + return $this->getClient()->request($path, $method, $data, $query); + } + + /** + * Analyzes a string + * + * Detailed arguments can be found here in the link + * + * @param string $text String to be analyzed + * @param array $args OPTIONAL Additional arguments + * @return array Server response + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-analyze.html + */ + public function analyze($text, $args = array()) + { + $data = $this->request('_analyze', Request::POST, $text, $args)->getData(); + return $data['tokens']; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Index/Settings.php b/vendor/ruflin/elastica/lib/Elastica/Index/Settings.php new file mode 100644 index 00000000..2f2b90c6 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Index/Settings.php @@ -0,0 +1,318 @@ +<?php + +namespace Elastica\Index; + +use Elastica\Index as BaseIndex; +use Elastica\Request; + +/** + * Elastica index settings object + * + * All settings listed in the update settings API (http://www.elasticsearch.org/guide/reference/api/admin-indices-update-settings.html) + * can be changed on a running indices. To make changes like the merge policy (http://www.elasticsearch.org/guide/reference/index-modules/merge.html) + * the index has to be closed first and reopened after the call + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-update-settings.html + * @link http://www.elasticsearch.org/guide/reference/index-modules/merge.html + */ +class Settings +{ + /** + * Response + * + * @var \Elastica\Response Response object + */ + protected $_response = null; + + /** + * Stats info + * + * @var array Stats info + */ + protected $_data = array(); + + /** + * Index + * + * @var \Elastica\Index Index object + */ + protected $_index = null; + + const DEFAULT_REFRESH_INTERVAL = '1s'; + + /** + * Construct + * + * @param \Elastica\Index $index Index object + */ + public function __construct(BaseIndex $index) + { + $this->_index = $index; + } + + /** + * Returns the current settings of the index + * + * If param is set, only specified setting is return. + * 'index.' is added in front of $setting. + * + * @param string $setting OPTIONAL Setting name to return + * @return array|string|null Settings data + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-update-settings.html + */ + public function get($setting = '') + { + $requestData = $this->request()->getData(); + $data = reset($requestData); + $settings = $data['settings']['index']; + + if (!empty($setting)) { + if (isset($settings[$setting])) { + return $settings[$setting]; + } else { + if (strpos($setting, '.') !== false) { + // translate old dot-notation settings to nested arrays + $keys = explode('.', $setting); + foreach ($keys as $key) { + if (isset($settings[$key])) { + $settings = $settings[$key]; + } else { + return null; + } + } + return $settings; + } + return null; + } + } + + return $settings; + } + + /** + * Sets the number of replicas + * + * @param int $replicas Number of replicas + * @return \Elastica\Response Response object + */ + public function setNumberOfReplicas($replicas) + { + $replicas = (int)$replicas; + + $data = array('number_of_replicas' => $replicas); + + return $this->set($data); + } + + /** + * Sets the index to read only + * + * @param bool $readOnly (default = true) + * @return \Elastica\Response + */ + public function setReadOnly($readOnly = true) + { + return $this->set(array('blocks.read_only' => $readOnly)); + } + + /** + * @return bool + */ + public function getBlocksRead() + { + return (bool)$this->get('blocks.read'); + } + + /** + * @param bool $state OPTIONAL (default = true) + * @return \Elastica\Response + */ + public function setBlocksRead($state = true) + { + $state = $state ? 1 : 0; + + return $this->set(array('blocks.read' => $state)); + } + + /** + * @return bool + */ + public function getBlocksWrite() + { + return (bool)$this->get('blocks.write'); + } + + /** + * @param bool $state OPTIONAL (default = true) + * @return \Elastica\Response + */ + public function setBlocksWrite($state = true) + { + $state = $state ? 1 : 0; + + return $this->set(array('blocks.write' => (int)$state)); + } + + /** + * @return bool + */ + public function getBlocksMetadata() + { + return (bool)$this->get('blocks.metadata'); + } + + /** + * @param bool $state OPTIONAL (default = true) + * @return \Elastica\Response + */ + public function setBlocksMetadata($state = true) + { + $state = $state ? 1 : 0; + + return $this->set(array('blocks.metadata' => (int)$state)); + } + + /** + * Sets the index refresh interval + * + * Value can be for example 3s for 3 seconds or + * 5m for 5 minutes. -1 refreshing is disabled. + * + * @param int $interval Number of seconds + * @return \Elastica\Response Response object + */ + public function setRefreshInterval($interval) + { + return $this->set(array('refresh_interval' => $interval)); + } + + /** + * Returns the refresh interval + * + * If no interval is set, the default interval is returned + * + * @return string Refresh interval + */ + public function getRefreshInterval() + { + $interval = $this->get('refresh_interval'); + + if (empty($interval)) { + $interval = self::DEFAULT_REFRESH_INTERVAL; + } + + return $interval; + } + + /** + * Return merge policy + * + * @return string Merge policy type + */ + public function getMergePolicyType() + { + + return $this->get('merge.policy.type'); + } + + /** + * Sets merge policy + * + * @param string $type Merge policy type + * @return \Elastica\Response Response object + * @link http://www.elasticsearch.org/guide/reference/index-modules/merge.html + */ + public function setMergePolicyType($type) + { + $this->getIndex()->close(); + $response = $this->set(array('merge.policy.type' => $type)); + $this->getIndex()->open(); + + return $response; + } + + /** + * Sets the specific merge policies + * + * To have this changes made the index has to be closed and reopened + * + * @param string $key Merge policy key (for ex. expunge_deletes_allowed) + * @param string $value + * @return \Elastica\Response + * @link http://www.elasticsearch.org/guide/reference/index-modules/merge.html + */ + public function setMergePolicy($key, $value) + { + $this->getIndex()->close(); + $response = $this->set(array('merge.policy.' . $key => $value)); + $this->getIndex()->open(); + + return $response; + } + + /** + * Returns the specific merge policy value + * + * @param string $key Merge policy key (for ex. expunge_deletes_allowed) + * @return string Refresh interval + * @link http://www.elasticsearch.org/guide/reference/index-modules/merge.html + */ + public function getMergePolicy($key) + { + $settings = $this->get(); + if (isset($settings['merge']['policy'][$key])) { + return $settings['merge']['policy'][$key]; + } + return null; + } + + /** + * Can be used to set/update settings + * + * @param array $data Arguments + * @return \Elastica\Response Response object + */ + public function set(array $data) + { + return $this->request($data, Request::PUT); + } + + /** + * Returns the index object + * + * @return \Elastica\Index Index object + */ + public function getIndex() + { + return $this->_index; + } + + /** + * Updates the given settings for the index + * + * With elasticsearch 0.16 the following settings are supported + * - index.term_index_interval + * - index.term_index_divisor + * - index.translog.flush_threshold_ops + * - index.translog.flush_threshold_size + * - index.translog.flush_threshold_period + * - index.refresh_interval + * - index.merge.policy + * - index.auto_expand_replicas + * + * @param array $data OPTIONAL Data array + * @param string $method OPTIONAL Transfer method (default = \Elastica\Request::GET) + * @return \Elastica\Response Response object + */ + public function request(array $data = array(), $method = Request::GET) + { + $path = '_settings'; + + $data = array('index' => $data); + + return $this->getIndex()->request($path, $method, $data); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Index/Stats.php b/vendor/ruflin/elastica/lib/Elastica/Index/Stats.php new file mode 100644 index 00000000..9312e273 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Index/Stats.php @@ -0,0 +1,109 @@ +<?php + +namespace Elastica\Index; +use Elastica\Index as BaseIndex; +use Elastica\Request; + +/** + * Elastica index stats object + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-stats.html + */ +class Stats +{ + /** + * Response + * + * @var \Elastica\Response Response object + */ + protected $_response = null; + + /** + * Stats info + * + * @var array Stats info + */ + protected $_data = array(); + + /** + * Index + * + * @var \Elastica\Index Index object + */ + protected $_index = null; + + /** + * Construct + * + * @param \Elastica\Index $index Index object + */ + public function __construct(BaseIndex $index) + { + $this->_index = $index; + $this->refresh(); + } + + /** + * Returns the raw stats info + * + * @return array Stats info + */ + public function getData() + { + return $this->_data; + } + + /** + * Returns the entry in the data array based on the params. + * Various params possible. + * + * @return mixed Data array entry or null if not found + */ + public function get() + { + $data = $this->getData(); + + foreach (func_get_args() as $arg) { + if (isset($data[$arg])) { + $data = $data[$arg]; + } else { + return null; + } + } + + return $data; + } + + /** + * Returns the index object + * + * @return \Elastica\Index Index object + */ + public function getIndex() + { + return $this->_index; + } + + /** + * Returns response object + * + * @return \Elastica\Response Response object + */ + public function getResponse() + { + return $this->_response; + } + + /** + * Reloads all status data of this object + */ + public function refresh() + { + $path = '_stats'; + $this->_response = $this->getIndex()->request($path, Request::GET); + $this->_data = $this->getResponse()->getData(); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Index/Status.php b/vendor/ruflin/elastica/lib/Elastica/Index/Status.php new file mode 100644 index 00000000..6a343025 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Index/Status.php @@ -0,0 +1,144 @@ +<?php + +namespace Elastica\Index; +use Elastica\Cluster; +use Elastica\Index as BaseIndex; +use Elastica\Request; + +/** + * Elastica index status object + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-status.html + */ +class Status +{ + /** + * Response + * + * @var \Elastica\Response Response object + */ + protected $_response = null; + + /** + * Stats info + * + * @var array Stats info + */ + protected $_data = array(); + + /** + * Index + * + * @var \Elastica\Index Index object + */ + protected $_index = null; + + /** + * Construct + * + * @param \Elastica\Index $index Index object + */ + public function __construct(BaseIndex $index) + { + $this->_index = $index; + $this->refresh(); + } + + /** + * Returns all status info + * + * @return array Status info + */ + public function getData() + { + return $this->_data; + } + + /** + * Returns the entry in the data array based on the params. + * Various params possible. + * + * @return mixed Data array entry or null if not found + */ + public function get() + { + $data = $this->getData(); + $data = $data['indices'][$this->getIndex()->getName()]; + + foreach (func_get_args() as $arg) { + if (isset($data[$arg])) { + $data = $data[$arg]; + } else { + return null; + } + } + + return $data; + } + + /** + * Returns all index aliases + * + * @return array Aliases + */ + public function getAliases() + { + $responseData = $this->getIndex()->request('_aliases', \Elastica\Request::GET)->getData(); + return array_keys($responseData[$this->getIndex()->getName()]['aliases']); + } + + /** + * Returns all index settings + * + * @return array Index settings + */ + public function getSettings() + { + $responseData = $this->getIndex()->request('_settings', \Elastica\Request::GET)->getData(); + return $responseData[$this->getIndex()->getName()]['settings']; + } + + /** + * Checks if the index has the given alias + * + * @param string $name Alias name + * @return bool + */ + public function hasAlias($name) + { + return in_array($name, $this->getAliases()); + } + + /** + * Returns the index object + * + * @return \Elastica\Index Index object + */ + public function getIndex() + { + return $this->_index; + } + + /** + * Returns response object + * + * @return \Elastica\Response Response object + */ + public function getResponse() + { + return $this->_response; + } + + /** + * Reloads all status data of this object + */ + public function refresh() + { + $path = '_status'; + $this->_response = $this->getIndex()->request($path, Request::GET); + $this->_data = $this->getResponse()->getData(); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/JSON.php b/vendor/ruflin/elastica/lib/Elastica/JSON.php new file mode 100644 index 00000000..07869821 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/JSON.php @@ -0,0 +1,67 @@ +<?php + +namespace Elastica; + +use Elastica\Exception\JSONParseException; + +/** + * Elastica JSON tools + * + * @package Elastica + */ +class JSON +{ + /** + * Parse JSON string to an array + * + * @param string $json JSON string to parse + * @return array PHP array representation of JSON string + * @link http://php.net/manual/en/function.json-decode.php + * @link http://www.php.net/manual/en/function.json-last-error.php + */ + public static function parse(/* inherit from json_decode */) + { + // extract arguments + $args = func_get_args(); + + // default to decoding into an assoc array + if (sizeof($args) === 1) { + $args[] = true; + } + + // run decode + $array = call_user_func_array('json_decode', $args); + + // turn errors into exceptions for easier catching + $error = json_last_error(); + if ($error !== JSON_ERROR_NONE) { + throw new JSONParseException($error); + } + + // output + return $array; + } + + /** + * Convert input to JSON string with standard options + * + * @param mixed check args for PHP function json_encode + * @return string Valid JSON representation of $input + * @link http://php.net/manual/en/function.json-encode.php + */ + public static function stringify(/* inherit from json_encode */) + { + // extract arguments + $args = func_get_args(); + + // allow special options value for Elasticsearch compatibility + if (sizeof($args) > 1 && $args[1] === 'JSON_ELASTICSEARCH') { + // Use built in JSON constants if available (php >= 5.4) + $args[1] = (defined('JSON_UNESCAPED_SLASHES') ? JSON_UNESCAPED_SLASHES : 64) + | (defined('JSON_UNESCAPED_UNICODE') ? JSON_UNESCAPED_UNICODE : 256); + } + + // run encode and output + return call_user_func_array('json_encode', $args); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Log.php b/vendor/ruflin/elastica/lib/Elastica/Log.php new file mode 100644 index 00000000..b246a7b1 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Log.php @@ -0,0 +1,84 @@ +<?php + +namespace Elastica; + +use Elastica\JSON; +use Psr\Log\AbstractLogger; + +/** + * Elastica log object + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class Log extends AbstractLogger +{ + /** + * Log path or true if enabled + * + * @var string|bool + */ + protected $_log = true; + + /** + * Last logged message + * + * @var string Last logged message + */ + protected $_lastMessage = ''; + + /** + * Inits log object + * + * @param string|bool String to set a specific file for logging + */ + public function __construct($log = '') + { + $this->setLog($log); + } + + /** + * Log a message + * + * @param mixed $level + * @param string $message + * @param array $context + * @return null|void + */ + public function log($level, $message, array $context = array()) + { + $context['error_message'] = $message; + $this->_lastMessage = JSON::stringify($context); + + if (!empty($this->_log) && is_string($this->_log)) { + error_log($this->_lastMessage . PHP_EOL, 3, $this->_log); + } else { + error_log($this->_lastMessage); + } + + } + + /** + * Enable/disable log or set log path + * + * @param bool|string $log Enables log or sets log path + * @return \Elastica\Log + */ + public function setLog($log) + { + $this->_log = $log; + + return $this; + } + + /** + * Return last logged message + * + * @return string Last logged message + */ + public function getLastMessage() + { + return $this->_lastMessage; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Multi/ResultSet.php b/vendor/ruflin/elastica/lib/Elastica/Multi/ResultSet.php new file mode 100644 index 00000000..a0df5785 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Multi/ResultSet.php @@ -0,0 +1,208 @@ +<?php + +namespace Elastica\Multi; +use Elastica\Exception\InvalidException; +use Elastica\Response; +use Elastica\Search as BaseSearch; +use Elastica\ResultSet as BaseResultSet; + +/** + * Elastica multi search result set + * List of result sets for each search request + * + * @category Xodoa + * @package Elastica + * @author munkie + */ +class ResultSet implements \Iterator, \ArrayAccess, \Countable +{ + /** + * Result Sets + * + * @var array|\Elastica\ResultSet[] Result Sets + */ + protected $_resultSets = array(); + + /** + * Current position + * + * @var int Current position + */ + protected $_position = 0; + + /** + * Response + * + * @var \Elastica\Response Response object + */ + protected $_response; + + /** + * Constructs ResultSet object + * + * @param \Elastica\Response $response + * @param array|\Elastica\Search[] $searches + */ + public function __construct(Response $response, array $searches) + { + $this->rewind(); + $this->_init($response, $searches); + } + + /** + * @param \Elastica\Response $response + * @param array|\Elastica\Search[] $searches + * @throws \Elastica\Exception\InvalidException + */ + protected function _init(Response $response, array $searches) + { + $this->_response = $response; + $responseData = $response->getData(); + + if (isset($responseData['responses']) && is_array($responseData['responses'])) { + reset($searches); + foreach ($responseData['responses'] as $key => $responseData) { + $currentSearch = each($searches); + + if ($currentSearch === false) { + throw new InvalidException('No result found for search #' . $key); + } elseif (!$currentSearch['value'] instanceof BaseSearch) { + throw new InvalidException('Invalid object for search #' . $key . ' provided. Should be Elastica\Search'); + } + + $search = $currentSearch['value']; + $query = $search->getQuery(); + + $response = new Response($responseData); + $this->_resultSets[$currentSearch['key']] = new BaseResultSet($response, $query); + } + } + } + + /** + * @return array|\Elastica\ResultSet[] + */ + public function getResultSets() + { + return $this->_resultSets; + } + + /** + * Returns response object + * + * @return \Elastica\Response Response object + */ + public function getResponse() + { + return $this->_response; + } + + /** + * There is at least one result set with error + * + * @return bool + */ + public function hasError() + { + foreach ($this->getResultSets() as $resultSet) { + if ($resultSet->getResponse()->hasError()) { + return true; + } + } + + return false; + } + + /** + * @return bool|\Elastica\ResultSet + */ + public function current() + { + if ($this->valid()) { + return $this->_resultSets[$this->key()]; + } else { + return false; + } + } + + /** + * @return void + */ + public function next() + { + $this->_position++; + } + + /** + * @return int + */ + public function key() + { + return $this->_position; + } + + /** + * @return bool + */ + public function valid() + { + return isset($this->_resultSets[$this->key()]); + } + + /** + * @return void + */ + public function rewind() + { + $this->_position = 0; + } + + /** + * @return int + */ + public function count() + { + return count($this->_resultSets); + } + + /** + * @param string|int $offset + * @return boolean true on success or false on failure. + */ + public function offsetExists($offset) + { + return isset($this->_resultSets[$offset]); + } + + /** + * @param mixed $offset + * @return mixed Can return all value types. + */ + public function offsetGet($offset) + { + return isset($this->_resultSets[$offset]) ? $this->_resultSets[$offset] : null; + } + + /** + * @param mixed $offset + * @param mixed $value + * @return void + */ + public function offsetSet($offset, $value) + { + if (is_null($offset)) { + $this->_resultSets[] = $value; + } else { + $this->_resultSets[$offset] = $value; + } + } + + /** + * @param mixed $offset + * @return void + */ + public function offsetUnset($offset) + { + unset($this->_resultSets[$offset]); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Multi/Search.php b/vendor/ruflin/elastica/lib/Elastica/Multi/Search.php new file mode 100644 index 00000000..a9874eb2 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Multi/Search.php @@ -0,0 +1,198 @@ +<?php + +namespace Elastica\Multi; + +use Elastica\Client; +use Elastica\JSON; +use Elastica\Request; +use Elastica\Search as BaseSearch; + +/** + * Elastica multi search + * + * @category Xodoa + * @package Elastica + * @author munkie + * @link http://www.elasticsearch.org/guide/reference/api/multi-search.html + */ +class Search +{ + /** + * @var array|\Elastica\Search[] + */ + protected $_searches = array(); + + /** + * @var array + */ + protected $_options = array(); + + /** + * @var \Elastica\Client + */ + protected $_client; + + /** + * Constructs search object + * + * @param \Elastica\Client $client Client object + */ + public function __construct(Client $client) + { + $this->setClient($client); + } + + /** + * @return \Elastica\Client + */ + public function getClient() + { + return $this->_client; + } + + /** + * @param \Elastica\Client $client + * @return \Elastica\Multi\Search + */ + public function setClient(Client $client) + { + $this->_client = $client; + + return $this; + } + + /** + * @return \Elastica\Multi\Search + */ + public function clearSearches() + { + $this->_searches = array(); + + return $this; + } + + /** + * @param \Elastica\Search $search + * @param string $key Optional key + * @return \Elastica\Multi\Search + */ + public function addSearch(BaseSearch $search, $key = null) + { + if ($key) { + $this->_searches[$key] = $search; + } else { + $this->_searches[] = $search; + } + + return $this; + } + + /** + * @param array|\Elastica\Search[] $searches + * @return \Elastica\Multi\Search + */ + public function addSearches(array $searches) + { + foreach ($searches as $key => $search) { + $this->addSearch($search, $key); + } + + return $this; + } + + /** + * @param array|\Elastica\Search[] $searches + * @return \Elastica\Multi\Search + */ + public function setSearches(array $searches) + { + $this->clearSearches(); + $this->addSearches($searches); + + return $this; + } + + /** + * @return array|\Elastica\Search[] + */ + public function getSearches() + { + return $this->_searches; + } + + /** + * @param string $searchType + * @return \Elastica\Multi\Search + */ + public function setSearchType($searchType) + { + $this->_options[BaseSearch::OPTION_SEARCH_TYPE] = $searchType; + + return $this; + } + + /** + * @return \Elastica\Multi\ResultSet + */ + public function search() + { + $data = $this->_getData(); + + $response = $this->getClient()->request( + '_msearch', + Request::POST, + $data, + $this->_options + ); + + return new ResultSet($response, $this->getSearches()); + } + + /** + * @return string + */ + protected function _getData() + { + $data = ''; + foreach ($this->getSearches() as $search) { + $data.= $this->_getSearchData($search); + } + + return $data; + } + + /** + * @param \Elastica\Search $search + * @return string + */ + protected function _getSearchData(BaseSearch $search) + { + $header = $this->_getSearchDataHeader($search); + $header = (empty($header)) ? new \stdClass : $header; + $query = $search->getQuery(); + + $data = JSON::stringify($header) . "\n"; + $data.= JSON::stringify($query->toArray()) . "\n"; + + return $data; + } + + /** + * @param \Elastica\Search $search + * @return array + */ + protected function _getSearchDataHeader(BaseSearch $search) + { + $header = $search->getOptions(); + + if ($search->hasIndices()) { + $header['index'] = $search->getIndices(); + } + + if ($search->hasTypes()) { + $header['types'] = $search->getTypes(); + } + + return $header; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Node.php b/vendor/ruflin/elastica/lib/Elastica/Node.php new file mode 100644 index 00000000..a9684ca6 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Node.php @@ -0,0 +1,130 @@ +<?php + +namespace Elastica; +use Elastica\Node\Info; +use Elastica\Node\Stats; + +/** + * Elastica cluster node object + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-status.html + */ +class Node +{ + /** + * Client + * + * @var \Elastica\Client + */ + protected $_client = null; + + /** + * Node name + * + * @var string Node name + */ + protected $_name = ''; + + /** + * Node stats + * + * @var \Elastica\Node\Stats Node Stats + */ + protected $_stats = null; + + /** + * Node info + * + * @var \Elastica\Node\Info Node info + */ + protected $_info = null; + + /** + * Create a new node object + * + * @param string $name Node name + * @param \Elastica\Client $client Node object + */ + public function __construct($name, Client $client) + { + $this->_name = $name; + $this->_client = $client; + $this->refresh(); + } + + /** + * Get the name of the node + * + * @return string Node name + */ + public function getName() + { + return $this->_name; + } + + /** + * Returns the current client object + * + * @return \Elastica\Client Client + */ + public function getClient() + { + return $this->_client; + } + + /** + * Return stats object of the current node + * + * @return \Elastica\Node\Stats Node stats + */ + public function getStats() + { + if (!$this->_stats) { + $this->_stats = new Stats($this); + } + + return $this->_stats; + } + + /** + * Return info object of the current node + * + * @return \Elastica\Node\Info Node info object + */ + public function getInfo() + { + if (!$this->_info) { + $this->_info = new Info($this); + } + + return $this->_info; + } + + /** + * Refreshes all node information + * + * This should be called after updating a node to refresh all information + */ + public function refresh() + { + $this->_stats = null; + $this->_info = null; + } + + /** + * Shuts this node down + * + * @param string $delay OPTIONAL Delay after which node is shut down (default = 1s) + * @return \Elastica\Response + * @link http://www.elasticsearch.org/guide/reference/api/admin-cluster-nodes-shutdown.html + */ + public function shutdown($delay = '1s') + { + $path = '_cluster/nodes/' . $this->getName() . '/_shutdown?delay=' . $delay; + + return $this->_client->request($path, Request::POST); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Node/Info.php b/vendor/ruflin/elastica/lib/Elastica/Node/Info.php new file mode 100644 index 00000000..1d04e53d --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Node/Info.php @@ -0,0 +1,196 @@ +<?php + +namespace Elastica\Node; + +use Elastica\Node as BaseNode; +use Elastica\Request; + +/** + * Elastica cluster node object + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-status.html + */ +class Info +{ + /** + * Response + * + * @var \Elastica\Response Response object + */ + protected $_response = null; + + /** + * Stats data + * + * @var array stats data + */ + protected $_data = array(); + + /** + * Node + * + * @var \Elastica\Node Node object + */ + protected $_node = null; + + /** + * Query parameters + * + * @var array + */ + protected $_params = array(); + + /** + * Create new info object for node + * + * @param \Elastica\Node $node Node object + * @param array $params List of params to return. Can be: settings, os, process, jvm, thread_pool, network, transport, http + */ + public function __construct(BaseNode $node, array $params = array()) + { + $this->_node = $node; + $this->refresh($params); + } + + /** + * Returns the entry in the data array based on the params. + * Several params possible. + * + * Example 1: get('os', 'mem', 'total') returns total memory of the system the + * node is running on + * Example 2: get('os', 'mem') returns an array with all mem infos + * + * @return mixed Data array entry or null if not found + */ + public function get() + { + $data = $this->getData(); + + foreach (func_get_args() as $arg) { + if (isset($data[$arg])) { + $data = $data[$arg]; + } else { + return null; + } + } + + return $data; + } + + /** + * Return port of the node + * + * @return string Returns Node port + */ + public function getPort() + { + // Returns string in format: inet[/192.168.1.115:9201] + $data = $this->get('http_address'); + $data = substr($data, 6, strlen($data) - 7); + $data = explode(':', $data); + + return $data[1]; + } + + /** + * Return IP of the node + * + * @return string Returns Node ip address + */ + public function getIp() + { + // Returns string in format: inet[/192.168.1.115:9201] + $data = $this->get('http_address'); + $data = substr($data, 6, strlen($data) - 7); + $data = explode(':', $data); + + return $data[0]; + } + + /** + * Return data regarding plugins installed on this node + * @return array plugin data + * @link http://www.elasticsearch.org/guide/reference/api/admin-cluster-nodes-info/ + */ + public function getPlugins() + { + if(!in_array('plugins', $this->_params)) { + //Plugin data was not retrieved when refresh() was called last. Get it now. + $this->_params[] = 'plugins'; + $this->refresh($this->_params); + } + return $this->get('plugins'); + } + + /** + * Check if the given plugin is installed on this node + * @param string $name plugin name + * @return bool true if the plugin is installed, false otherwise + */ + public function hasPlugin($name) + { + foreach($this->getPlugins() as $plugin) { + if($plugin['name'] == $name) { + return true; + } + } + return false; + } + + /** + * Return all info data + * + * @return array Data array + */ + public function getData() + { + return $this->_data; + } + + /** + * Return node object + * + * @return \Elastica\Node Node object + */ + public function getNode() + { + return $this->_node; + } + + /** + * Returns response object + * + * @return \Elastica\Response Response object + */ + public function getResponse() + { + return $this->_response; + } + + /** + * Reloads all nodes information. Has to be called if informations changed + * + * @param array $params Params to return (default none). Possible options: settings, os, process, jvm, thread_pool, network, transport, http, plugin + * @return \Elastica\Response Response object + */ + public function refresh(array $params = array()) + { + $this->_params = $params; + + $path = '_nodes/' . $this->getNode()->getName(); + + if (!empty($params)) { + $path .= '?'; + foreach ($params as $param) { + $path .= $param . '=true&'; + } + } + + $this->_response = $this->getNode()->getClient()->request($path, Request::GET); + $data = $this->getResponse()->getData(); + $this->_data = reset($data['nodes']); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Node/Stats.php b/vendor/ruflin/elastica/lib/Elastica/Node/Stats.php new file mode 100644 index 00000000..d918e686 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Node/Stats.php @@ -0,0 +1,115 @@ +<?php + +namespace Elastica\Node; + +use Elastica\Node as BaseNode; +use Elastica\Request; + +/** + * Elastica cluster node object + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-status.html + */ +class Stats +{ + /** + * Response + * + * @var \Elastica\Response Response object + */ + protected $_response = null; + + /** + * Stats data + * + * @var array stats data + */ + protected $_data = array(); + + /** + * Node + * + * @var \Elastica\Node Node object + */ + protected $_node = null; + + /** + * Create new stats for node + * + * @param \Elastica\Node $node Elastica node object + */ + public function __construct(BaseNode $node) + { + $this->_node = $node; + $this->refresh(); + } + + /** + * Returns all node stats as array based on the arguments + * + * Several arguments can be use + * get('index', 'test', 'example') + * + * @return array Node stats for the given field or null if not found + */ + public function get() + { + $data = $this->getData(); + + foreach (func_get_args() as $arg) { + if (isset($data[$arg])) { + $data = $data[$arg]; + } else { + return null; + } + } + + return $data; + } + + /** + * Returns all stats data + * + * @return array Data array + */ + public function getData() + { + return $this->_data; + } + + /** + * Returns node object + * + * @return \Elastica\Node Node object + */ + public function getNode() + { + return $this->_node; + } + + /** + * Returns response object + * + * @return \Elastica\Response Response object + */ + public function getResponse() + { + return $this->_response; + } + + /** + * Reloads all nodes information. Has to be called if informations changed + * + * @return \Elastica\Response Response object + */ + public function refresh() + { + $path = '_nodes/' . $this->getNode()->getName() . '/stats'; + $this->_response = $this->getNode()->getClient()->request($path, Request::GET); + $data = $this->getResponse()->getData(); + $this->_data = reset($data['nodes']); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Param.php b/vendor/ruflin/elastica/lib/Elastica/Param.php new file mode 100644 index 00000000..38a45d14 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Param.php @@ -0,0 +1,162 @@ +<?php + +namespace Elastica; +use Elastica\Exception\InvalidException; + +/** + * Class to handle params + * + * This function can be used to handle params for queries, filter, facets + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class Param +{ + /** + * Params + * + * @var array + */ + protected $_params = array(); + + /** + * Raw Params + * + * @var array + */ + protected $_rawParams = array(); + + /** + * Converts the params to an array. A default implementation exist to create + * the an array out of the class name (last part of the class name) + * and the params + * + * @return array Filter array + */ + public function toArray() + { + $data = array($this->_getBaseName() => $this->getParams()); + + if (!empty($this->_rawParams)) { + $data = array_merge($data, $this->_rawParams); + } + + return $data; + } + + /** + * Param's name + * Picks the last part of the class name and makes it snake_case + * You can override this method if you want to change the name + * + * @return string name + */ + protected function _getBaseName() + { + return Util::getParamName($this); + } + + /** + * Sets params not inside params array + * + * @param string $key + * @param mixed $value + * @return \Elastica\Param + */ + protected function _setRawParam($key, $value) + { + $this->_rawParams[$key] = $value; + + return $this; + } + + /** + * Sets (overwrites) the value at the given key + * + * @param string $key Key to set + * @param mixed $value Key Value + * @return \Elastica\Param + */ + public function setParam($key, $value) + { + $this->_params[$key] = $value; + + return $this; + } + + /** + * Sets (overwrites) all params of this object + * + * @param array $params Parameter list + * @return \Elastica\Param + */ + public function setParams(array $params) + { + $this->_params = $params; + + return $this; + } + + /** + * Adds a param to the list. + * + * This function can be used to add an array of params + * + * @param string $key Param key + * @param mixed $value Value to set + * @return \Elastica\Param + */ + public function addParam($key, $value) + { + if($key != null) { + if (!isset($this->_params[$key])) { + $this->_params[$key] = array(); + } + + $this->_params[$key][] = $value; + } else { + $this->_params = $value; + } + + return $this; + } + + /** + * Returns a specific param + * + * @param string $key Key to return + * @return mixed Key value + * @throws \Elastica\Exception\InvalidException If requested key is not set + */ + public function getParam($key) + { + if (!$this->hasParam($key)) { + throw new InvalidException('Param ' . $key . ' does not exist'); + } + + return $this->_params[$key]; + } + + /** + * Test if a param is set + * + * @param string $key Key to test + * @return boolean True if the param is set, false otherwise + */ + public function hasParam($key) + { + return isset($this->_params[$key]); + } + + /** + * Returns the params array + * + * @return array Params + */ + public function getParams() + { + return $this->_params; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Percolator.php b/vendor/ruflin/elastica/lib/Elastica/Percolator.php new file mode 100644 index 00000000..2ec312b9 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Percolator.php @@ -0,0 +1,132 @@ +<?php + +namespace Elastica; + +/** + * Percolator class + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/api/percolate/ + */ +class Percolator +{ + /** + * Index object + * + * @var \Elastica\Index + */ + protected $_index = null; + + /** + * Construct new percolator + * + * @param \Elastica\Index $index + */ + public function __construct(Index $index) + { + $this->_index = $index; + } + + /** + * Registers a percolator query, with optional extra fields to include in the registered query. + * + * @param string $name Query name + * @param string|\Elastica\Query|\Elastica\Query\AbstractQuery $query Query to add + * @param array $fields Extra fields to include in the registered query + * and can be used to filter executed queries. + * @return \Elastica\Response + */ + public function registerQuery($name, $query, $fields = array()) + { + $path = $this->_index->getName() . '/.percolator/' . $name; + $query = Query::create($query); + + $data = array_merge($query->toArray(), $fields); + + return $this->_index->getClient()->request($path, Request::PUT, $data); + } + + /** + * Removes a percolator query + * @param string $name query name + * @return \Elastica\Response + */ + public function unregisterQuery($name) + { + $path = $this->_index->getName() . '/.percolator/' . $name; + + return $this->_index->getClient()->request($path, Request::DELETE); + } + + /** + * Match a document to percolator queries + * + * @param \Elastica\Document $doc + * @param string|\Elastica\Query|\Elastica\Query\AbstractQuery $query Query to filter the percolator queries which + * are executed. + * @param string $type + * @param array $params + * @return array With matching registered queries. + */ + public function matchDoc(Document $doc, $query = null, $type = 'type', $params = array()) + { + $path = $this->_index->getName() . '/' . $type . '/_percolate'; + $data = array('doc' => $doc->getData()); + + return $this->_percolate($path, $query, $data, $params); + } + + /** + * Percolating an existing document + * + * @param string $id + * @param string $type + * @param string|\Elastica\Query|\Elastica\Query\AbstractQuery $query Query to filter the percolator queries which + * are executed. + * @param array $params + * @return array With matching registered queries. + */ + public function matchExistingDoc($id, $type, $query = null, $params = array()) + { + $id = urlencode($id); + $path = $this->_index->getName() . '/' . $type . '/'. $id . '/_percolate'; + + return $this->_percolate($path, $query, array(), $params); + } + + /** + * @param string $path + * @param string|\Elastica\Query|\Elastica\Query\AbstractQuery $query] $query [description] + * @param array $data + * @param array $params + * @return array + */ + protected function _percolate($path, $query, $data = array(), $params = array()) + { + // Add query to filter the percolator queries which are executed. + if ($query) { + $query = Query::create($query); + $data['query'] = $query->getQuery(); + } + + $response = $this->getIndex()->getClient()->request($path, Request::GET, $data, $params); + $data = $response->getData(); + + if (isset($data['matches'])) { + return $data['matches']; + } + return array(); + } + + /** + * Return index object + * + * @return \Elastica\Index + */ + public function getIndex() + { + return $this->_index; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query.php b/vendor/ruflin/elastica/lib/Elastica/Query.php new file mode 100644 index 00000000..2f37f2ea --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query.php @@ -0,0 +1,420 @@ +<?php + +namespace Elastica; +use Elastica\Aggregation\AbstractAggregation; +use Elastica\Exception\InvalidException; +use Elastica\Exception\NotImplementedException; +use Elastica\Facet\AbstractFacet; +use Elastica\Filter\AbstractFilter; +use Elastica\Query\AbstractQuery; +use Elastica\Query\MatchAll; +use Elastica\Query\QueryString; +use Elastica\Suggest\AbstractSuggest; +use Elastica\Suggest; + +/** + * Elastica query object + * + * Creates different types of queries + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/api/search/ + */ +class Query extends Param +{ + /** + * Params + * + * @var array Params + */ + protected $_params = array(); + + /** + * Suggest query or not + * + * @var int Suggest + */ + protected $_suggest = 0; + + /** + * Creates a query object + * + * @param array|\Elastica\Query\AbstractQuery $query OPTIONAL Query object (default = null) + */ + public function __construct($query = null) + { + if (is_array($query)) { + $this->setRawQuery($query); + } elseif ($query instanceof AbstractQuery) { + $this->setQuery($query); + } elseif ($query instanceof Suggest) { + $this->setSuggest($query); + } + } + + /** + * Transforms a string or an array to a query object + * + * If query is empty, + * + * @param mixed $query + * @throws \Elastica\Exception\NotImplementedException + * @return \Elastica\Query + */ + public static function create($query) + { + switch (true) { + case $query instanceof Query: + return $query; + case $query instanceof AbstractQuery: + return new self($query); + case $query instanceof AbstractFilter: + $newQuery = new self(); + $newQuery->setFilter($query); + + return $newQuery; + case empty($query): + return new self(new MatchAll()); + case is_array($query): + return new self($query); + case is_string($query): + return new self(new QueryString($query)); + case $query instanceof AbstractSuggest: + return new self(new Suggest($query)); + + case $query instanceof Suggest: + return new self($query); + + } + + // TODO: Implement queries without + throw new NotImplementedException(); + } + + /** + * Sets query as raw array. Will overwrite all already set arguments + * + * @param array $query Query array + * @return \Elastica\Query Query object + */ + public function setRawQuery(array $query) + { + $this->_params = $query; + + return $this; + } + + /** + * Sets the query + * + * @param \Elastica\Query\AbstractQuery $query Query object + * @return \Elastica\Query Query object + */ + public function setQuery(AbstractQuery $query) + { + return $this->setParam('query', $query->toArray()); + } + + /** + * Gets the query array + * + * @return array + **/ + public function getQuery() + { + return $this->getParam('query'); + } + + /** + * Set Filter + * + * @param \Elastica\Filter\AbstractFilter $filter Filter object + * @return \Elastica\Query Current object + */ + public function setFilter(AbstractFilter $filter) + { + return $this->setParam('filter', $filter->toArray()); + } + + /** + * Sets the start from which the search results should be returned + * + * @param int $from + * @return \Elastica\Query Query object + */ + public function setFrom($from) + { + return $this->setParam('from', $from); + } + + /** + * Sets sort arguments for the query + * Replaces existing values + * + * @param array $sortArgs Sorting arguments + * @return \Elastica\Query Query object + * @link http://www.elasticsearch.org/guide/reference/api/search/sort.html + */ + public function setSort(array $sortArgs) + { + return $this->setParam('sort', $sortArgs); + } + + /** + * Adds a sort param to the query + * + * @param mixed $sort Sort parameter + * @return \Elastica\Query Query object + * @link http://www.elasticsearch.org/guide/reference/api/search/sort.html + */ + public function addSort($sort) + { + return $this->addParam('sort', $sort); + } + + /** + * Sets highlight arguments for the query + * + * @param array $highlightArgs Set all highlight arguments + * @return \Elastica\Query Query object + * @link http://www.elasticsearch.org/guide/reference/api/search/highlighting.html + */ + public function setHighlight(array $highlightArgs) + { + return $this->setParam('highlight', $highlightArgs); + } + + /** + * Adds a highlight argument + * + * @param mixed $highlight Add highlight argument + * @return \Elastica\Query Query object + * @link http://www.elasticsearch.org/guide/reference/api/search/highlighting.html + */ + public function addHighlight($highlight) + { + return $this->addParam('highlight', $highlight); + } + + /** + * Sets maximum number of results for this query + * + * @param int $size OPTIONAL Maximal number of results for query (default = 10) + * @return \Elastica\Query Query object + */ + public function setSize($size = 10) + { + return $this->setParam('size', $size); + + } + + /** + * Alias for setSize + * + * @deprecated Use the setSize() method, this method will be removed in future releases + * @param int $limit OPTIONAL Maximal number of results for query (default = 10) + * @return \Elastica\Query Query object + */ + public function setLimit($limit = 10) + { + return $this->setSize($limit); + } + + /** + * Enables explain on the query + * + * @param bool $explain OPTIONAL Enabled or disable explain (default = true) + * @return \Elastica\Query Current object + * @link http://www.elasticsearch.org/guide/reference/api/search/explain.html + */ + public function setExplain($explain = true) + { + return $this->setParam('explain', $explain); + } + + /** + * Enables version on the query + * + * @param bool $version OPTIONAL Enabled or disable version (default = true) + * @return \Elastica\Query Current object + * @link http://www.elasticsearch.org/guide/reference/api/search/version.html + */ + public function setVersion($version = true) + { + return $this->setParam('version', $version); + } + + /** + * Sets the fields to be returned by the search + * + * @param array $fields Fields to be returned + * @return \Elastica\Query Current object + * @link http://www.elasticsearch.org/guide/reference/api/search/fields.html + */ + public function setFields(array $fields) + { + return $this->setParam('fields', $fields); + } + + /** + * Set script fields + * + * @param array|\Elastica\ScriptFields $scriptFields Script fields + * @return \Elastica\Query Current object + * @link http://www.elasticsearch.org/guide/reference/api/search/script-fields.html + */ + public function setScriptFields($scriptFields) + { + if (is_array($scriptFields)) { + $scriptFields = new ScriptFields($scriptFields); + } + + return $this->setParam('script_fields', $scriptFields->toArray()); + } + + /** + * Adds a Script to the query + * + * @param string $name + * @param \Elastica\Script $script Script object + * @return \Elastica\Query Query object + */ + public function addScriptField($name, Script $script) + { + $this->_params['script_fields'][$name] = $script->toArray(); + + return $this; + } + + /** + * Sets all facets for this query object. Replaces existing facets + * + * @param array $facets List of facet objects + * @return \Elastica\Query Query object + * @link http://www.elasticsearch.org/guide/reference/api/search/facets/ + */ + public function setFacets(array $facets) + { + $this->_params['facets'] = array(); + foreach ($facets as $facet) { + $this->addFacet($facet); + } + + return $this; + } + + /** + * Adds a Facet to the query + * + * @param \Elastica\Facet\AbstractFacet $facet Facet object + * @return \Elastica\Query Query object + */ + public function addFacet(AbstractFacet $facet) + { + $this->_params['facets'][$facet->getName()] = $facet->toArray(); + + return $this; + } + + /** + * Adds an Aggregation to the query + * + * @param AbstractAggregation $agg + * @return \Elastica\Query Query object + */ + public function addAggregation(AbstractAggregation $agg) + { + if (!array_key_exists('aggs', $this->_params)) { + $this->_params['aggs'] = array(); + } + $this->_params['aggs'][$agg->getName()] = $agg->toArray(); + return $this; + } + + /** + * Converts all query params to an array + * + * @return array Query array + */ + public function toArray() + { + if (!isset($this->_params['query']) && ($this->_suggest == 0)) { + $this->setQuery(new MatchAll()); + } + + if (isset($this->_params['facets']) && 0 === count($this->_params['facets'])) { + unset($this->_params['facets']); + } + + if (isset($this->_params['post_filter']) && 0 === count($this->_params['post_filter'])) { + unset($this->_params['post_filter']); + } + + return $this->_params; + } + + /** + * Allows filtering of documents based on a minimum score + * + * @param int $minScore Minimum score to filter documents by + * @throws \Elastica\Exception\InvalidException + * @return \Elastica\Query Query object + */ + public function setMinScore($minScore) + { + if (!is_numeric($minScore)) { + throw new InvalidException('has to be numeric param'); + } + + return $this->setParam('min_score', $minScore); + } + + /** + * Add a suggest term + * + * @param \Elastica\Suggest $suggest suggestion object + */ + public function setSuggest(Suggest $suggest) + { + $this->addParam(NULL, $suggest->toArray()); + $this->_suggest = 1; + } + + /** + * Add a Rescore + * + * @param \Elastica\Rescore\AbstractRescore $suggest suggestion object + */ + public function setRescore($rescore) + { + $this->setParam('rescore', $rescore->toArray()); + } + + /** + * Sets the _source field to be returned with every hit + * + * @param array $fields Fields to be returned + * @return \Elastica\Query Current object + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/1.x/search-request-source-filtering.html + */ + public function setSource(array $fields) + { + return $this->setParam('_source', $fields); + } + + /** + * Sets post_filter argument for the query. The filter is applied after the query has executed + * @param array $post + * @return \Elastica\Query Current object + * @link http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/_filtering_queries_and_aggregations.html#_post_filter + */ + public function setPostFilter(array $post) + { + return $this->setParam("post_filter", $post); + } +} + + + diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/AbstractQuery.php b/vendor/ruflin/elastica/lib/Elastica/Query/AbstractQuery.php new file mode 100644 index 00000000..5b24ace4 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/AbstractQuery.php @@ -0,0 +1,15 @@ +<?php + +namespace Elastica\Query; +use Elastica\Param; + +/** + * Abstract query object. Should be extended by all query types. + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +abstract class AbstractQuery extends Param +{ +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/Bool.php b/vendor/ruflin/elastica/lib/Elastica/Query/Bool.php new file mode 100644 index 00000000..2b2c1157 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/Bool.php @@ -0,0 +1,92 @@ +<?php + +namespace Elastica\Query; +use Elastica\Exception\InvalidException; +use Elastica\Query\AbstractQuery; + +/** + * Bool query + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/bool-query.html + */ +class Bool extends AbstractQuery +{ + /** + * Add should part to query + * + * @param \Elastica\Query\AbstractQuery|array $args Should query + * @return \Elastica\Query\Bool Current object + */ + public function addShould($args) + { + return $this->_addQuery('should', $args); + } + + /** + * Add must part to query + * + * @param \Elastica\Query\AbstractQuery|array $args Must query + * @return \Elastica\Query\Bool Current object + */ + public function addMust($args) + { + return $this->_addQuery('must', $args); + } + + /** + * Add must not part to query + * + * @param \Elastica\Query\AbstractQuery|array $args Must not query + * @return \Elastica\Query\Bool Current object + */ + public function addMustNot($args) + { + return $this->_addQuery('must_not', $args); + } + + /** + * Adds a query to the current object + * + * @param string $type Query type + * @param \Elastica\Query\AbstractQuery|array $args Query + * @return \Elastica\Query\Bool + * @throws \Elastica\Exception\InvalidException If not valid query + */ + protected function _addQuery($type, $args) + { + if ($args instanceof AbstractQuery) { + $args = $args->toArray(); + } + + if (!is_array($args)) { + throw new InvalidException('Invalid parameter. Has to be array or instance of Elastica\Query\AbstractQuery'); + } + + return $this->addParam($type, $args); + } + + /** + * Sets boost value of this query + * + * @param float $boost Boost value + * @return \Elastica\Query\Bool Current object + */ + public function setBoost($boost) + { + return $this->setParam('boost', $boost); + } + + /** + * Set the minimum number of of should match + * + * @param int $minimumNumberShouldMatch Should match minimum + * @return \Elastica\Query\Bool Current object + */ + public function setMinimumNumberShouldMatch($minimumNumberShouldMatch) + { + return $this->setParam('minimum_number_should_match', $minimumNumberShouldMatch); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/Boosting.php b/vendor/ruflin/elastica/lib/Elastica/Query/Boosting.php new file mode 100644 index 00000000..fe429637 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/Boosting.php @@ -0,0 +1,44 @@ +<?php + +namespace Elastica\Query; + +/** + * Class Boosting + * @package Elastica\Query + * @author Balazs Nadasdi <yitsushi@gmail.com> + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-boosting-query.html + */ +class Boosting extends AbstractQuery +{ + const NEGATIVE_BOOST = 0.2; + + /** + * Set the positive query for this Boosting Query + * @param AbstractQuery $query + * @return \Elastica\Query\Boosting + */ + public function setPositiveQuery(AbstractQuery $query) + { + return $this->setParam('positive', $query->toArray()); + } + + /** + * Set the negative query for this Boosting Query + * @param AbstractQuery $query + * @return \Elastica\Query\Boosting + */ + public function setNegativeQuery(AbstractQuery $query) + { + return $this->setParam('negative', $query->toArray()); + } + + /** + * Set the negative_boost parameter for this Boosting Query + * @param Float $negativeBoost + * @return \Elastica\Query\Boosting + */ + public function setNegativeBoost($negativeBoost) + { + return $this->setParam('negative_boost', (float)$negativeBoost); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/Builder.php b/vendor/ruflin/elastica/lib/Elastica/Query/Builder.php new file mode 100644 index 00000000..2a5e8baa --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/Builder.php @@ -0,0 +1,933 @@ +<?php + +namespace Elastica\Query; + +use Elastica\Exception\InvalidException; +use Elastica\Exception\JSONParseException; +use Elastica\JSON; + +/** + * Query Builder. + * + * @category Xodoa + * @package Elastica + * @author Chris Gedrim <chris@gedr.im> + * @link http://www.elasticsearch.org/ + **/ +class Builder extends AbstractQuery +{ + /** + * Query string. + * + * @var string + */ + private $_string = '{'; + + /** + * Factory method. + * + * @param string $string JSON encoded string to use as query. + * + * @return \Elastica\Query\Builder + */ + public static function factory($string = null) + { + return new Builder($string); + } + + /** + * Constructor + * + * @param string $string JSON encoded string to use as query. + */ + public function __construct($string = null) + { + if (! $string == null) { + $this->_string .= substr($string, 1, -1); + } + } + + /** + * Output the query string. + * + * @return string + */ + public function __toString() + { + return rtrim($this->_string, ',').'}'; + } + + /** + * {@inheritdoc} + */ + public function toArray() + { + try { + return JSON::parse($this->__toString()); + } catch (JSONParseException $e) { + throw new InvalidException('The query produced is invalid'); + } + } + + /** + * Allow wildcards (*, ?) as the first character in a query. + * + * @param boolean $bool Defaults to true. + * + * @return \Elastica\Query\Builder + */ + public function allowLeadingWildcard($bool = true) + { + return $this->field('allow_leading_wildcard', (bool) $bool); + } + + /** + * Enable best effort analysis of wildcard terms. + * + * @param boolean $bool Defaults to true. + * + * @return \Elastica\Query\Builder + */ + public function analyzeWildcard($bool = true) + { + return $this->field('analyze_wildcard', (bool) $bool); + } + + /** + * Set the analyzer name used to analyze the query string. + * + * @param string $analyzer Analyzer to use. + * + * @return \Elastica\Query\Builder + */ + public function analyzer($analyzer) + { + return $this->field('analyzer', $analyzer); + } + + /** + * Autogenerate phrase queries. + * + * @param boolean $bool Defaults to true. + * + * @return \Elastica\Query\Builder + */ + public function autoGeneratePhraseQueries($bool = true) + { + return $this->field('auto_generate_phrase_queries', (bool) $bool); + } + + /** + * Bool Query. + * + * A query that matches documents matching boolean combinations of other queries. + * + * The bool query maps to Lucene BooleanQuery. + * + * It is built using one or more boolean clauses, each clause with a typed + * occurrence. + * + * The occurrence types are: must, should, must_not. + * + * @return \Elastica\Query\Builder + */ + public function bool() + { + return $this->fieldOpen('bool'); + } + + /** + * Close a 'bool' block. + * + * Alias of close() for ease of reading in source. + * + * @return \Elastica\Query\Builder + */ + public function boolClose() + { + return $this->fieldClose(); + } + + /** + * Sets the boost value of the query. + * + * @param float $boost Defaults to 1.0. + * + * @return \Elastica\Query\Builder + */ + public function boost($boost = 1.0) + { + return $this->field('boost', (float) $boost); + } + + /** + * Close a previously opened brace. + * + * @return \Elastica\Query\Builder + */ + public function close() + { + $this->_string = rtrim($this->_string, ' ,').'},'; + + return $this; + } + + /** + * Constant Score Query. + * + * A query that wraps a filter or another query and simply returns a constant + * score equal to the query boost for every document in the filter. + * + * Maps to Lucene ConstantScoreQuery. + * + * @return \Elastica\Query\Builder + */ + public function constantScore() + { + return $this->fieldOpen('constant_score'); + } + + /** + * Close a 'constant_score' block. + * + * Alias of close() for ease of reading in source. + * + * @return \Elastica\Query\Builder + */ + public function constantScoreClose() + { + return $this->fieldClose(); + } + + /** + * The default field for query terms if no prefix field is specified. + * + * @param string $field Defaults to _all. + * + * @return \Elastica\Query\Builder + */ + public function defaultField($field = '_all') + { + return $this->field('default_field', $field); + } + + /** + * The default operator used if no explicit operator is specified. + * + * For example, with a default operator of OR, the query "capital of Hungary" + * is translated to "capital OR of OR Hungary", and with default operator of + * AND, the same query is translated to "capital AND of AND Hungary". + * + * @param string $operator Defaults to OR. + * + * @return \Elastica\Query\Builder + */ + public function defaultOperator($operator = 'OR') + { + return $this->field('default_operator', $operator); + } + + /** + * Dis Max Query. + * + * A query that generates the union of documents produced by its subqueries, + * and that scores each document with the maximum score for that document as + * produced by any subquery, plus a tie breaking increment for any additional + * matching subqueries. + * + * @return \Elastica\Query\Builder + */ + public function disMax() + { + return $this->fieldOpen('dis_max'); + } + + /** + * Close a 'dis_max' block. + * + * Alias of close() for ease of reading in source. + * + * @return \Elastica\Query\Builder + */ + public function disMaxClose() + { + return $this->fieldClose(); + } + + /** + * Enable position increments in result queries. + * + * @param boolean $bool Defaults to true. + * + * @return \Elastica\Query\Builder + */ + public function enablePositionIncrements($bool = true) + { + return $this->field('enable_position_increments', (bool) $bool); + } + + /** + * Enables explanation for each hit on how its score was computed. + * + * @param boolean $value Turn on / off explain. + * + * @return \Elastica\Query\Builder + */ + public function explain($value = true) + { + return $this->field('explain', $value); + } + + /** + * Open 'facets' block. + * + * Facets provide aggregated data based on a search query. + * + * In the simple case, a facet can return facet counts for various facet + * values for a specific field. + * + * Elasticsearch supports more advanced facet implementations, such as + * statistical or date histogram facets. + * + * @return \Elastica\Query\Builder + */ + public function facets() + { + return $this->fieldOpen('facets'); + } + + /** + * Close a facets block. + * + * Alias of close() for ease of reading in source. + * + * @return \Elastica\Query\Builder + */ + public function facetsClose() + { + return $this->close(); + } + + /** + * Add a specific field / value entry. + * + * @param string $name Field to add. + * @param mixed $value Value to set. + * + * @return \Elastica\Query\Builder + */ + public function field($name, $value) + { + if (is_bool($value)) { + $value = '"'. var_export($value, true) . '"'; + } elseif (is_array($value)) { + $value = '["'.implode('","', $value).'"]'; + } else { + $value = '"'.$value.'"'; + } + + $this->_string .= '"'.$name.'":'.$value.','; + + return $this; + } + + /** + * Close a field block. + * + * Alias of close() for ease of reading in source. + * Passed parameters will be ignored, however they can be useful in source for + * seeing which field is being closed. + * + * Builder::factory() + * ->query() + * ->range() + * ->fieldOpen('created') + * ->gte('2011-07-18 00:00:00') + * ->lt('2011-07-19 00:00:00') + * ->fieldClose('created') + * ->rangeClose() + * ->queryClose(); + * + * @return \Elastica\Query\Builder + */ + public function fieldClose() + { + return $this->close(); + } + + /** + * Open a node for the specified name. + * + * @param string $name Field name. + * + * @return \Elastica\Query\Builder + */ + public function fieldOpen($name) + { + $this->_string .= '"'.$name.'":'; + $this->open(); + + return $this; + } + + /** + * Explicitly define fields to return. + * + * @param array $fields Array of fields to return. + * + * @return \Elastica\Query\Builder + */ + public function fields(array $fields) + { + $this->_string .= '"fields":['; + + foreach ($fields as $field) { + $this->_string .= '"'.$field.'",'; + } + + $this->_string = rtrim($this->_string, ',').'],'; + + return $this; + } + + /** + * Open a 'filter' block. + * + * @return \Elastica\Query\Builder + */ + public function filter() + { + return $this->fieldOpen('filter'); + } + + /** + * Close a filter block. + * + * @return \Elastica\Query\Builder + */ + public function filterClose() + { + return $this->close(); + } + + /** + * Query. + * + * @return \Elastica\Query\Builder + */ + public function filteredQuery() + { + return $this->fieldOpen('filtered'); + } + + /** + * Close a 'filtered_query' block. + * + * Alias of close() for ease of reading in source. + * + * @return \Elastica\Query\Builder + */ + public function filteredQueryClose() + { + return $this->fieldClose(); + } + + /** + * Set the from parameter (offset). + * + * @param integer $value Result number to start from. + * + * @return \Elastica\Query\Builder + */ + public function from($value = 0) + { + return $this->field('from', $value); + } + + /** + * Set the minimum similarity for fuzzy queries. + * + * @param float $value Defaults to 0.5. + * + * @return \Elastica\Query\Builder + */ + public function fuzzyMinSim($value = 0.5) + { + return $this->field('fuzzy_min_sim', (float) $value); + } + + /** + * Set the prefix length for fuzzy queries. + * + * @param integer $value Defaults to 0. + * + * @return \Elastica\Query\Builder + */ + public function fuzzyPrefixLength($value = 0) + { + return $this->field('fuzzy_prefix_length', (int) $value); + } + + /** + * Add a greater than (gt) clause. + * + * Used in range blocks. + * + * @param mixed $value Value to be gt. + * + * @return \Elastica\Query\Builder + */ + public function gt($value) + { + return $this->field('gt', $value); + } + + /** + * Add a greater than or equal to (gte) clause. + * + * Used in range blocks. + * + * @param mixed $value Value to be gte to. + * + * @return \Elastica\Query\Builder + */ + public function gte($value) + { + return $this->field('gte', $value); + } + + /** + * Automatically lower-case terms of wildcard, prefix, fuzzy, and range queries. + * + * @param boolean $bool Defaults to true. + * + * @return \Elastica\Query\Builder + */ + public function lowercaseExpandedTerms($bool = true) + { + return $this->field('lowercase_expanded_terms', (bool) $bool); + } + + /** + * Add a less than (lt) clause. + * + * Used in range blocks. + * + * @param mixed $value Value to be lt. + * + * @return \Elastica\Query\Builder + */ + public function lt($value) + { + return $this->field('lt', $value); + } + + /** + * Add a less than or equal to (lte) clause. + * + * Used in range blocks. + * + * @param mixed $value Value to be lte to. + * + * @return \Elastica\Query\Builder + */ + public function lte($value) + { + return $this->field('lte', $value); + } + + /** + * Match All Query. + * + * A query that matches all documents. + * + * Maps to Lucene MatchAllDocsQuery. + * + * @param float $boost Boost to use. + * + * @return \Elastica\Query\Builder + */ + public function matchAll($boost = null) + { + $this->fieldOpen('match_all'); + + if ( ! $boost == null && is_numeric($boost)) { + $this->field('boost', (float) $boost); + } + + return $this->close(); + } + + /** + * The minimum number of should clauses to match. + * + * @param integer $minimum Minimum number that should match. + * + * @return \Elastica\Query\Builder + */ + public function minimumNumberShouldMatch($minimum) + { + return $this->field('minimum_number_should_match', (int) $minimum); + } + + /** + * The clause (query) must appear in matching documents. + * + * @return \Elastica\Query\Builder + */ + public function must() + { + return $this->fieldOpen('must'); + } + + /** + * Close a 'must' block. + * + * Alias of close() for ease of reading in source. + * + * @return \Elastica\Query\Builder + */ + public function mustClose() + { + return $this->fieldClose(); + } + + /** + * The clause (query) must not appear in the matching documents. + * + * Note that it is not possible to search on documents that only consists of + * a must_not clauses. + * + * @return \Elastica\Query\Builder + */ + public function mustNot() + { + return $this->fieldOpen('must_not'); + } + + /** + * Close a 'must_not' block. + * + * Alias of close() for ease of reading in source. + * + * @return \Elastica\Query\Builder + */ + public function mustNotClose() + { + return $this->fieldClose(); + } + + /** + * Add an opening brace. + * + * @return \Elastica\Query\Builder + */ + public function open() + { + $this->_string .= '{'; + + return $this; + } + + /** + * Sets the default slop for phrases. + * + * If zero, then exact phrase matches are required. + * + * @param integer $value Defaults to 0. + * + * @return \Elastica\Query\Builder + */ + public function phraseSlop($value = 0) + { + return $this->field('phrase_slop', (int) $value); + } + + /** + * Query. + * + * @return \Elastica\Query\Builder + */ + public function prefix() + { + return $this->fieldOpen('prefix'); + } + + /** + * Close a 'prefix' block. + * + * Alias of close() for ease of reading in source. + * + * @return \Elastica\Query\Builder + */ + public function prefixClose() + { + return $this->fieldClose(); + } + + /** + * Queries to run within a dis_max query. + * + * @param array $queries Array of queries. + * + * @return \Elastica\Query\Builder + */ + public function queries(array $queries) + { + $this->_string .= '"queries":['; + + foreach ($queries as $query) { + $this->_string .= $query.','; + } + + $this->_string = rtrim($this->_string, ' ,').'],'; + + return $this; + } + + /** + * Open a query block. + * + * @return \Elastica\Query\Builder + */ + public function query() + { + return $this->fieldOpen('query'); + } + + /** + * Close a query block. + * + * Alias of close() for ease of reading in source. + * + * @return \Elastica\Query\Builder + */ + public function queryClose() + { + return $this->close(); + } + + /** + * Query String Query. + * + * A query that uses a query parser in order to parse its content + * + * @return \Elastica\Query\Builder + */ + public function queryString() + { + return $this->fieldOpen('query_string'); + } + + /** + * Close a 'query_string' block. + * + * Alias of close() for ease of reading in source. + * + * @return \Elastica\Query\Builder + */ + public function queryStringClose() + { + return $this->fieldClose(); + } + + /** + * Open a range block. + * + * @return \Elastica\Query\Builder + */ + public function range() + { + return $this->fieldOpen('range'); + } + + /** + * Close a range block. + * + * Alias of close() for ease of reading in source. + * + * @return \Elastica\Query\Builder + */ + public function rangeClose() + { + return $this->close(); + } + + /** + * The clause (query) should appear in the matching document. + * + * A boolean query with no must clauses, one or more should clauses must + * match a document. + * + * @return \Elastica\Query\Builder + */ + public function should() + { + return $this->fieldOpen('should'); + } + + /** + * Close a 'should' block. + * + * Alias of close() for ease of reading in source. + * + * @return \Elastica\Query\Builder + */ + public function shouldClose() + { + return $this->fieldClose(); + } + + /** + * Set the size parameter (number of records to return). + * + * @param integer $value Number of records to return. + * + * @return \Elastica\Query\Builder + */ + public function size($value = 10) + { + return $this->field('size', $value); + } + + /** + * Allows to add one or more sort on specific fields. + * + * @return \Elastica\Query\Builder + */ + public function sort() + { + return $this->fieldOpen('sort'); + } + + /** + * Close a sort block. + * + * Alias of close() for ease of reading in source. + * + * @return \Elastica\Query\Builder + */ + public function sortClose() + { + return $this->close(); + } + + /** + * Add a field to sort on. + * + * @param string $name Field to sort. + * @param boolean $reverse Reverse direction. + * + * @return \Elastica\Query\Builder + */ + public function sortField($name, $reverse = false) + { + return $this + ->fieldOpen('sort') + ->fieldOpen($name) + ->field('reverse', $reverse) + ->close() + ->close(); + } + + /** + * Sort on multiple fields + * + * @param array $fields Associative array where the keys are field names to sort on, and the + * values are the sort order: "asc" or "desc" + * + * @return \Elastica\Query\Builder + */ + public function sortFields(array $fields) + { + $this->_string .= '"sort":['; + + foreach ($fields as $fieldName => $order) { + $this->_string .= '{"'.$fieldName.'":"'.$order.'"},'; + } + + $this->_string = rtrim($this->_string, ',') . '],'; + + return $this; + } + + /** + * Term Query. + * + * Matches documents that have fields that contain a term (not analyzed). + * + * The term query maps to Lucene TermQuery. + * + * @return \Elastica\Query\Builder + */ + public function term() + { + return $this->fieldOpen('term'); + } + + /** + * Close a 'term' block. + * + * Alias of close() for ease of reading in source. + * + * @return \Elastica\Query\Builder + */ + public function termClose() + { + return $this->fieldClose(); + } + + /** + * Open a 'text_phrase' block. + * + * @return \Elastica\Query\Builder + */ + public function textPhrase() + { + return $this->fieldOpen('text_phrase'); + } + + /** + * Close a 'text_phrase' block. + * + * @return \Elastica\Query\Builder + */ + public function textPhraseClose() + { + return $this->close(); + } + + /** + * When using dis_max, the disjunction max tie breaker. + * + * @param float $multiplier Multiplier to use. + * + * @return \Elastica\Query\Builder + */ + public function tieBreakerMultiplier($multiplier) + { + return $this->field('tie_breaker_multiplier', (float) $multiplier); + } + + /** + * Query. + * + * @return \Elastica\Query\Builder + */ + public function wildcard() + { + return $this->fieldOpen('wildcard'); + } + + /** + * Close a 'wildcard' block. + * + * Alias of close() for ease of reading in source. + * + * @return \Elastica\Query\Builder + */ + public function wildcardClose() + { + return $this->fieldClose(); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/Common.php b/vendor/ruflin/elastica/lib/Elastica/Query/Common.php new file mode 100644 index 00000000..6e112769 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/Common.php @@ -0,0 +1,150 @@ +<?php + +namespace Elastica\Query; + + +/** + * Class Common + * @package Elastica + * @link http://www.elasticsearch.org/guide/reference/query-dsl/common-terms-query/ + */ +class Common extends AbstractQuery +{ + const OPERATOR_AND = 'and'; + const OPERATOR_OR = 'or'; + + /** + * @var string + */ + protected $_field; + + /** + * @var array + */ + protected $_queryParams = array(); + + /** + * @param string $field the field on which to query + * @param string $query the query string + * @param float $cutoffFrequency percentage in decimal form (.001 == 0.1%) + */ + public function __construct($field, $query, $cutoffFrequency) + { + $this->setField($field); + $this->setQuery($query); + $this->setCutoffFrequency($cutoffFrequency); + } + + /** + * Set the field on which to query + * @param string $field the field on which to query + * @return \Elastica\Query\Common + */ + public function setField($field) + { + $this->_field = $field; + return $this; + } + + /** + * Set the query string for this query + * @param string $query + * @return \Elastica\Query\Common + */ + public function setQuery($query) + { + return $this->setQueryParam('query', $query); + } + + /** + * Set the frequency below which terms will be put in the low frequency group + * @param float $frequency percentage in decimal form (.001 == 0.1%) + * @return \Elastica\Query\Common + */ + public function setCutoffFrequency($frequency) + { + return $this->setQueryParam('cutoff_frequency', (float)$frequency); + } + + /** + * Set the logic operator for low frequency terms + * @param string $operator see OPERATOR_* class constants for options + * @return \Elastica\Query\Common + */ + public function setLowFrequencyOperator($operator) + { + return $this->setQueryParam('low_freq_operator', $operator); + } + + /** + * Set the logic operator for high frequency terms + * @param string $operator see OPERATOR_* class constants for options + * @return \Elastica\Query\Common + */ + public function setHighFrequencyOperator($operator) + { + return $this->setQueryParam('high_frequency_operator', $operator); + } + + /** + * Set the minimum_should_match parameter + * @param int|string $minimum minimum number of low frequency terms which must be present + * @return \Elastica\Query\Common + * @link Possible values for minimum_should_match http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-minimum-should-match.html + */ + public function setMinimumShouldMatch($minimum) + { + return $this->setQueryParam('minimum_should_match', $minimum); + } + + /** + * Set the boost for this query + * @param float $boost + * @return \Elastica\Query\Common + */ + public function setBoost($boost) + { + return $this->setQueryParam('boost', (float)$boost); + } + + /** + * Set the analyzer for this query + * @param string $analyzer + * @return \Elastica\Query\Common + */ + public function setAnalyzer($analyzer) + { + return $this->setQueryParam('analyzer', $analyzer); + } + + /** + * Enable / disable computation of score factor based on the fraction of all query terms contained in the document + * @param bool $disable disable_coord is false by default + * @return \Elastica\Query\Common + */ + public function setDisableCoord($disable = true) + { + return $this->setQueryParam('disable_coord', (bool)$disable); + } + + /** + * Set a parameter in the body of this query + * @param string $key parameter key + * @param mixed $value parameter value + * @return \Elastica\Query\Common + */ + public function setQueryParam($key, $value) + { + $this->_queryParams[$key] = $value; + return $this; + } + + /** + * @return array + */ + public function toArray() + { + $this->setParam($this->_field, $this->_queryParams); + return parent::toArray(); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/ConstantScore.php b/vendor/ruflin/elastica/lib/Elastica/Query/ConstantScore.php new file mode 100644 index 00000000..16854600 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/ConstantScore.php @@ -0,0 +1,68 @@ +<?php + +namespace Elastica\Query; +use Elastica\Filter\AbstractFilter; + +/** + * Constant score query + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/constant-score-query.html + */ +class ConstantScore extends AbstractQuery +{ + /** + * Construct constant score query + * + * @param null|\Elastica\Filter\AbstractFilter|array $filter + */ + public function __construct($filter = null) + { + if (!is_null($filter)) { + $this->setFilter($filter); + } + } + + /** + * Set filter + * + * @param array|\Elastica\Filter\AbstractFilter $filter + * @return \Elastica\Query\ConstantScore Query object + */ + public function setFilter($filter) + { + if ($filter instanceof AbstractFilter) { + $filter = $filter->toArray(); + } + + return $this->setParam('filter', $filter); + } + + /** + * Set query + * + * @param array|\Elastica\Query\AbstractQuery $query + * @return \Elastica\Query\ConstantScore Query object + */ + public function setQuery($query) + { + if ($query instanceof AbstractQuery) { + $query = $query->toArray(); + } + + return $this->setParam('query', $query); + } + + /** + * Set boost + * + * @param float $boost + * @return \Elastica\Query\ConstantScore + */ + public function setBoost($boost) + { + return $this->setParam('boost', $boost); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/DisMax.php b/vendor/ruflin/elastica/lib/Elastica/Query/DisMax.php new file mode 100644 index 00000000..4b1d320d --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/DisMax.php @@ -0,0 +1,59 @@ +<?php + +namespace Elastica\Query; +use Elastica\Exception\InvalidException; + +/** + * DisMax query + * + * @category Xodoa + * @package Elastica + * @author Hung Tran <oohnoitz@gmail.com> + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-dis-max-query.html + */ +class DisMax extends AbstractQuery +{ + /** + * Adds a query to the current object + * + * @param \Elastica\Query\AbstractQuery|array $args Query + * @return \Elastica\Query\DisMax + * @throws \Elastica\Exception\InvalidException If not valid query + */ + public function addQuery($args) + { + if ($args instanceof AbstractQuery) { + $args = $args->toArray(); + } + + if (!is_array($args)) { + throw new InvalidException('Invalid parameter. Has to be array or instance of Elastica\Query\AbstractQuery'); + } + + return $this->addParam('queries', $args); + } + + /** + * Set boost + * + * @param float $boost + * @return \Elastica\Query\DisMax + */ + public function setBoost($boost) + { + return $this->setParam('boost', $boost); + } + + /** + * Sets tie breaker to multiplier value to balance the scores between lower and higher scoring fields. + * + * If not set, defaults to 0.0 + * + * @param float $tieBreaker + * @return \Elastica\Query\DisMax + */ + public function setTieBreaker($tieBreaker = 0.0) + { + return $this->setParam('tie_breaker', $tieBreaker); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/Filtered.php b/vendor/ruflin/elastica/lib/Elastica/Query/Filtered.php new file mode 100644 index 00000000..c28d4cdd --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/Filtered.php @@ -0,0 +1,95 @@ +<?php + +namespace Elastica\Query; + +use Elastica\Filter\AbstractFilter; +use Elastica\Exception\InvalidException; + +/** + * Filtered query. Needs a query and a filter + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/filtered-query.html + */ +class Filtered extends AbstractQuery +{ + /** + * Constructs a filtered query + * + * @param \Elastica\Query\AbstractQuery $query OPTIONAL Query object + * @param \Elastica\Filter\AbstractFilter $filter OPTIONAL Filter object + */ + public function __construct(AbstractQuery $query = null, AbstractFilter $filter = null) { + $this->setQuery($query); + $this->setFilter($filter); + } + + /** + * Sets a query + * + * @param \Elastica\Query\AbstractQuery $query Query object + * @return \Elastica\Query\Filtered Current object + */ + public function setQuery(AbstractQuery $query = null) + { + return $this->setParam('query', $query); + } + + /** + * Sets the filter + * + * @param \Elastica\Filter\AbstractFilter $filter Filter object + * @return \Elastica\Query\Filtered Current object + */ + public function setFilter(AbstractFilter $filter = null) + { + return $this->setParam('filter', $filter); + } + + /** + * Gets the filter. + * + * @return \Elastica\Filter\AbstractFilter + */ + public function getFilter() + { + return $this->getParam('filter'); + } + + /** + * Gets the query. + * + * @return \Elastica\Query\AbstractQuery + */ + public function getQuery() + { + return $this->getParam('query'); + } + + /** + * Converts query to array + * + * @return array Query array + * @see \Elastica\Query\AbstractQuery::toArray() + */ + public function toArray() + { + $filtered = array(); + + if ($this->hasParam('query') && $this->getParam('query') instanceof AbstractQuery) { + $filtered['query'] = $this->getParam('query')->toArray(); + } + + if ($this->hasParam('filter') && $this->getParam('filter') instanceof AbstractFilter) { + $filtered['filter'] = $this->getParam('filter')->toArray(); + } + + if (empty($filtered)) { + throw new InvalidException('A query and/or filter is required'); + } + + return array('filtered' => $filtered); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/FunctionScore.php b/vendor/ruflin/elastica/lib/Elastica/Query/FunctionScore.php new file mode 100644 index 00000000..8230c86e --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/FunctionScore.php @@ -0,0 +1,201 @@ +<?php + +namespace Elastica\Query; +use Elastica\Filter\AbstractFilter; +use Elastica\Script; + +/** + * Class FunctionScore + * @package Elastica\Query + * @link http://www.elasticsearch.org/guide/reference/query-dsl/function-score-query/ + */ +class FunctionScore extends AbstractQuery +{ + const BOOST_MODE_MULTIPLY = 'multiply'; + const BOOST_MODE_REPLACE = 'replace'; + const BOOST_MODE_SUM = 'sum'; + const BOOST_MODE_AVERAGE = 'average'; + const BOOST_MODE_MAX = 'max'; + const BOOST_MODE_MIN = 'min'; + + const SCORE_MODE_MULTIPLY = 'multiply'; + const SCORE_MODE_SUM = 'sum'; + const SCORE_MODE_AVERAGE = 'avg'; + const SCORE_MODE_FIRST = 'first'; + const SCORE_MODE_MAX = 'max'; + const SCORE_MODE_MIN = 'min'; + + const DECAY_GAUSS = 'gauss'; + const DECAY_EXPONENTIAL = 'exp'; + const DECAY_LINEAR = 'linear'; + + protected $_functions = array(); + + /** + * Set the child query for this function_score query + * @param AbstractQuery $query + * @return \Elastica\Query\FunctionScore + */ + public function setQuery(AbstractQuery $query) + { + return $this->setParam('query', $query->toArray()); + } + + /** + * @param AbstractFilter $filter + * @return \Elastica\Param + */ + public function setFilter(AbstractFilter $filter) + { + return $this->setParam('filter', $filter->toArray()); + } + + /** + * Add a function to the function_score query + * @param string $functionType valid values are DECAY_* constants and script_score + * @param array|float $functionParams the body of the function. See documentation for proper syntax. + * @param AbstractFilter $filter optional filter to apply to the function + * @return \Elastica\Query\FunctionScore + */ + public function addFunction($functionType, $functionParams, AbstractFilter $filter = NULL) + { + $function = array( + $functionType => $functionParams + ); + if (!is_null($filter)) { + $function['filter'] = $filter->toArray(); + } + $this->_functions[] = $function; + return $this; + } + + /** + * Add a script_score function to the query + * @param Script $script a Script object + * @param AbstractFilter $filter an optional filter to apply to the function + * @return \Elastica\Query\FunctionScore + */ + public function addScriptScoreFunction(Script $script, AbstractFilter $filter = NULL) + { + return $this->addFunction('script_score', $script->toArray(), $filter); + } + + /** + * Add a decay function to the query + * @param string $function see DECAY_* constants for valid options + * @param string $field the document field on which to perform the decay function + * @param string $origin the origin value for this decay function + * @param string $scale a scale to define the rate of decay for this function + * @param string $offset If defined, this function will only be computed for documents with a distance from the origin greater than this value + * @param float $decay optionally defines how documents are scored at the distance given by the $scale parameter + * @param float $scaleWeight optional factor by which to multiply the score at the value provided by the $scale parameter + * @param AbstractFilter $filter a filter associated with this function + * @return \Elastica\Query\FunctionScore + */ + public function addDecayFunction($function, $field, $origin, $scale, $offset = NULL, $decay = NULL, $scaleWeight = NULL, + AbstractFilter $filter = NULL) + { + $functionParams = array( + $field => array( + 'origin' => $origin, + 'scale' => $scale + ) + ); + if (!is_null($offset)) { + $functionParams[$field]['offset'] = $offset; + } + if (!is_null($decay)) { + $functionParams[$field]['decay'] = (float)$decay; + } + if (!is_null($scaleWeight)) { + $functionParams[$field]['scale_weight'] = (float)$scaleWeight; + } + return $this->addFunction($function, $functionParams, $filter); + } + + /** + * Add a boost_factor function to the query + * @param float $boostFactor the boost factor value + * @param AbstractFilter $filter a filter associated with this function + */ + public function addBoostFactorFunction($boostFactor, AbstractFilter $filter = NULL) + { + $this->addFunction('boost_factor', $boostFactor, $filter); + } + + /** + * Add a random_score function to the query + * @param number $seed the seed value + * @param AbstractFilter $filter a filter associated with this function + * @param float $boost an optional boost value associated with this function + */ + public function addRandomScoreFunction($seed, AbstractFilter $filter = NULL, $boost = NULL) + { + $this->addFunction('random_score', array('seed' => $seed), $filter, $boost); + } + + /** + * Set an overall boost value for this query + * @param float $boost + * @return \Elastica\Query\FunctionScore + */ + public function setBoost($boost) + { + return $this->setParam('boost', (float)$boost); + } + + /** + * Restrict the combined boost of the function_score query and its child query + * @param float $maxBoost + * @return \Elastica\Query\FunctionScore + */ + public function setMaxBoost($maxBoost) + { + return $this->setParam('max_boost', (float)$maxBoost); + } + + /** + * The boost mode determines how the score of this query is combined with that of the child query + * @param string $mode see BOOST_MODE_* constants for valid options. Default is multiply. + * @return \Elastica\Query\FunctionScore + */ + public function setBoostMode($mode) + { + return $this->setParam('boost_mode', $mode); + } + + /** + * If set, this query will return results in random order. + * @param int $seed Set a seed value to return results in the same random order for consistent pagination. + * @return \Elastica\Query\FunctionScore + */ + public function setRandomScore($seed = NULL) + { + $seedParam = new \stdClass(); + if (!is_null($seed)) { + $seedParam->seed = $seed; + } + return $this->setParam('random_score', $seedParam); + } + + /** + * Set the score method + * @param string $mode see SCORE_MODE_* constants for valid options. Default is multiply. + * @return \Elastica\Query\FunctionScore + */ + public function setScoreMode($mode) + { + return $this->setParam('score_mode', $mode); + } + + /** + * @return array + */ + public function toArray() + { + if (sizeof($this->_functions)) { + $this->setParam('functions', $this->_functions); + } + return parent::toArray(); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/Fuzzy.php b/vendor/ruflin/elastica/lib/Elastica/Query/Fuzzy.php new file mode 100644 index 00000000..73b0f1a1 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/Fuzzy.php @@ -0,0 +1,84 @@ +<?php + +namespace Elastica\Query; + +use Elastica\Exception\InvalidException; + +/** + * Fuzzy query + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/fuzzy-query.html + */ +class Fuzzy extends AbstractQuery +{ + /** + * Construct a fuzzy query + * + * @param string $fieldName Field name + * @param string $value String to search for + * @return \Elastica\Query\Fuzzy Current object + */ + public function __construct ($fieldName = null, $value = null) + { + if ($fieldName and $value) { + $this->setField($fieldName, $value); + } + } + + /** + * Set field for fuzzy query + * + * @param string $fieldName Field name + * @param string $value String to search for + * @return \Elastica\Query\Fuzzy Current object + */ + public function setField ($fieldName, $value) + { + if (!is_string($value) or !is_string($fieldName)) { + throw new InvalidException('The field and value arguments must be of type string.'); + } + if (count($this->getParams()) > 0 and array_shift(array_keys($this->getParams())) != $fieldName) { + throw new InvalidException('Fuzzy query can only support a single field.'); + } + return $this->setParam($fieldName, array('value' => $value)); + } + + /** + * Set optional parameters on the existing query + * + * @param string $param option name + * @param mixed $value Value of the parameter + * @return \Elastica\Query\Fuzzy Current object + */ + public function setFieldOption ($param, $value) { + //Retrieve the single existing field for alteration. + $params = $this->getParams(); + if (count($params) < 1) { + throw new InvalidException('No field has been set'); + } + $keyArray = array_keys($params); + $params[$keyArray[0]][$param] = $value; + + return $this->setparam($keyArray[0], $params[$keyArray[0]]); + } + + /** + * Deprecated method of setting a field. + * @deprecated + */ + public function addField($fieldName, $args) + { + if (!array_key_exists('value', $args)) { + throw new InvalidException('Fuzzy query can only support a single field.'); + } + $this->setField($fieldName, $args['value']); + unset($args['value']); + foreach ($args as $param => $value) { + $this->setFieldOption($param, $value); + } + return $this; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/FuzzyLikeThis.php b/vendor/ruflin/elastica/lib/Elastica/Query/FuzzyLikeThis.php new file mode 100644 index 00000000..ffa34a81 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/FuzzyLikeThis.php @@ -0,0 +1,215 @@ +<?php + +namespace Elastica\Query; + +/** + * Fuzzy Like This query + * + * @category Xodoa + * @package Elastica + * @author Raul Martinez, Jr <juneym@gmail.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/flt-query.html + */ +class FuzzyLikeThis extends AbstractQuery +{ + /** + * Field names + * + * @var array Field names + */ + protected $_fields = array(); + + /** + * Like text + * + * @var string Like text + */ + protected $_likeText = ''; + + /** + * Ignore term frequency + * + * @var boolean ignore term frequency + */ + protected $_ignoreTF = false; + + /** + * Max query terms value + * + * @var int Max query terms value + */ + protected $_maxQueryTerms = 25; + + /** + * minimum similarity + * + * @var int minimum similarity + */ + protected $_minSimilarity = 0.5; + + /** + * Prefix Length + * + * @var int Prefix Length + */ + protected $_prefixLength = 0; + + /** + * Boost + * + * @var float Boost + */ + protected $_boost = 1.0; + + /** + * Analyzer + * + * @var sting Analyzer + */ + protected $_analyzer; + + + /** + * Adds field to flt query + * + * @param array $fields Field names + * @return \Elastica\Query\FuzzyLikeThis Current object + */ + public function addFields(array $fields) + { + $this->_fields = $fields; + + return $this; + } + + /** + * Set the "like_text" value + * + * @param string $text + * @return \Elastica\Query\FuzzyLikeThis This current object + */ + public function setLikeText($text) + { + $text = trim($text); + $this->_likeText = $text; + + return $this; + } + + /** + * Set the "ignore_tf" value (ignore term frequency) + * + * @param bool $ignoreTF + * @return \Elastica\Query\FuzzyLikeThis Current object + */ + public function setIgnoreTF($ignoreTF) + { + $this->_ignoreTF = (bool) $ignoreTF; + + return $this; + } + + /** + * Set the minimum similarity + * + * @param int $value + * @return \Elastica\Query\FuzzyLikeThis This current object + */ + public function setMinSimilarity($value) + { + $value = (float) $value; + $this->_minSimilarity = $value; + + return $this; + } + + /** + * Set boost + * + * @param float $value Boost value + * @return \Elastica\Query\FuzzyLikeThis Query object + */ + public function setBoost($value) + { + $this->_boost = (float) $value; + + return $this; + } + + /** + * Set Prefix Length + * + * @param int $value Prefix length + * @return \Elastica\Query\FuzzyLikeThis + */ + public function setPrefixLength($value) + { + $this->_prefixLength = (int) $value; + + return $this; + } + + /** + * Set max_query_terms + * + * @param int $value Max query terms value + * @return \Elastica\Query\FuzzyLikeThis + */ + public function setMaxQueryTerms($value) + { + $this->_maxQueryTerms = (int) $value; + + return $this; + } + + /** + * Set analyzer + * + * @param string $text Analyzer text + * @return \Elastica\Query\FuzzyLikeThis + */ + public function setAnalyzer($text) + { + $text = trim($text); + $this->_analyzer = $text; + + return $this; + } + + /** + * Converts fuzzy like this query to array + * + * @return array Query array + * @see \Elastica\Query\AbstractQuery::toArray() + */ + public function toArray() + { + if (!empty($this->_fields)) { + $args['fields'] = $this->_fields; + } + + if (!empty($this->_boost)) { + $args['boost'] = $this->_boost; + } + + if (!empty($this->_likeText)) { + $args['like_text'] = $this->_likeText; + } + + if (!empty($this->_analyzer)) { + $args['analyzer'] = $this->_analyzer; + } + + + $args['min_similarity'] = ($this->_minSimilarity > 0) ? $this->_minSimilarity : 0; + + $args['prefix_length'] = $this->_prefixLength; + $args['ignore_tf'] = $this->_ignoreTF; + $args['max_query_terms'] = $this->_maxQueryTerms; + + $data = parent::toArray(); + $args = array_merge($args, $data['fuzzy_like_this']); + + return array('fuzzy_like_this' => $args); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/HasChild.php b/vendor/ruflin/elastica/lib/Elastica/Query/HasChild.php new file mode 100644 index 00000000..e849a9bf --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/HasChild.php @@ -0,0 +1,63 @@ +<?php + +namespace Elastica\Query; +use Elastica\Query as BaseQuery; + +/** + * Returns parent documents having child docs matching the query + * + * @category Xodoa + * @package Elastica + * @author Fabian Vogler <fabian@equivalence.ch> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/has-child-query.html + */ +class HasChild extends AbstractQuery +{ + /** + * Construct HasChild Query + * + * @param string|\Elastica\Query|\Elastica\Query\AbstractQuery $query + * @param string $type Parent document type + */ + public function __construct($query, $type = null) + { + $this->setType($type); + $this->setQuery($query); + } + + /** + * Sets query object + * + * @param string|\Elastica\Query|\Elastica\Query\AbstractQuery $query + * @return \Elastica\Query\HasChild + */ + public function setQuery($query) + { + $query = BaseQuery::create($query); + $data = $query->toArray(); + + return $this->setParam('query', $data['query']); + } + + /** + * Set type of the parent document + * + * @param string $type Parent document type + * @return \Elastica\Query\HasChild Current object + */ + public function setType($type) + { + return $this->setParam('type', $type); + } + + /** + * Sets the scope + * + * @param string $scope Scope + * @return \Elastica\Query\HasChild Current object + */ + public function setScope($scope) + { + return $this->setParam('_scope', $scope); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/HasParent.php b/vendor/ruflin/elastica/lib/Elastica/Query/HasParent.php new file mode 100644 index 00000000..809fb18d --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/HasParent.php @@ -0,0 +1,62 @@ +<?php + +namespace Elastica\Query; +use Elastica\Query as BaseQuery; + +/** + * Returns child documents having parent docs matching the query + * + * @category Xodoa + * @package Elastica + * @link http://www.elasticsearch.org/guide/reference/query-dsl/has-parent-query.html + */ +class HasParent extends AbstractQuery +{ + /** + * Construct HasChild Query + * + * @param string|\Elastica\Query|\Elastica\Query\AbstractQuery $query + * @param string $type Parent document type + */ + public function __construct($query, $type) + { + $this->setQuery($query); + $this->setType($type); + } + + /** + * Sets query object + * + * @param string|\Elastica\Query|\Elastica\Query\AbstractQuery $query + * @return \Elastica\Filter\HasParent + */ + public function setQuery($query) + { + $query = BaseQuery::create($query); + $data = $query->toArray(); + + return $this->setParam('query', $data['query']); + } + + /** + * Set type of the parent document + * + * @param string $type Parent document type + * @return \Elastica\Filter\HasParent Current object + */ + public function setType($type) + { + return $this->setParam('type', $type); + } + + /** + * Sets the scope + * + * @param string $scope Scope + * @return \Elastica\Filter\HasParent Current object + */ + public function setScope($scope) + { + return $this->setParam('_scope', $scope); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/Ids.php b/vendor/ruflin/elastica/lib/Elastica/Query/Ids.php new file mode 100644 index 00000000..f4a6f1aa --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/Ids.php @@ -0,0 +1,117 @@ +<?php + +namespace Elastica\Query; +use Elastica\Type; + +/** + * Ids Query + * + * @category Xodoa + * @package Elastica + * @author Lee Parker + * @author Nicolas Ruflin <spam@ruflin.com> + * @author Tim Rupp + * @link http://www.elasticsearch.org/guide/reference/query-dsl/ids-query.html + */ +class Ids extends AbstractQuery +{ + /** + * Params + * + * @var array Params + */ + protected $_params = array(); + + /** + * Creates filter object + * + * @param string|\Elastica\Type $type Type to filter on + * @param array $ids List of ids + */ + public function __construct($type = null, array $ids = array()) + { + $this->setType($type); + $this->setIds($ids); + } + + /** + * Adds one more filter to the and filter + * + * @param string $id Adds id to filter + * @return \Elastica\Query\Ids Current object + */ + public function addId($id) + { + $this->_params['values'][] = $id; + + return $this; + } + + /** + * Adds one more type to query + * + * @param string|\Elastica\Type $type Type name or object + * @return \Elastica\Query\Ids Current object + */ + public function addType($type) + { + if ($type instanceof Type) { + $type = $type->getName(); + } elseif (empty($type) && !is_numeric($type)) { + // A type can be 0, but cannot be empty + return $this; + } + + $this->_params['type'][] = $type; + + return $this; + } + + /** + * Set type + * + * @param string|\Elastica\Type $type Type name or object + * @return \Elastica\Query\Ids Current object + */ + public function setType($type) + { + if ($type instanceof Type) { + $type = $type->getName(); + } elseif (empty($type) && !is_numeric($type)) { + // A type can be 0, but cannot be empty + return $this; + } + + $this->_params['type'] = $type; + + return $this; + } + + /** + * Sets the ids to filter + * + * @param array|string $ids List of ids + * @return \Elastica\Query\Ids Current object + */ + public function setIds($ids) + { + if (is_array($ids)) { + $this->_params['values'] = $ids; + } else { + $this->_params['values'] = array($ids); + } + + return $this; + } + + /** + * Converts filter to array + * + * @see \Elastica\Query\AbstractQuery::toArray() + * @return array Query array + */ + public function toArray() + { + return array('ids' => $this->_params); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/Match.php b/vendor/ruflin/elastica/lib/Elastica/Query/Match.php new file mode 100644 index 00000000..ba66ad63 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/Match.php @@ -0,0 +1,198 @@ +<?php + +namespace Elastica\Query; + +/** + * Match query + * + * @category Xodoa + * @package Elastica + * @author F21 + * @author WONG Wing Lun <luiges90@gmail.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/match-query.html + */ +class Match extends AbstractQuery +{ + const ZERO_TERM_NONE = 'none'; + const ZERO_TERM_ALL = 'all'; + + /** + * Sets a param for the message array + * + * @param string $field + * @param mixed $values + * @return \Elastica\Query\Match + */ + public function setField($field, $values) + { + return $this->setParam($field, $values); + } + + /** + * Sets a param for the given field + * + * @param string $field + * @param string $key + * @param string $value + * @return \Elastica\Query\Match + */ + public function setFieldParam($field, $key, $value) + { + if (!isset($this->_params[$field])) { + $this->_params[$field] = array(); + } + + $this->_params[$field][$key] = $value; + + return $this; + } + + /** + * Sets the query string + * + * @param string $field + * @param string $query + * @return \Elastica\Query\Match + */ + public function setFieldQuery($field, $query) + { + return $this->setFieldParam($field, 'query', $query); + } + + /** + * Set field type + * + * @param string $field + * @param string $type + * @return \Elastica\Query\Match + */ + public function setFieldType($field, $type) + { + return $this->setFieldParam($field, 'type', $type); + } + + /** + * Set field operator + * + * @param string $field + * @param string $operator + * @return \Elastica\Query\Match + */ + public function setFieldOperator($field, $operator) + { + return $this->setFieldParam($field, 'operator', $operator); + } + + /** + * Set field analyzer + * + * @param string $field + * @param string $analyzer + * @return \Elastica\Query\Match + */ + public function setFieldAnalyzer($field, $analyzer) + { + return $this->setFieldParam($field, 'analyzer', $analyzer); + } + + /** + * Set field boost value + * + * If not set, defaults to 1.0. + * + * @param string $field + * @param float $boost + * @return \Elastica\Query\Match + */ + public function setFieldBoost($field, $boost = 1.0) + { + return $this->setFieldParam($field, 'boost', (float) $boost); + } + + /** + * Set field minimum should match + * + * @param string $field + * @param int|string $minimumShouldMatch + * @return \Elastica\Query\Match + * @link Possible values for minimum_should_match http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-minimum-should-match.html + */ + public function setFieldMinimumShouldMatch($field, $minimumShouldMatch) + { + return $this->setFieldParam($field, 'minimum_should_match', $minimumShouldMatch); + } + + /** + * Set field fuzziness + * + * @param string $field + * @param mixed $fuzziness + * @return \Elastica\Query\Match + */ + public function setFieldFuzziness($field, $fuzziness) + { + return $this->setFieldParam($field, 'fuzziness', $fuzziness); + } + + /** + * Set field fuzzy rewrite + * + * @param string $field + * @param string $fuzzyRewrite + * @return \Elastica\Query\Match + */ + public function setFieldFuzzyRewrite($field, $fuzzyRewrite) + { + return $this->setFieldParam($field, 'fuzzy_rewrite', $fuzzyRewrite); + } + + /** + * Set field prefix length + * + * @param string $field + * @param int $prefixLength + * @return \Elastica\Query\Match + */ + public function setFieldPrefixLength($field, $prefixLength) + { + return $this->setFieldParam($field, 'prefix_length', (int) $prefixLength); + } + + /** + * Set field max expansions + * + * @param string $field + * @param int $maxExpansions + * @return \Elastica\Query\Match + */ + public function setFieldMaxExpansions($field, $maxExpansions) + { + return $this->setFieldParam($field, 'max_expansions', (int) $maxExpansions); + } + + /** + * Set zero terms query + * + * If not set, default to 'none' + * + * @param string $field + * @param string $zeroTermQuery + * @return \Elastica\Query\Match + */ + public function setFieldZeroTermsQuery($field, $zeroTermQuery = 'none') + { + return $this->setFieldParam($field, 'zero_terms_query', $zeroTermQuery); + } + + /** + * Set cutoff frequency + * + * @param string $field + * @param float $cutoffFrequency + * @return \Elastica\Query\Match + */ + public function setFieldCutoffFrequency($field, $cutoffFrequency) + { + return $this->setFieldParam($field, 'cutoff_frequency', $cutoffFrequency); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/MatchAll.php b/vendor/ruflin/elastica/lib/Elastica/Query/MatchAll.php new file mode 100644 index 00000000..23b4fdfc --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/MatchAll.php @@ -0,0 +1,22 @@ +<?php + +namespace Elastica\Query; + +/** + * Match all query. Returns all results + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/match-all-query.html + */ +class MatchAll extends AbstractQuery +{ + /** + * Creates match all query + */ + public function __construct() + { + $this->_params = new \stdClass(); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/MoreLikeThis.php b/vendor/ruflin/elastica/lib/Elastica/Query/MoreLikeThis.php new file mode 100644 index 00000000..d9ae4284 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/MoreLikeThis.php @@ -0,0 +1,162 @@ +<?php + +namespace Elastica\Query; + +/** + * More Like This query + * + * @category Xodoa + * @package Elastica + * @author Raul Martinez, Jr <juneym@gmail.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/mlt-query.html + */ +class MoreLikeThis extends AbstractQuery +{ + /** + * Adds field to mlt query + * + * @param array $fields Field names + * @return \Elastica\Query\MoreLikeThis Current object + */ + public function setFields(array $fields) + { + return $this->setParam('fields', $fields); + } + + /** + * Set the "like_text" value + * + * @param string $likeText + * @return \Elastica\Query\MoreLikeThis This current object + */ + public function setLikeText($likeText) + { + $likeText = trim($likeText); + + return $this->setParam('like_text', $likeText); + } + + /** + * Set boost + * + * @param float $boost Boost value + * @return \Elastica\Query\MoreLikeThis Query object + */ + public function setBoost($boost) + { + return $this->setParam('boost', (float) $boost); + } + + /** + * Set max_query_terms + * + * @param int $maxQueryTerms Max query terms value + * @return \Elastica\Query\MoreLikeThis + */ + public function setMaxQueryTerms($maxQueryTerms) + { + return $this->setParam('max_query_terms', (int) $maxQueryTerms); + } + + /** + * Set percent terms to match + * + * @param float $percentTermsToMatch Percentage + * @return \Elastica\Query\MoreLikeThis + */ + public function setPercentTermsToMatch($percentTermsToMatch) + { + return $this->setParam('percent_terms_to_match', (float) $percentTermsToMatch); + } + + /** + * Set min term frequency + * + * @param int $minTermFreq + * @return \Elastica\Query\MoreLikeThis + */ + public function setMinTermFrequency($minTermFreq) + { + return $this->setParam('min_term_freq', (int) $minTermFreq); + } + + /** + * set min document frequency + * + * @param int $minDocFreq + * @return \Elastica\Query\MoreLikeThis + */ + public function setMinDocFrequency($minDocFreq) + { + return $this->setParam('min_doc_freq', (int) $minDocFreq); + } + + /** + * set max document frequency + * + * @param int $maxDocFreq + * @return \Elastica\Query\MoreLikeThis + */ + public function setMaxDocFrequency($maxDocFreq) + { + return $this->setParam('max_doc_freq', (int) $maxDocFreq); + } + + /** + * Set min word length + * + * @param int $minWordLength + * @return \Elastica\Query\MoreLikeThis + */ + public function setMinWordLength($minWordLength) + { + return $this->setParam('min_word_length', (int) $minWordLength); + } + + /** + * Set max word length + * + * @param int $maxWordLength + * @return \Elastica\Query\MoreLikeThis + */ + public function setMaxWordLength($maxWordLength) + { + return $this->setParam('max_word_length', (int) $maxWordLength); + } + + /** + * Set boost terms + * + * @param bool $boostTerms + * @return \Elastica\Query\MoreLikeThis + * @link http://www.elasticsearch.org/guide/reference/query-dsl/mlt-query.html + */ + public function setBoostTerms($boostTerms) + { + return $this->setParam('boost_terms', (bool) $boostTerms); + } + + /** + * Set analyzer + * + * @param string $analyzer + * @return \Elastica\Query\MoreLikeThis + */ + public function setAnalyzer($analyzer) + { + $analyzer = trim($analyzer); + + return $this->setParam('analyzer', $analyzer); + } + + /** + * Set stop words + * + * @param array $stopWords + * @return \Elastica\Query\MoreLikeThis + */ + public function setStopWords(array $stopWords) + { + return $this->setParam('stop_words', $stopWords); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/MultiMatch.php b/vendor/ruflin/elastica/lib/Elastica/Query/MultiMatch.php new file mode 100644 index 00000000..ac2d01b3 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/MultiMatch.php @@ -0,0 +1,180 @@ +<?php + +namespace Elastica\Query; + +/** + * Multi Match + * + * @category Xodoa + * @package Elastica + * @author Rodolfo Adhenawer Campagnoli Moraes <adhenawer@gmail.com> + * @author Wong Wing Lun <luiges90@gmail.com> + * @author Tristan Maindron <tmaindron@gmail.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/multi-match-query.html + */ +class MultiMatch extends AbstractQuery +{ + const TYPE_BEST_FIELDS = 'best_fields'; + const TYPE_MOST_FIELDS = 'most_fields'; + const TYPE_CROSS_FIELDS = 'cross_fields'; + const TYPE_PHRASE = 'phrase'; + const TYPE_PHRASE_PREFIX = 'phrase_prefix'; + + const OPERATOR_OR = 'or'; + const OPERATOR_AND = 'and'; + + const ZERO_TERM_NONE = 'none'; + const ZERO_TERM_ALL = 'all'; + + /** + * Sets the query + * + * @param string $query Query + * @return \Elastica\Query\MultiMatch Current object + */ + public function setQuery($query = '') + { + return $this->setParam('query', $query); + } + + /** + * Sets Fields to be used in the query. + * + * @param array $fields Fields + * @return \Elastica\Query\MultiMatch Current object + */ + public function setFields($fields = array()) + { + return $this->setParam('fields', $fields); + } + + /** + * Sets use dis max indicating to either create a dis_max query or a bool query. + * + * If not set, defaults to true. + * + * @param boolean $useDisMax + * @return \Elastica\Query\MultiMatch Current object + */ + public function setUseDisMax($useDisMax = true) + { + return $this->setParam('use_dis_max', $useDisMax); + } + + /** + * Sets tie breaker to multiplier value to balance the scores between lower and higher scoring fields. + * + * If not set, defaults to 0.0. + * + * @param float $tieBreaker + * @return \Elastica\Query\MultiMatch Current object + */ + public function setTieBreaker($tieBreaker = 0.0) + { + return $this->setParam('tie_breaker', $tieBreaker); + } + + /** + * Sets operator for Match Query + * + * If not set, defaults to 'or' + * + * @param string $operator + * @return \Elastica\Query\MultiMatch Current object + */ + public function setOperator($operator = 'or') + { + return $this->setParam('operator', $operator); + } + + /** + * Set field minimum should match for Match Query + * + * @param int $minimumShouldMatch + * @return \Elastica\Query\Match + */ + public function setMinimumShouldMatch($minimumShouldMatch) + { + return $this->setParam('minimum_should_match', (int) $minimumShouldMatch); + } + + /** + * Set zero terms query for Match Query + * + * If not set, default to 'none' + * + * @param string $zeroTermQuery + * @return \Elastica\Query\Match + */ + public function setZeroTermsQuery($zeroTermQuery = 'none') + { + return $this->setParam('zero_terms_query', $zeroTermQuery); + } + + /** + * Set cutoff frequency for Match Query + * + * @param float $cutoffFrequency + * @return \Elastica\Query\Match + */ + public function setCutoffFrequency($cutoffFrequency) + { + return $this->setParam('cutoff_frequency', $cutoffFrequency); + } + + /** + * Set type + * + * @param string $field + * @param string $type + * @return \Elastica\Query\Match + */ + public function setType($type) + { + return $this->setParam('type', $type); + } + + /** + * Set fuzziness + * + * @param float $fuzziness + * @return \Elastica\Query\Match + */ + public function setFuzziness($fuzziness) + { + return $this->setParam('fuzziness', (float) $fuzziness); + } + + /** + * Set prefix length + * + * @param int $prefixLength + * @return \Elastica\Query\Match + */ + public function setPrefixLength($prefixLength) + { + return $this->setParam('prefix_length', (int) $prefixLength); + } + + /** + * Set max expansions + * + * @param int $maxExpansions + * @return \Elastica\Query\Match + */ + public function setMaxExpansions($maxExpansions) + { + return $this->setParam('max_expansions', (int) $maxExpansions); + } + + /** + * Set analyzer + * + * @param string $analyzer + * @return \Elastica\Query\Match + */ + public function setAnalyzer($analyzer) + { + return $this->setParam('analyzer', $analyzer); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/Nested.php b/vendor/ruflin/elastica/lib/Elastica/Query/Nested.php new file mode 100644 index 00000000..3d2f2f64 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/Nested.php @@ -0,0 +1,47 @@ +<?php + +namespace Elastica\Query; + +/** + * Nested query + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/nested-query.html + */ +class Nested extends AbstractQuery +{ + /** + * Adds field to mlt query + * + * @param string $path Nested object path + * @return \Elastica\Query\Nested + */ + public function setPath($path) + { + return $this->setParam('path', $path); + } + + /** + * Sets nested query + * + * @param \Elastica\Query\AbstractQuery $query + * @return \Elastica\Query\Nested + */ + public function setQuery(AbstractQuery $query) + { + return $this->setParam('query', $query->toArray()); + } + + /** + * Set score method + * + * @param string $scoreMode Options: avg, total, max and none. + * @return \Elastica\Query\Nested + */ + public function setScoreMode($scoreMode) + { + return $this->setParam('score_mode', $scoreMode); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/Prefix.php b/vendor/ruflin/elastica/lib/Elastica/Query/Prefix.php new file mode 100644 index 00000000..4306fd9c --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/Prefix.php @@ -0,0 +1,48 @@ +<?php + +namespace Elastica\Query; + +/** + * Prefix query + * + * @category Xodoa + * @package Elastica + * @link http://www.elasticsearch.org/guide/reference/query-dsl/prefix-query.html + */ +class Prefix extends AbstractQuery +{ + /** + * Constructs the Prefix query object + * + * @param array $prefix OPTIONAL Calls setRawPrefix with the given $prefix array + */ + public function __construct(array $prefix = array()) + { + $this->setRawPrefix($prefix); + } + + /** + * setRawPrefix can be used instead of setPrefix if some more special + * values for a prefix have to be set. + * + * @param array $prefix Prefix array + * @return \Elastica\Query\Prefix Current object + */ + public function setRawPrefix(array $prefix) + { + return $this->setParams($prefix); + } + + /** + * Adds a prefix to the prefix query + * + * @param string $key Key to query + * @param string|array $value Values(s) for the query. Boost can be set with array + * @param float $boost OPTIONAL Boost value (default = 1.0) + * @return \Elastica\Query\Prefix Current object + */ + public function setPrefix($key, $value, $boost = 1.0) + { + return $this->setRawPrefix(array($key => array('value' => $value, 'boost' => $boost))); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/QueryString.php b/vendor/ruflin/elastica/lib/Elastica/Query/QueryString.php new file mode 100644 index 00000000..7d0b0094 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/QueryString.php @@ -0,0 +1,267 @@ +<?php + +namespace Elastica\Query; +use Elastica\Exception\InvalidException; + +/** + * QueryString query + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com>, Jasper van Wanrooy <jasper@vanwanrooy.net> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/query-string-query.html + */ +class QueryString extends AbstractQuery +{ + /** + * Query string + * + * @var string Query string + */ + protected $_queryString = ''; + + /** + * Creates query string object. Calls setQuery with argument + * + * @param string $queryString OPTIONAL Query string for object + */ + public function __construct($queryString = '') + { + $this->setQuery($queryString); + } + + /** + * Sets a new query string for the object + * + * @param string $query Query string + * @throws \Elastica\Exception\InvalidException + * @return \Elastica\Query\QueryString Current object + */ + public function setQuery($query = '') + { + if (!is_string($query)) { + throw new InvalidException('Parameter has to be a string'); + } + + return $this->setParam('query', $query); + } + + /** + * Sets the default field + * + * If no field is set, _all is chosen + * + * @param string $field Field + * @return \Elastica\Query\QueryString Current object + */ + public function setDefaultField($field) + { + return $this->setParam('default_field', $field); + } + + /** + * Sets the default operator AND or OR + * + * If no operator is set, OR is chosen + * + * @param string $operator Operator + * @return \Elastica\Query\QueryString Current object + */ + public function setDefaultOperator($operator) + { + return $this->setParam('default_operator', $operator); + } + + /** + * Sets the analyzer to analyze the query with. + * + * @param string $analyzer Analyser to use + * @return \Elastica\Query\QueryString Current object + */ + public function setAnalyzer($analyzer) + { + return $this->setParam('analyzer', $analyzer); + } + + /** + * Sets the parameter to allow * and ? as first characters. + * + * If not set, defaults to true. + * + * @param bool $allow + * @return \Elastica\Query\QueryString Current object + */ + public function setAllowLeadingWildcard($allow = true) + { + return $this->setParam('allow_leading_wildcard', (bool) $allow); + } + + /** + * Sets the parameter to auto-lowercase terms of some queries. + * + * If not set, defaults to true. + * + * @param bool $lowercase + * @return \Elastica\Query\QueryString Current object + */ + public function setLowercaseExpandedTerms($lowercase = true) + { + return $this->setParam('lowercase_expanded_terms', (bool) $lowercase); + } + + /** + * Sets the parameter to enable the position increments in result queries. + * + * If not set, defaults to true. + * + * @param bool $enabled + * @return \Elastica\Query\QueryString Current object + */ + public function setEnablePositionIncrements($enabled = true) + { + return $this->setParam('enable_position_increments', (bool) $enabled); + } + + /** + * Sets the fuzzy prefix length parameter. + * + * If not set, defaults to 0. + * + * @param int $length + * @return \Elastica\Query\QueryString Current object + */ + public function setFuzzyPrefixLength($length = 0) + { + return $this->setParam('fuzzy_prefix_length', (int) $length); + } + + /** + * Sets the fuzzy minimal similarity parameter. + * + * If not set, defaults to 0.5 + * + * @param float $minSim + * @return \Elastica\Query\QueryString Current object + */ + public function setFuzzyMinSim($minSim = 0.5) + { + return $this->setParam('fuzzy_min_sim', (float) $minSim); + } + + /** + * Sets the phrase slop. + * + * If zero, exact phrases are required. + * If not set, defaults to zero. + * + * @param int $phraseSlop + * @return \Elastica\Query\QueryString Current object + */ + public function setPhraseSlop($phraseSlop = 0) + { + return $this->setParam('phrase_slop', (int) $phraseSlop); + } + + /** + * Sets the boost value of the query. + * + * If not set, defaults to 1.0. + * + * @param float $boost + * @return \Elastica\Query\QueryString Current object + */ + public function setBoost($boost = 1.0) + { + return $this->setParam('boost', (float) $boost); + } + + /** + * Allows analyzing of wildcard terms. + * + * If not set, defaults to true + * + * @param bool $analyze + * @return \Elastica\Query\QueryString Current object + */ + public function setAnalyzeWildcard($analyze = true) + { + return $this->setParam('analyze_wildcard', (bool) $analyze); + } + + /** + * Sets the param to automatically generate phrase queries. + * + * If not set, defaults to true. + * + * @param bool $autoGenerate + * @return \Elastica\Query\QueryString Current object + */ + public function setAutoGeneratePhraseQueries($autoGenerate = true) + { + return $this->setParam('auto_generate_phrase_queries', (bool) $autoGenerate); + } + + /** + * Sets the fields + * + * If no fields are set, _all is chosen + * + * @param array $fields Fields + * @throws \Elastica\Exception\InvalidException + * @return \Elastica\Query\QueryString Current object + */ + public function setFields(array $fields) + { + if (!is_array($fields)) { + throw new InvalidException('Parameter has to be an array'); + } + + return $this->setParam('fields', $fields); + } + + /** + * Whether to use bool or dis_max queries to internally combine results for multi field search. + * + * @param bool $value Determines whether to use + * @return \Elastica\Query\QueryString Current object + */ + public function setUseDisMax($value = true) + { + return $this->setParam('use_dis_max', (bool) $value); + } + + /** + * When using dis_max, the disjunction max tie breaker. + * + * If not set, defaults to 0. + * + * @param int $tieBreaker + * @return \Elastica\Query\QueryString Current object + */ + public function setTieBreaker($tieBreaker = 0) + { + return $this->setParam('tie_breaker', (float) $tieBreaker); + } + + /** + * Set a re-write condition. See https://github.com/elasticsearch/elasticsearch/issues/1186 for additional information + * + * @param string $rewrite + * @return \Elastica\Query\QueryString Current object + */ + public function setRewrite($rewrite = "") + { + return $this->setParam('rewrite', $rewrite); + } + + /** + * Converts query to array + * + * @see \Elastica\Query\AbstractQuery::toArray() + * @return array Query array + */ + public function toArray() + { + return array('query_string' => array_merge(array('query' => $this->_queryString), $this->getParams()),); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/Range.php b/vendor/ruflin/elastica/lib/Elastica/Query/Range.php new file mode 100644 index 00000000..54b79027 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/Range.php @@ -0,0 +1,39 @@ +<?php + +namespace Elastica\Query; + +/** + * Range query + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/range-query.html + */ +class Range extends AbstractQuery +{ + /** + * Constructor + * + * @param string $fieldName Field name + * @param array $args Field arguments + */ + public function __construct($fieldName = null, array $args = array()) + { + if ($fieldName) { + $this->addField($fieldName, $args); + } + } + + /** + * Adds a range field to the query + * + * @param string $fieldName Field name + * @param array $args Field arguments + * @return \Elastica\Query\Range Current object + */ + public function addField($fieldName, array $args) + { + return $this->setParam($fieldName, $args); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/Simple.php b/vendor/ruflin/elastica/lib/Elastica/Query/Simple.php new file mode 100644 index 00000000..2448ca79 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/Simple.php @@ -0,0 +1,55 @@ +<?php + +namespace Elastica\Query; + +/** + * Simple query + * Pure php array query. Can be used to create any not existing type of query. + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class Simple extends AbstractQuery +{ + /** + * Query + * + * @var array Query + */ + protected $_query = array(); + + /** + * Constructs a query based on an array + * + * @param array $query Query array + */ + public function __construct(array $query) + { + $this->setQuery($query); + } + + /** + * Sets new query array + * + * @param array $query Query array + * @return \Elastica\Query\Simple Current object + */ + public function setQuery(array $query) + { + $this->_query = $query; + + return $this; + } + + /** + * Converts query to array + * + * @return array Query array + * @see \Elastica\Query\AbstractQuery::toArray() + */ + public function toArray() + { + return $this->_query; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/SimpleQueryString.php b/vendor/ruflin/elastica/lib/Elastica/Query/SimpleQueryString.php new file mode 100644 index 00000000..a6c4ba9d --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/SimpleQueryString.php @@ -0,0 +1,65 @@ +<?php + +namespace Elastica\Query; + +/** + * Class SimpleQueryString + * @package Elastica\Query + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html + */ +class SimpleQueryString extends AbstractQuery +{ + const OPERATOR_AND = "and"; + const OPERATOR_OR = "or"; + + /** + * @param string $query + * @param array $fields + */ + public function __construct($query, array $fields = array()) + { + $this->setQuery($query); + if (sizeof($fields)) { + $this->setFields($fields); + } + } + + /** + * Set the querystring for this query + * @param string $query see ES documentation for querystring syntax + * @return \Elastica\Query\SimpleQueryString + */ + public function setQuery($query) + { + return $this->setParam("query", $query); + } + + /** + * @param string[] $fields the fields on which to perform this query. Defaults to index.query.default_field. + * @return \Elastica\Query\SimpleQueryString + */ + public function setFields(array $fields) + { + return $this->setParam("fields", $fields); + } + + /** + * Set the default operator to use if no explicit operator is defined in the query string + * @param string $operator see OPERATOR_* constants for options + * @return \Elastica\Query\SimpleQueryString + */ + public function setDefaultOperator($operator) + { + return $this->setParam("default_operator", $operator); + } + + /** + * Set the analyzer used to analyze each term of the query + * @param string $analyzer + * @return \Elastica\Query\SimpleQueryString + */ + public function setAnalyzer($analyzer) + { + return $this->setParam("analyzer", $analyzer); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/Term.php b/vendor/ruflin/elastica/lib/Elastica/Query/Term.php new file mode 100644 index 00000000..eb20eb86 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/Term.php @@ -0,0 +1,49 @@ +<?php + +namespace Elastica\Query; + +/** + * Term query + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/term-query.html + */ +class Term extends AbstractQuery +{ + /** + * Constructs the Term query object + * + * @param array $term OPTIONAL Calls setTerm with the given $term array + */ + public function __construct(array $term = array()) + { + $this->setRawTerm($term); + } + + /** + * Set term can be used instead of addTerm if some more special + * values for a term have to be set. + * + * @param array $term Term array + * @return \Elastica\Query\Term Current object + */ + public function setRawTerm(array $term) + { + return $this->setParams($term); + } + + /** + * Adds a term to the term query + * + * @param string $key Key to query + * @param string|array $value Values(s) for the query. Boost can be set with array + * @param float $boost OPTIONAL Boost value (default = 1.0) + * @return \Elastica\Query\Term Current object + */ + public function setTerm($key, $value, $boost = 1.0) + { + return $this->setRawTerm(array($key => array('value' => $value, 'boost' => $boost))); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/Terms.php b/vendor/ruflin/elastica/lib/Elastica/Query/Terms.php new file mode 100644 index 00000000..41cc9216 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/Terms.php @@ -0,0 +1,103 @@ +<?php + +namespace Elastica\Query; +use Elastica\Exception\InvalidException; + +/** + * Terms query + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/terms-query.html + */ +class Terms extends AbstractQuery +{ + /** + * Terms + * + * @var array Terms + */ + protected $_terms = array(); + + /** + * Params + * + * @var array Params + */ + protected $_params = array(); + + /** + * Terms key + * + * @var string Terms key + */ + protected $_key = ''; + + /** + * Construct terms query + * + * @param string $key OPTIONAL Terms key + * @param array $terms OPTIONAL Terms list + */ + public function __construct($key = '', array $terms = array()) + { + $this->setTerms($key, $terms); + } + + /** + * Sets key and terms for the query + * + * @param string $key Terms key + * @param array $terms Terms for the query. + * @return \Elastica\Query\Terms + */ + public function setTerms($key, array $terms) + { + $this->_key = $key; + $this->_terms = array_values($terms); + + return $this; + } + + /** + * Adds a single term to the list + * + * @param string $term Term + * @return \Elastica\Query\Terms + */ + public function addTerm($term) + { + $this->_terms[] = $term; + + return $this; + } + + /** + * Sets the minimum matching values + * + * @param int $minimum Minimum value + * @return \Elastica\Query\Terms + */ + public function setMinimumMatch($minimum) + { + return $this->setParam('minimum_match', (int) $minimum); + } + + /** + * Converts the terms object to an array + * + * @see \Elastica\Query\AbstractQuery::toArray() + * @throws \Elastica\Exception\InvalidException + * @return array Query array + */ + public function toArray() + { + if (empty($this->_key)) { + throw new InvalidException('Terms key has to be set'); + } + $this->setParam($this->_key, $this->_terms); + + return parent::toArray(); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/TopChildren.php b/vendor/ruflin/elastica/lib/Elastica/Query/TopChildren.php new file mode 100644 index 00000000..baaf7501 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/TopChildren.php @@ -0,0 +1,52 @@ +<?php + +namespace Elastica\Query; +use Elastica\Query as BaseQuery; + +/** + * Runs the child query with an estimated hits size, and out of the hit docs, aggregates it into parent docs. + * + * @category Xodoa + * @package Elastica + * @author Wu Yang <darkyoung@gmail.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/top-children-query.html + */ +class TopChildren extends AbstractQuery +{ + /** + * Construct topChildren query + * + * @param string|\Elastica\Query|\Elastica\Query\AbstractQuery $query + * @param string $type Parent document type + */ + public function __construct($query, $type = null) + { + $this->setQuery($query); + $this->setType($type); + } + + /** + * Sets query object + * + * @param string|\Elastica\Query|\Elastica\Query\AbstractQuery $query + * @return \Elastica\Query\TopChildren + */ + public function setQuery($query) + { + $query = BaseQuery::create($query); + $data = $query->toArray(); + + return $this->setParam('query', $data['query']); + } + + /** + * Set type of the parent document + * + * @param string $type Parent document type + * @return \Elastica\Query\TopChildren Current object + */ + public function setType($type) + { + return $this->setParam('type', $type); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Query/Wildcard.php b/vendor/ruflin/elastica/lib/Elastica/Query/Wildcard.php new file mode 100644 index 00000000..68aca67e --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Query/Wildcard.php @@ -0,0 +1,41 @@ +<?php + +namespace Elastica\Query; + +/** + * Wildcard query + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/query-dsl/wildcard-query.html + */ +class Wildcard extends AbstractQuery +{ + /** + * Construct wildcard query + * + * @param string $key OPTIONAL Wildcard key + * @param string $value OPTIONAL Wildcard value + * @param float $boost OPTIONAL Boost value (default = 1) + */ + public function __construct($key = '', $value = null, $boost = 1.0) + { + if (!empty($key)) { + $this->setValue($key, $value, $boost); + } + } + + /** + * Sets the query expression for a key with its boost value + * + * @param string $key + * @param string $value + * @param float $boost + * @return \Elastica\Query\Wildcard + */ + public function setValue($key, $value, $boost = 1.0) + { + return $this->setParam($key, array('value' => $value, 'boost' => $boost)); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Request.php b/vendor/ruflin/elastica/lib/Elastica/Request.php new file mode 100644 index 00000000..6c6298be --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Request.php @@ -0,0 +1,200 @@ +<?php + +namespace Elastica; + +use Elastica\Exception\InvalidException; +use Elastica\JSON; + +/** + * Elastica Request object + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class Request extends Param +{ + const HEAD = 'HEAD'; + const POST = 'POST'; + const PUT = 'PUT'; + const GET = 'GET'; + const DELETE = 'DELETE'; + + /** + * @var \Elastica\Connection + */ + protected $_connection; + + /** + * Construct + * + * @param string $path Request path + * @param string $method OPTIONAL Request method (use const's) (default = self::GET) + * @param array $data OPTIONAL Data array + * @param array $query OPTIONAL Query params + * @param Connection $connection + * @return \Elastica\Request OPTIONAL Connection object + */ + public function __construct($path, $method = self::GET, $data = array(), array $query = array(), Connection $connection = null) + { + $this->setPath($path); + $this->setMethod($method); + $this->setData($data); + $this->setQuery($query); + + if ($connection) { + $this->setConnection($connection); + } + } + + /** + * Sets the request method. Use one of the for consts + * + * @param string $method Request method + * @return \Elastica\Request Current object + */ + public function setMethod($method) + { + return $this->setParam('method', $method); + } + + /** + * Get request method + * + * @return string Request method + */ + public function getMethod() + { + return $this->getParam('method'); + } + + /** + * Sets the request data + * + * @param array $data Request data + * @return \Elastica\Request + */ + public function setData($data) + { + return $this->setParam('data', $data); + } + + /** + * Return request data + * + * @return array Request data + */ + public function getData() + { + return $this->getParam('data'); + } + + /** + * Sets the request path + * + * @param string $path Request path + * @return \Elastica\Request Current object + */ + public function setPath($path) + { + return $this->setParam('path', $path); + } + + /** + * Return request path + * + * @return string Request path + */ + public function getPath() + { + return $this->getParam('path'); + } + + /** + * Return query params + * + * @return array Query params + */ + public function getQuery() + { + return $this->getParam('query'); + } + + /** + * @param array $query + * @return \Elastica\Request + */ + public function setQuery(array $query = array()) + { + return $this->setParam('query', $query); + } + + /** + * @param \Elastica\Connection $connection + * @return \Elastica\Request + */ + public function setConnection(Connection $connection) + { + $this->_connection = $connection; + + return $this; + } + + /** + * Return Connection Object + * + * @throws Exception\InvalidException + * @return \Elastica\Connection + */ + public function getConnection() + { + if (empty($this->_connection)) { + throw new InvalidException('No valid connection object set'); + } + + return $this->_connection; + } + + /** + * Sends request to server + * + * @return \Elastica\Response Response object + */ + public function send() + { + $transport = $this->getConnection()->getTransportObject(); + + // Refactor: Not full toArray needed in exec? + return $transport->exec($this, $this->getConnection()->toArray()); + } + + /** + * @return array + */ + public function toArray() + { + $data = $this->getParams(); + if ($this->_connection) { + $data['connection'] = $this->_connection->getParams(); + } + return $data; + } + + /** + * Converts request to curl request format + * + * @return string + */ + public function toString() + { + return JSON::stringify($this->toArray()); + } + + /** + * @return string + */ + public function __toString() + { + return $this->toString(); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Rescore/AbstractRescore.php b/vendor/ruflin/elastica/lib/Elastica/Rescore/AbstractRescore.php new file mode 100644 index 00000000..cb6c7cce --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Rescore/AbstractRescore.php @@ -0,0 +1,36 @@ +<?php + +namespace Elastica\Rescore; +use Elastica\Param; + +/** + * Abstract rescore object. Should be extended by all rescorers. + * + * @category Xodoa + * @package Elastica + * @author Jason Hu <mjhu91@gmail.com> + * @link http://www.elasticsearch.org/guide/reference/api/search/rescore/ + */ +abstract class AbstractRescore extends Param +{ + /** + * Overridden to return rescore as name + * + * @return string name + */ + protected function _getBaseName() + { + return 'rescore'; + } + + /** + * Sets window_size + * + * @param int $size + * @return \Elastica\Rescore + */ + public function setWindowSize($size) + { + return $this->setParam('window_size', $size); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Rescore/Query.php b/vendor/ruflin/elastica/lib/Elastica/Rescore/Query.php new file mode 100644 index 00000000..5041f3ed --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Rescore/Query.php @@ -0,0 +1,90 @@ +<?php + +namespace Elastica\Rescore; + +use Elastica\Query as BaseQuery; + +/** + * Query Rescore + * + * @category Xodoa + * @package Elastica + * @author Jason Hu <mjhu91@gmail.com> + * @link http://www.elasticsearch.org/guide/reference/api/search/rescore/ + */ +class Query extends AbstractRescore +{ + /** + * Constructor + * + * @param string|\Elastica\Query\AbstractQuery $rescoreQuery + * @param string|\Elastica\Query\AbstractQuery $query + */ + public function __construct($query = null) + { + $this->setParam('query', array()); + $this->setRescoreQuery($query); + } + + /** + * Override default implementation so params are in the format + * expected by elasticsearch + * + * @return array Rescore array + */ + public function toArray() + { + $data = $this->getParams(); + + if (!empty($this->_rawParams)) { + $data = array_merge($data, $this->_rawParams); + } + + return $data; + } + + /** + * Sets rescoreQuery object + * + * @param string|\Elastica\Query|\Elastica\Query\AbstractQuery $query + * @return \Elastica\Query\Rescore + */ + public function setRescoreQuery($rescoreQuery) + { + $query = BaseQuery::create($rescoreQuery); + $data = $query->toArray(); + + $query = $this->getParam('query'); + $query['rescore_query'] = $data['query']; + + return $this->setParam('query', $query); + } + + /** + * Sets query_weight + * + * @param float $weight + * @return \Elastica\Query\Rescore + */ + public function setQueryWeight($weight) + { + $query = $this->getParam('query'); + $query['query_weight'] = $weight; + + return $this->setParam('query', $query); + } + + /** + * Sets rescore_query_weight + * + * @param float $size + * @return \Elastica\Query\Rescore + */ + public function setRescoreQueryWeight($weight) + { + $query = $this->getParam('query'); + $query['rescore_query_weight'] = $weight; + + return $this->setParam('query', $query); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Response.php b/vendor/ruflin/elastica/lib/Elastica/Response.php new file mode 100644 index 00000000..5c0ef24d --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Response.php @@ -0,0 +1,299 @@ +<?php + +namespace Elastica; + +use Elastica\Exception\JSONParseException; +use Elastica\Exception\NotFoundException; +use Elastica\JSON; + +/** + * Elastica Response object + * + * Stores query time, and result array -> is given to result set, returned by ... + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class Response +{ + /** + * Query time + * + * @var float Query time + */ + protected $_queryTime = null; + + /** + * Response string (json) + * + * @var string Response + */ + protected $_responseString = ''; + + /** + * Error + * + * @var boolean Error + */ + protected $_error = false; + + /** + * Transfer info + * + * @var array transfer info + */ + protected $_transferInfo = array(); + + /** + * Response + * + * @var \Elastica\Response Response object + */ + protected $_response = null; + + /** + * HTTP response status code + * + * @var int + */ + protected $_status = null; + + /** + * Construct + * + * @param string|array $responseString Response string (json) + * @param int $responseStatus http status code + */ + public function __construct($responseString, $responseStatus = null) + { + if (is_array($responseString)) { + $this->_response = $responseString; + } else { + $this->_responseString = $responseString; + } + $this->_status = $responseStatus; + } + + /** + * Error message + * + * @return string Error message + */ + public function getError() + { + $message = ''; + $response = $this->getData(); + + if (isset($response['error'])) { + $message = $response['error']; + } + + return $message; + } + + /** + * True if response has error + * + * @return bool True if response has error + */ + public function hasError() + { + $response = $this->getData(); + + if (isset($response['error'])) { + return true; + } + + return false; + } + + /** + * True if response has failed shards + * + * @return bool True if response has failed shards + */ + public function hasFailedShards() + { + try { + $shardsStatistics = $this->getShardsStatistics(); + } catch (NotFoundException $e) { + return false; + } + + return array_key_exists('failures', $shardsStatistics); + } + + /** + * Checks if the query returned ok + * + * @return bool True if ok + */ + public function isOk() + { + $data = $this->getData(); + + // Bulk insert checks. Check every item + if (isset($data['status'])) { + if ($data['status'] >= 200 && $data['status'] <= 300) { + return true; + } + return false; + } + if (isset($data['items'])) { + foreach ($data['items'] as $item) { + if (false == $item['index']['ok']) { + return false; + } + } + + return true; + } + + if ($this->_status >= 200 && $this->_status <= 300) { + // http status is ok + return true; + } + + return (isset($data['ok']) && $data['ok']); + } + + /** + * @return int + */ + public function getStatus() + { + return $this->_status; + } + + + /** + * Response data array + * + * @return array Response data array + */ + public function getData() + { + if ($this->_response == null) { + $response = $this->_responseString; + if ($response === false) { + $this->_error = true; + } else { + try { + $response = JSON::parse($response); + } catch (JSONParseException $e) { + // leave reponse as is if parse fails + } + } + + if (empty($response)) { + $response = array(); + } + + if (is_string($response)) { + $response = array('message' => $response); + } + + $this->_response = $response; + } + + return $this->_response; + } + + /** + * Gets the transfer information. + * + * @return array Information about the curl request. + */ + public function getTransferInfo() + { + return $this->_transferInfo; + } + + /** + * Sets the transfer info of the curl request. This function is called + * from the \Elastica\Client::_callService . + * + * @param array $transferInfo The curl transfer information. + * @return \Elastica\Response Current object + */ + public function setTransferInfo(array $transferInfo) + { + $this->_transferInfo = $transferInfo; + return $this; + } + + /** + * This is only available if DEBUG constant is set to true + * + * @return float Query time + */ + public function getQueryTime() + { + return $this->_queryTime; + } + + /** + * Sets the query time + * + * @param float $queryTime Query time + * @return \Elastica\Response Current object + */ + public function setQueryTime($queryTime) + { + $this->_queryTime = $queryTime; + + return $this; + } + + /** + * Time request took + * + * @throws \Elastica\Exception\NotFoundException + * @return int Time request took + */ + public function getEngineTime() + { + $data = $this->getData(); + + if (!isset($data['took'])) { + throw new NotFoundException("Unable to find the field [took]from the response"); + } + + return $data['took']; + } + + /** + * Get the _shard statistics for the response + * + * @throws \Elastica\Exception\NotFoundException + * @return array + */ + public function getShardsStatistics() + { + $data = $this->getData(); + + if (!isset($data['_shards'])) { + throw new NotFoundException("Unable to find the field [_shards] from the response"); + } + + return $data['_shards']; + } + + /** + * Get the _scroll value for the response + * + * @throws \Elastica\Exception\NotFoundException + * @return string + */ + public function getScrollId() + { + $data = $this->getData(); + + if (!isset($data['_scroll_id'])) { + throw new NotFoundException("Unable to find the field [_scroll_id] from the response"); + } + + return $data['_scroll_id']; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Result.php b/vendor/ruflin/elastica/lib/Elastica/Result.php new file mode 100644 index 00000000..e8aa8e3d --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Result.php @@ -0,0 +1,216 @@ +<?php + +namespace Elastica; + +/** + * Elastica result item + * + * Stores all information from a result + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class Result +{ + /** + * Hit array + * + * @var array Hit array + */ + protected $_hit = array(); + + /** + * Constructs a single results object + * + * @param array $hit Hit data + */ + public function __construct(array $hit) + { + $this->_hit = $hit; + } + + /** + * Returns a param from the result hit array + * + * This function can be used to retrieve all data for which a specific + * function doesn't exist. + * If the param does not exist, an empty array is returned + * + * @param string $name Param name + * @return array Result data + */ + public function getParam($name) + { + if (isset($this->_hit[$name])) { + return $this->_hit[$name]; + } + + return array(); + } + + /** + * Test if a param from the result hit is set + * + * @param string $name Param name to test + * @return boolean True if the param is set, false otherwise + */ + public function hasParam($name) + { + return isset($this->_hit[$name]); + } + + /** + * Returns the hit id + * + * @return string Hit id + */ + public function getId() + { + return $this->getParam('_id'); + } + + /** + * Returns the type of the result + * + * @return string Result type + */ + public function getType() + { + return $this->getParam('_type'); + } + + /** + * Returns list of fields + * + * @return array Fields list + */ + public function getFields() + { + return $this->getParam('fields'); + } + + /** + * Returns whether result has fields + * + * @return bool + */ + public function hasFields() + { + return $this->hasParam('fields'); + } + + /** + * Returns the index name of the result + * + * @return string Index name + */ + public function getIndex() + { + return $this->getParam('_index'); + } + + /** + * Returns the score of the result + * + * @return float Result score + */ + public function getScore() + { + return $this->getParam('_score'); + } + + /** + * Returns the raw hit array + * + * @return array Hit array + */ + public function getHit() + { + return $this->_hit; + } + + /** + * Returns the version information from the hit + * + * @return string|int Document version + */ + public function getVersion() + { + return $this->getParam('_version'); + } + + /** + * Returns result data + * + * Checks for partial result data with getFields, falls back to getSource + * + * @return array Result data array + */ + public function getData() + { + if (isset($this->_hit['fields']) && !isset($this->_hit['_source'])) { + return $this->getFields(); + } + + return $this->getSource(); + } + + /** + * Returns the result source + * + * @return array Source data array + */ + public function getSource() + { + return $this->getParam('_source'); + } + + /** + * Returns result data + * + * @return array Result data array + */ + public function getHighlights() + { + return $this->getParam('highlight'); + } + + /** + * Returns explanation on how its score was computed. + * + * @return array explanations + */ + public function getExplanation() + { + return $this->getParam('_explanation'); + } + + /** + * Magic function to directly access keys inside the result + * + * Returns null if key does not exist + * + * @param string $key Key name + * @return mixed Key value + */ + public function __get($key) + { + $source = $this->getData(); + + return array_key_exists($key, $source) ? $source[$key] : null; + } + + /** + * Magic function to support isset() calls + * + * @param string $key Key name + * @return bool + */ + public function __isset($key) + { + $source = $this->getData(); + + return array_key_exists($key, $source) && $source[$key] !== null; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/ResultSet.php b/vendor/ruflin/elastica/lib/Elastica/ResultSet.php new file mode 100644 index 00000000..3bb94fb0 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/ResultSet.php @@ -0,0 +1,383 @@ +<?php + +namespace Elastica; +use Elastica\Exception\InvalidException; + +/** + * Elastica result set + * + * List of all hits that are returned for a search on elasticsearch + * Result set implements iterator + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class ResultSet implements \Iterator, \Countable, \ArrayAccess +{ + /** + * Results + * + * @var array Results + */ + protected $_results = array(); + + /** + * Current position + * + * @var int Current position + */ + protected $_position = 0; + + /** + * Response + * + * @var \Elastica\Response Response object + */ + protected $_response = null; + + /** + * Query + * + * @var \Elastica\Query Query object + */ + protected $_query; + + /** + * @var int + */ + protected $_took = 0; + + /** + * @var boolean + */ + protected $_timedOut = false; + + /** + * @var int + */ + protected $_totalHits = 0; + + /** + * @var float + */ + protected $_maxScore = 0; + + /** + * Constructs ResultSet object + * + * @param \Elastica\Response $response Response object + * @param \Elastica\Query $query Query object + */ + public function __construct(Response $response, Query $query) + { + $this->rewind(); + $this->_init($response); + $this->_query = $query; + } + + /** + * Loads all data into the results object (initialisation) + * + * @param \Elastica\Response $response Response object + */ + protected function _init(Response $response) + { + $this->_response = $response; + $result = $response->getData(); + $this->_totalHits = isset($result['hits']['total']) ? $result['hits']['total'] : 0; + $this->_maxScore = isset($result['hits']['max_score']) ? $result['hits']['max_score'] : 0; + $this->_took = isset($result['took']) ? $result['took'] : 0; + $this->_timedOut = !empty($result['timed_out']); + if (isset($result['hits']['hits'])) { + foreach ($result['hits']['hits'] as $hit) { + $this->_results[] = new Result($hit); + } + } + } + + /** + * Returns all results + * + * @return Result[] Results + */ + public function getResults() + { + return $this->_results; + } + + /** + * Returns true if the response contains suggestion results; false otherwise + * @return bool + */ + public function hasSuggests(){ + $data = $this->_response->getData(); + return isset($data['suggest']); + } + + /** + * Return all suggests + * + * @return array suggest results + */ + public function getSuggests() + { + $data = $this->_response->getData(); + return isset($data['suggest']) ? $data['suggest'] : array(); + } + + /** + * Returns whether facets exist + * + * @return boolean Facet existence + */ + public function hasFacets() + { + $data = $this->_response->getData(); + + return isset($data['facets']); + } + + /** + * Returns whether aggregations exist + * + * @return boolean Aggregation existence + */ + public function hasAggregations() + { + $data = $this->_response->getData(); + + return isset($data['aggregations']); + } + + /** + * Returns all aggregation results + * + * @return array + */ + public function getAggregations() + { + $data = $this->_response->getData(); + + return isset($data['aggregations']) ? $data['aggregations'] : array(); + } + + /** + * Retrieve a specific aggregation from this result set + * @param string $name the name of the desired aggregation + * @return array + * @throws Exception\InvalidException if an aggregation by the given name cannot be found + */ + public function getAggregation($name) + { + $data = $this->_response->getData(); + + if (isset($data['aggregations']) && isset($data['aggregations'][$name])) { + return $data['aggregations'][$name]; + } + throw new InvalidException("This result set does not contain an aggregation named {$name}."); + } + + /** + * Returns all facets results + * + * @return array Facet results + */ + public function getFacets() + { + $data = $this->_response->getData(); + + return isset($data['facets']) ? $data['facets'] : array(); + } + + /** + * Returns the total number of found hits + * + * @return int Total hits + */ + public function getTotalHits() + { + return (int) $this->_totalHits; + } + + /** + * Returns the max score of the results found + * + * @return float Max Score + */ + public function getMaxScore() + { + return (float) $this->_maxScore; + } + + /** + * Returns the total number of ms for this search to complete + * + * @return int Total time + */ + public function getTotalTime() + { + return (int) $this->_took; + } + + /** + * Returns true iff the query has timed out + * + * @return bool Timed out + */ + public function hasTimedOut() + { + return (bool) $this->_timedOut; + } + + /** + * Returns response object + * + * @return \Elastica\Response Response object + */ + public function getResponse() + { + return $this->_response; + } + + /** + * @return \Elastica\Query + */ + public function getQuery() + { + return $this->_query; + } + + /** + * Returns size of current set + * + * @return int Size of set + */ + public function count() + { + return sizeof($this->_results); + } + + /** + * Returns size of current suggests + * + * @return int Size of suggests + */ + public function countSuggests() + { + return sizeof($this->getSuggests()); + } + + /** + * Returns the current object of the set + * + * @return \Elastica\Result|bool Set object or false if not valid (no more entries) + */ + public function current() + { + if ($this->valid()) { + return $this->_results[$this->key()]; + } else { + return false; + } + } + + /** + * Sets pointer (current) to the next item of the set + */ + public function next() + { + $this->_position++; + + return $this->current(); + } + + /** + * Returns the position of the current entry + * + * @return int Current position + */ + public function key() + { + return $this->_position; + } + + /** + * Check if an object exists at the current position + * + * @return bool True if object exists + */ + public function valid() + { + return isset($this->_results[$this->key()]); + } + + /** + * Resets position to 0, restarts iterator + */ + public function rewind() + { + $this->_position = 0; + } + + /** + * Whether a offset exists + * @link http://php.net/manual/en/arrayaccess.offsetexists.php + * + * @param integer $offset + * @return boolean true on success or false on failure. + */ + public function offsetExists($offset) + { + return isset($this->_results[$offset]); + } + + /** + * Offset to retrieve + * @link http://php.net/manual/en/arrayaccess.offsetget.php + * + * @param integer $offset + * @throws Exception\InvalidException + * @return Result|null + */ + public function offsetGet($offset) + { + if ($this->offsetExists($offset)) { + return $this->_results[$offset]; + } else { + throw new InvalidException("Offset does not exist."); + } + } + + /** + * Offset to set + * @link http://php.net/manual/en/arrayaccess.offsetset.php + * + * @param integer $offset + * @param Result $value + * @throws Exception\InvalidException + */ + public function offsetSet($offset, $value) + { + if (!($value instanceof Result)) { + throw new InvalidException("ResultSet is a collection of Result only."); + } + + if (!isset($this->_results[$offset])) { + throw new InvalidException("Offset does not exist."); + } + + $this->_results[$offset] = $value; + } + + /** + * Offset to unset + * @link http://php.net/manual/en/arrayaccess.offsetunset.php + * + * @param integer $offset + */ + public function offsetUnset($offset) + { + unset($this->_results[$offset]); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/ScanAndScroll.php b/vendor/ruflin/elastica/lib/Elastica/ScanAndScroll.php new file mode 100644 index 00000000..c83054e8 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/ScanAndScroll.php @@ -0,0 +1,150 @@ +<?php + +namespace Elastica; + +/** + * scan and scroll object + * + * @category Xodoa + * @package Elastica + * @author Manuel Andreo Garcia <andreo.garcia@gmail.com> + * @link http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/scan-scroll.html + */ +class ScanAndScroll implements \Iterator { + + /** + * time value parameter + * + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-scroll.html + * @var string + */ + public $expiryTime; + + /** + * @var int + */ + public $sizePerShard; + + /** + * @var Search + */ + protected $_search; + + /** + * @var null|string + */ + protected $_nextScrollId = null; + + /** + * @var null|string + */ + protected $_lastScrollId = null; + + /** + * @var null|ResultSet + */ + protected $_currentResultSet = null; + + /** + * Constructs scroll iterator object + * + * @param Search $search + * @param string $expiryTime + * @param int $sizePerShard + */ + public function __construct(Search $search, $expiryTime = '1m', $sizePerShard = 1000) { + $this->_search = $search; + $this->expiryTime = $expiryTime; + $this->sizePerShard = $sizePerShard; + } + + /** + * Return the current result set + * + * @link http://php.net/manual/en/iterator.current.php + * @return ResultSet + */ + public function current() { + return $this->_currentResultSet; + } + + /** + * Perform next scroll search + * + * @link http://php.net/manual/en/iterator.next.php + * @return void + */ + public function next() { + $this->_scroll(); + } + + /** + * Return the scroll id of current scroll request + * + * @link http://php.net/manual/en/iterator.key.php + * @return string + */ + public function key() { + return $this->_lastScrollId; + } + + /** + * Returns true if current result set contains one hit + * + * @link http://php.net/manual/en/iterator.valid.php + * @return boolean + */ + public function valid() { + return + $this->_nextScrollId !== null + && $this->_currentResultSet !== null + && $this->_currentResultSet->count() > 0; + } + + /** + * Start the initial scan search + * @link http://php.net/manual/en/iterator.rewind.php + * @throws \Elastica\Exception\InvalidException + * @return void + */ + public function rewind() { + $this->_search->getQuery()->setSize($this->sizePerShard); + + $this->_search->setOption(Search::OPTION_SEARCH_TYPE, Search::OPTION_SEARCH_TYPE_SCAN); + $this->_search->setOption(Search::OPTION_SCROLL, $this->expiryTime); + + // initial scan request + $this->_setScrollId($this->_search->search()); + + // trigger first scroll request + $this->_scroll(); + } + + /** + * Perform next scroll search + * @throws \Elastica\Exception\InvalidException + * @return void + */ + protected function _scroll() { + $this->_search->setOption(Search::OPTION_SEARCH_TYPE, Search::OPTION_SEARCH_TYPE_SCROLL); + $this->_search->setOption(Search::OPTION_SCROLL_ID, $this->_nextScrollId); + + $resultSet = $this->_search->search(); + $this->_currentResultSet = $resultSet; + $this->_setScrollId($resultSet); + } + + /** + * Save last scroll id and extract the new one if possible + * @param ResultSet $resultSet + */ + protected function _setScrollId(ResultSet $resultSet) { + $this->_lastScrollId = $this->_nextScrollId; + + $this->_nextScrollId = null; + if($resultSet->getResponse()->isOk()) { + $this->_nextScrollId = $resultSet->getResponse()->getScrollId(); + } + } + +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Script.php b/vendor/ruflin/elastica/lib/Elastica/Script.php new file mode 100644 index 00000000..99d9a6aa --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Script.php @@ -0,0 +1,148 @@ +<?php + +namespace Elastica; + +use Elastica\Exception\InvalidException; + +/** + * Script objects, containing script internals + * + * @category Xodoa + * @package Elastica + * @author avasilenko <aa.vasilenko@gmail.com> + * @link http://www.elasticsearch.org/guide/reference/modules/scripting.html + */ +class Script extends AbstractUpdateAction +{ + const LANG_MVEL = 'mvel'; + const LANG_JS = 'js'; + const LANG_GROOVY = 'groovy'; + const LANG_PYTHON = 'python'; + const LANG_NATIVE = 'native'; + + /** + * @var string + */ + private $_script; + + /** + * @var string + */ + private $_lang; + + /** + * @param string $script + * @param array|null $params + * @param string|null $lang + */ + public function __construct($script, array $params = null, $lang = null, $id = null) + { + $this->setScript($script); + if ($params) { + $this->setParams($params); + } + if ($lang) { + $this->setLang($lang); + } + + if ($id) { + $this->setId($id); + } + } + + /** + * @param string $lang + */ + public function setLang($lang) + { + $this->_lang = $lang; + } + + /** + * @return string + */ + public function getLang() + { + return $this->_lang; + } + + /** + * @param string $script + */ + public function setScript($script) + { + $this->_script = $script; + } + + /** + * @return string + */ + public function getScript() + { + return $this->_script; + } + + /** + * @param string|array|\Elastica\Script $data + * @throws \Elastica\Exception\InvalidException + * @return \Elastica\Script + */ + public static function create($data) + { + if ($data instanceof self) { + $script = $data; + } elseif (is_array($data)) { + $script = self::_createFromArray($data); + } elseif (is_string($data)) { + $script = new self($data); + } else { + throw new InvalidException('Failed to create script. Invalid data passed.'); + } + + return $script; + } + + /** + * @param array $data + * @throws \Elastica\Exception\InvalidException + * @return \Elastica\Script + */ + protected static function _createFromArray(array $data) + { + if (!isset($data['script'])) { + throw new InvalidException("\$data['script'] is required"); + } + + $script = new self($data['script']); + + if (isset($data['lang'])) { + $script->setLang($data['lang']); + } + if (isset($data['params'])) { + if (!is_array($data['params'])) { + throw new InvalidException("\$data['params'] should be array"); + } + $script->setParams($data['params']); + } + + return $script; + } + + /** + * @return array + */ + public function toArray() + { + $array = array( + 'script' => $this->_script, + ); + if (!empty($this->_params)) { + $array['params'] = $this->_params; + } + if ($this->_lang) { + $array['lang'] = $this->_lang; + } + + return $array; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/ScriptFields.php b/vendor/ruflin/elastica/lib/Elastica/ScriptFields.php new file mode 100644 index 00000000..0a8b4871 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/ScriptFields.php @@ -0,0 +1,63 @@ +<?php + +namespace Elastica; +use Elastica\Exception\InvalidException; + +/** + * Container for scripts as fields + * + * @category Xodoa + * @package Elastica + * @author Sebastien Lavoie <github@lavoie.sl> + * @link http://www.elasticsearch.org/guide/reference/api/search/script-fields.html + */ +class ScriptFields extends Param +{ + /** + * @param \Elastica\Script[]|array $scripts OPTIONAL + */ + public function __construct(array $scripts = array()) + { + if ($scripts) { + $this->setScripts($scripts); + } + } + + /** + * @param string $name Name of the Script field + * @param \Elastica\Script $script + * @throws \Elastica\Exception\InvalidException + * @return \Elastica\ScriptFields + */ + public function addScript($name, Script $script) + { + if (!is_string($name) || !strlen($name)) { + throw new InvalidException('The name of a Script is required and must be a string'); + } + $this->setParam($name, $script->toArray()); + + return $this; + } + + /** + * @param \Elastica\Script[]|array $scripts Associative array of string => Elastica\Script + * @return \Elastica\ScriptFields + */ + public function setScripts(array $scripts) + { + $this->_params = array(); + foreach ($scripts as $name => $script) { + $this->addScript($name, $script); + } + + return $this; + } + + /** + * @return array + */ + public function toArray() + { + return $this->_params; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Search.php b/vendor/ruflin/elastica/lib/Elastica/Search.php new file mode 100644 index 00000000..4163a1a2 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Search.php @@ -0,0 +1,514 @@ +<?php + +namespace Elastica; + +use Elastica\Exception\InvalidException; +use Elastica\Suggest; + +/** + * Elastica search object + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class Search +{ + /* + * Options + */ + const OPTION_SEARCH_TYPE = 'search_type'; + const OPTION_ROUTING = 'routing'; + const OPTION_PREFERENCE = 'preference'; + const OPTION_VERSION = 'version'; + const OPTION_TIMEOUT = 'timeout'; + const OPTION_FROM = 'from'; + const OPTION_SIZE = 'size'; + const OPTION_SCROLL = 'scroll'; + const OPTION_SCROLL_ID = 'scroll_id'; + + /* + * Search types + */ + const OPTION_SEARCH_TYPE_COUNT = 'count'; + const OPTION_SEARCH_TYPE_SCAN = 'scan'; + const OPTION_SEARCH_TYPE_DFS_QUERY_THEN_FETCH = 'dfs_query_then_fetch'; + const OPTION_SEARCH_TYPE_DFS_QUERY_AND_FETCH = 'dfs_query_and_fetch'; + const OPTION_SEARCH_TYPE_QUERY_THEN_FETCH = 'query_then_fetch'; + const OPTION_SEARCH_TYPE_QUERY_AND_FETCH = 'query_and_fetch'; + const OPTION_SEARCH_TYPE_SUGGEST = 'suggest'; + const OPTION_SEARCH_TYPE_SCROLL = 'scroll'; + + /** + * Array of indices + * + * @var array + */ + protected $_indices = array(); + + /** + * Array of types + * + * @var array + */ + protected $_types = array(); + + /** + * @var \Elastica\Query + */ + protected $_query; + + /** + * @var array + */ + protected $_options = array(); + + /** + * Client object + * + * @var \Elastica\Client + */ + protected $_client; + + /** + * Constructs search object + * + * @param \Elastica\Client $client Client object + */ + public function __construct(Client $client) + { + $this->_client = $client; + } + + /** + * Adds a index to the list + * + * @param \Elastica\Index|string $index Index object or string + * @throws \Elastica\Exception\InvalidException + * @return \Elastica\Search Current object + */ + public function addIndex($index) + { + if ($index instanceof Index) { + $index = $index->getName(); + } + + if (!is_string($index)) { + throw new InvalidException('Invalid param type'); + } + + $this->_indices[] = $index; + + return $this; + } + + /** + * Add array of indices at once + * + * @param array $indices + * @return \Elastica\Search + */ + public function addIndices(array $indices = array()) + { + foreach ($indices as $index) { + $this->addIndex($index); + } + + return $this; + } + + /** + * Adds a type to the current search + * + * @param \Elastica\Type|string $type Type name or object + * @return \Elastica\Search Search object + * @throws \Elastica\Exception\InvalidException + */ + public function addType($type) + { + if ($type instanceof Type) { + $type = $type->getName(); + } + + if (!is_string($type)) { + throw new InvalidException('Invalid type type'); + } + + $this->_types[] = $type; + + return $this; + } + + /** + * Add array of types + * + * @param array $types + * @return \Elastica\Search + */ + public function addTypes(array $types = array()) + { + foreach ($types as $type) { + $this->addType($type); + } + + return $this; + } + + /** + * @param string|array|\Elastica\Query|\Elastica\Suggest|\Elastica\Query\AbstractQuery|\Elastica\Filter\AbstractFilter $query| + * @return \Elastica\Search + */ + public function setQuery($query) + { + $this->_query = Query::create($query); + + return $this; + } + + /** + * @param string $key + * @param mixed $value + * @return \Elastica\Search + */ + public function setOption($key, $value) + { + $this->_validateOption($key); + + $this->_options[$key] = $value; + + return $this; + } + + /** + * @param array $options + * @return \Elastica\Search + */ + public function setOptions(array $options) + { + $this->clearOptions(); + + foreach ($options as $key => $value) { + $this->setOption($key, $value); + } + + return $this; + } + + /** + * @return \Elastica\Search + */ + public function clearOptions() + { + $this->_options = array(); + + return $this; + } + + /** + * @param string $key + * @param mixed $value + * @return \Elastica\Search + */ + public function addOption($key, $value) + { + $this->_validateOption($key); + + if (!isset($this->_options[$key])) { + $this->_options[$key] = array(); + } + + $this->_options[$key][] = $value; + + return $this; + } + + /** + * @param string $key + * @return bool + */ + public function hasOption($key) + { + return isset($this->_options[$key]); + } + + /** + * @param string $key + * @return mixed + * @throws \Elastica\Exception\InvalidException + */ + public function getOption($key) + { + if (!$this->hasOption($key)) { + throw new InvalidException('Option ' . $key . ' does not exist'); + } + + return $this->_options[$key]; + } + + /** + * @return array + */ + public function getOptions() + { + return $this->_options; + } + + /** + * @param string $key + * @return bool + * @throws \Elastica\Exception\InvalidException + */ + protected function _validateOption($key) + { + switch ($key) { + case self::OPTION_SEARCH_TYPE: + case self::OPTION_ROUTING: + case self::OPTION_PREFERENCE: + case self::OPTION_VERSION: + case self::OPTION_TIMEOUT: + case self::OPTION_FROM: + case self::OPTION_SIZE: + case self::OPTION_SCROLL: + case self::OPTION_SCROLL_ID: + case self::OPTION_SEARCH_TYPE_SUGGEST: + return true; + } + + throw new InvalidException('Invalid option ' . $key); + } + + /** + * Return client object + * + * @return \Elastica\Client Client object + */ + public function getClient() + { + return $this->_client; + } + + /** + * Return array of indices + * + * @return array List of index names + */ + public function getIndices() + { + return $this->_indices; + } + + /** + * @return bool + */ + public function hasIndices() + { + return count($this->_indices) > 0; + } + + /** + * @param Index|string $index + * @return bool + */ + public function hasIndex($index) + { + if ($index instanceof Index) { + $index = $index->getName(); + } + + return in_array($index, $this->_indices); + } + + /** + * Return array of types + * + * @return array List of types + */ + public function getTypes() + { + return $this->_types; + } + + /** + * @return bool + */ + public function hasTypes() + { + return count($this->_types) > 0; + } + + /** + * @param \Elastica\Type|string $type + * @return bool + */ + public function hasType($type) + { + if ($type instanceof Type) { + $type = $type->getName(); + } + + return in_array($type, $this->_types); + } + + /** + * @return \Elastica\Query + */ + public function getQuery() + { + if (null === $this->_query) { + $this->_query = Query::create(''); + } + + return $this->_query; + } + + /** + * Creates new search object + * + * @param \Elastica\SearchableInterface $searchObject + * @return \Elastica\Search + */ + public static function create(SearchableInterface $searchObject) + { + return $searchObject->createSearch(); + } + + /** + * Combines indices and types to the search request path + * + * @return string Search path + */ + public function getPath() + { + if (isset($this->_options[self::OPTION_SCROLL_ID])) { + return '_search/scroll'; + } + + $indices = $this->getIndices(); + + $path = ''; + $types = $this->getTypes(); + + if (empty($indices)) { + if (!empty($types)) { + $path .= '_all'; + } + } else { + $path .= implode(',', $indices); + } + + if (!empty($types)) { + $path .= '/' . implode(',', $types); + } + + // Add full path based on indices and types -> could be all + return $path . '/_search'; + } + + /** + * Search in the set indices, types + * + * @param mixed $query + * @param int|array $options OPTIONAL Limit or associative array of options (option=>value) + * @throws \Elastica\Exception\InvalidException + * @return \Elastica\ResultSet + */ + public function search($query = '', $options = null) + { + $this->setOptionsAndQuery($options, $query); + + $query = $this->getQuery(); + $path = $this->getPath(); + + $params = $this->getOptions(); + + // Send scroll_id via raw HTTP body to handle cases of very large (> 4kb) ids. + if ('_search/scroll' == $path) { + $data = $params[self::OPTION_SCROLL_ID]; + unset($params[self::OPTION_SCROLL_ID]); + } else { + $data = $query->toArray(); + } + + $response = $this->getClient()->request( + $path, + Request::GET, + $data, + $params + ); + + return new ResultSet($response, $query); + } + + /** + * + * @param mixed $query + * @param $fullResult (default = false) By default only the total hit count is returned. If set to true, the full ResultSet including facets is returned. + * @return int|ResultSet + */ + public function count($query = '', $fullResult = false) + { + $this->setOptionsAndQuery(null, $query); + + $query = $this->getQuery(); + $path = $this->getPath(); + + $response = $this->getClient()->request( + $path, + Request::GET, + $query->toArray(), + array(self::OPTION_SEARCH_TYPE => self::OPTION_SEARCH_TYPE_COUNT) + ); + $resultSet = new ResultSet($response, $query); + + return $fullResult ? $resultSet : $resultSet->getTotalHits(); + } + + /** + * @param array|int $options + * @param string|array|\Elastica\Query $query + * @return \Elastica\Search + */ + public function setOptionsAndQuery($options = null, $query = '') + { + if ('' != $query) { + $this->setQuery($query); + } + + if (is_int($options)) { + $this->getQuery()->setSize($options); + } elseif (is_array($options)) { + if (isset($options['limit'])) { + $this->getQuery()->setSize($options['limit']); + unset($options['limit']); + } + if (isset($options['explain'])) { + $this->getQuery()->setExplain($options['explain']); + unset($options['explain']); + } + $this->setOptions($options); + } + + return $this; + } + + /** + * @param Suggest $suggest + * @return Search + */ + public function setSuggest(Suggest $suggest) + { + return $this->setOptionsAndQuery(array(self::OPTION_SEARCH_TYPE_SUGGEST => 'suggest'), $suggest); + } + + /** + * Returns the ScanAndScroll Iterator + * + * @see Elastica\ScanAndScroll + * @param string $expiryTime + * @param int $sizePerShard + * @return ScanAndScroll + */ + public function scanAndScroll($expiryTime = '1m', $sizePerShard = 1000) { + return new ScanAndScroll($this, $expiryTime, $sizePerShard); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/SearchableInterface.php b/vendor/ruflin/elastica/lib/Elastica/SearchableInterface.php new file mode 100644 index 00000000..372bcb11 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/SearchableInterface.php @@ -0,0 +1,52 @@ +<?php + +namespace Elastica; + +/** + * Elastica searchable interface + * + * @category Xodoa + * @package Elastica + * @author Thibault Duplessis <thibault.duplessis@gmail.com> + */ +interface SearchableInterface +{ + /** + * Searches results for a query + * + * TODO: Improve sample code + * { + * "from" : 0, + * "size" : 10, + * "sort" : { + * "postDate" : {"reverse" : true}, + * "user" : { }, + * "_score" : { } + * }, + * "query" : { + * "term" : { "user" : "kimchy" } + * } + * } + * + * @param string|array|\Elastica\Query $query Array with all query data inside or a Elastica\Query object + * @return \Elastica\ResultSet ResultSet with all results inside + */ + public function search($query = '', $options = null); + + /** + * Counts results for a query + * + * If no query is set, matchall query is created + * + * @param string|array|\Elastica\Query $query Array with all query data inside or a Elastica\Query object + * @return int number of documents matching the query + */ + public function count($query = ''); + + /** + * @param \Elastica\Query $query + * @param array $options + * @return \Elastica\Search + */ + public function createSearch($query = '', $options = null); +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Snapshot.php b/vendor/ruflin/elastica/lib/Elastica/Snapshot.php new file mode 100644 index 00000000..4b32172c --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Snapshot.php @@ -0,0 +1,155 @@ +<?php + +namespace Elastica; + +use Elastica\Exception\NotFoundException; +use Elastica\Exception\ResponseException; + +/** + * Class Snapshot + * @package Elastica + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/modules-snapshots.html + */ +class Snapshot +{ + /** + * @var Client + */ + protected $_client; + + /** + * @param Client $client + */ + public function __construct(Client $client) + { + $this->_client = $client; + } + + /** + * Register a snapshot repository + * @param string $name the name of the repository + * @param string $type the repository type ("fs" for file system) + * @param array $settings Additional repository settings. If type "fs" is used, the "location" setting must be provided. + * @return Response + */ + public function registerRepository($name, $type, $settings = array()) + { + $data = array( + 'type' => $type, + 'settings' => $settings + ); + return $this->request($name, Request::PUT, $data); + } + + /** + * Retrieve a repository record by name + * @param string $name the name of the desired repository + * @throws Exception\ResponseException + * @throws Exception\NotFoundException + * @return array + */ + public function getRepository($name) + { + try { + $response = $this->request($name); + } catch (ResponseException $e) { + if ($e->getResponse()->getStatus() == 404) { + throw new NotFoundException("Repository '" . $name . "' does not exist."); + } + throw $e; + } + $data = $response->getData(); + return $data[$name]; + } + + /** + * Retrieve all repository records + * @return array + */ + public function getAllRepositories() + { + return $this->request("_all")->getData(); + } + + /** + * Create a new snapshot + * @param string $repository the name of the repository in which this snapshot should be stored + * @param string $name the name of this snapshot + * @param array $options optional settings for this snapshot + * @param bool $waitForCompletion if true, the request will not return until the snapshot operation is complete + * @return Response + */ + public function createSnapshot($repository, $name, $options = array(), $waitForCompletion = false) + { + return $this->request($repository . '/' . $name, Request::PUT, $options, array('wait_for_completion' => $waitForCompletion)); + } + + /** + * Retrieve data regarding a specific snapshot + * @param string $repository the name of the repository from which to retrieve the snapshot + * @param string $name the name of the desired snapshot + * @throws Exception\ResponseException + * @throws Exception\NotFoundException + * @return array + */ + public function getSnapshot($repository, $name) + { + try { + $response = $this->request($repository . "/" . $name); + } catch (ResponseException $e) { + if ($e->getResponse()->getStatus() == 404) { + throw new NotFoundException("Snapshot '" . $name . "' does not exist in repository '" . $repository . "'."); + } + throw $e; + } + $data = $response->getData(); + return $data['snapshots'][0]; + } + + /** + * Retrieve data regarding all snapshots in the given repository + * @param string $repository the repository name + * @return array + */ + public function getAllSnapshots($repository) + { + return $this->request($repository . "/_all")->getData(); + } + + /** + * Delete a snapshot + * @param string $repository the repository in which the snapshot resides + * @param string $name the name of the snapshot to be deleted + * @return Response + */ + public function deleteSnapshot($repository, $name) + { + return $this->request($repository . "/" . $name, Request::DELETE); + } + + /** + * Restore a snapshot + * @param string $repository the name of the repository + * @param string $name the name of the snapshot + * @param array $options options for the restore operation + * @param bool $waitForCompletion if true, the request will not return until the restore operation is complete + * @return Response + */ + public function restoreSnapshot($repository, $name, $options = array(), $waitForCompletion = false) + { + return $this->request($repository . "/" . $name . "/_restore", Request::POST, $options, array("wait_for_completion" => $waitForCompletion)); + } + + /** + * Perform a snapshot request + * @param string $path the URL + * @param string $method the HTTP method + * @param array $data request body data + * @param array $query query string parameters + * @return Response + */ + public function request($path, $method = Request::GET, $data = array(), array $query = array()) + { + return $this->_client->request("/_snapshot/" . $path, $method, $data, $query); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Status.php b/vendor/ruflin/elastica/lib/Elastica/Status.php new file mode 100644 index 00000000..a747b9a5 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Status.php @@ -0,0 +1,179 @@ +<?php + +namespace Elastica; +use Elastica\Exception\ResponseException; +use Elastica\Index\Status as IndexStatus; + +/** + * Elastica general status + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-status.html + */ +class Status +{ + /** + * Contains all status infos + * + * @var \Elastica\Response Response object + */ + protected $_response = null; + + /** + * Data + * + * @var array Data + */ + protected $_data = array(); + + /** + * Client object + * + * @var \Elastica\Client Client object + */ + protected $_client = null; + + /** + * Constructs Status object + * + * @param \Elastica\Client $client Client object + */ + public function __construct(Client $client) + { + $this->_client = $client; + $this->refresh(); + } + + /** + * Returns status data + * + * @return array Status data + */ + public function getData() + { + return $this->_data; + } + + /** + * Returns status objects of all indices + * + * @return array|\Elastica\Index\Status[] List of Elastica\Client\Index objects + */ + public function getIndexStatuses() + { + $statuses = array(); + foreach ($this->getIndexNames() as $name) { + $index = new Index($this->_client, $name); + $statuses[] = new IndexStatus($index); + } + + return $statuses; + } + + /** + * Returns a list of the existing index names + * + * @return array Index names list + */ + public function getIndexNames() + { + $names = array(); + foreach ($this->_data['indices'] as $name => $data) { + $names[] = $name; + } + + return $names; + } + + /** + * Checks if the given index exists + * + * @param string $name Index name to check + * @return bool True if index exists + */ + public function indexExists($name) + { + return in_array($name, $this->getIndexNames()); + } + + /** + * Checks if the given alias exists + * + * @param string $name Alias name + * @return bool True if alias exists + */ + public function aliasExists($name) + { + return count($this->getIndicesWithAlias($name)) > 0; + } + + /** + * Returns an array with all indices that the given alias name points to + * + * @param string $alias Alias name + * @return array|\Elastica\Index[] List of Elastica\Index + */ + public function getIndicesWithAlias($alias) + { + $response = null; + try { + $response = $this->_client->request('/_alias/' . $alias); + } catch (ResponseException $e) { + $transferInfo = $e->getResponse()->getTransferInfo(); + // 404 means the index alias doesn't exist which means no indexes have it. + if ($transferInfo['http_code'] === 404) { + return array(); + } + // If we don't have a 404 then this is still unexpected so rethrow the exception. + throw $e; + } + $indices = array(); + foreach ($response->getData() as $name => $unused) { + $indices[] = new Index($this->_client, $name); + } + return $indices; + } + + /** + * Returns response object + * + * @return \Elastica\Response Response object + */ + public function getResponse() + { + return $this->_response; + } + + /** + * Return shards info + * + * @return array Shards info + */ + public function getShards() + { + return $this->_data['shards']; + } + + /** + * Refresh status object + */ + public function refresh() + { + $path = '_status'; + $this->_response = $this->_client->request($path, Request::GET); + $this->_data = $this->getResponse()->getData(); + } + + /** + * Refresh serverStatus object + */ + public function getServerStatus() + { + $path = ''; + $response = $this->_client->request($path, Request::GET); + + return $response->getData(); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Suggest.php b/vendor/ruflin/elastica/lib/Elastica/Suggest.php new file mode 100644 index 00000000..dd5dbbcc --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Suggest.php @@ -0,0 +1,62 @@ +<?php + +namespace Elastica; + + +use Elastica\Exception\NotImplementedException; +use Elastica\Suggest\AbstractSuggest; + +/** + * Class Suggest + * @package Elastica\Suggest + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters.html + */ +class Suggest extends Param +{ + /** + * @param AbstractSuggest $suggestion + */ + function __construct(AbstractSuggest $suggestion = NULL) + { + if (!is_null($suggestion)) { + $this->addSuggestion($suggestion); + } + } + + + /** + * Set the global text for this suggester + * @param string $text + * @return \Elastica\Suggest + */ + public function setGlobalText($text) + { + return $this->setParam("text", $text); + } + + /** + * Add a suggestion to this suggest clause + * @param AbstractSuggest $suggestion + * @return \Elastica\Suggest + */ + public function addSuggestion(AbstractSuggest $suggestion) + { + return $this->setParam($suggestion->getName(), $suggestion->toArray()); + } + + /** + * @param Suggest|AbstractSuggest $suggestion + * @return \Elastica\Suggest + * @throws Exception\NotImplementedException + */ + public static function create($suggestion) + { + switch(true){ + case $suggestion instanceof Suggest: + return $suggestion; + case $suggestion instanceof AbstractSuggest: + return new self($suggestion); + } + throw new NotImplementedException(); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Suggest/AbstractSuggest.php b/vendor/ruflin/elastica/lib/Elastica/Suggest/AbstractSuggest.php new file mode 100644 index 00000000..e5f5e01c --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Suggest/AbstractSuggest.php @@ -0,0 +1,92 @@ +<?php + +namespace Elastica\Suggest; + + +use Elastica\Param; + +/** + * Class AbstractSuggestion + * @package Elastica\Suggest + */ +abstract class AbstractSuggest extends Param +{ + /** + * @var string the name of this suggestion + */ + protected $_name; + + /** + * @var string the text for this suggestion + */ + protected $_text; + + /** + * @param string $name + * @param string $field + */ + public function __construct($name, $field) + { + $this->_name = $name; + $this->setField($field); + } + + /** + * Suggest text must be set either globally or per suggestion + * @param string $text + * @return \Elastica\Suggest\AbstractSuggest + */ + public function setText($text) + { + $this->_text = $text; + return $this; + } + + /** + * @param string $field + * @return \Elastica\Suggest\AbstractSuggest + */ + public function setField($field) + { + return $this->setParam("field", $field); + } + + /** + * @param int $size + * @return \Elastica\Suggest\AbstractSuggest + */ + public function setSize($size) + { + return $this->setParam("size", $size); + } + + /** + * @param int $size maximum number of suggestions to be retrieved from each shard + * @return \Elastica\Suggest\AbstractSuggest + */ + public function setShardSize($size) + { + return $this->setParam("shard_size", $size); + } + + /** + * Retrieve the name of this suggestion + * @return string + */ + public function getName() + { + return $this->_name; + } + + /** + * @return array + */ + public function toArray() + { + $array = parent::toArray(); + if (isset($this->_text)) { + $array['text'] = $this->_text; + } + return $array; + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Suggest/CandidateGenerator/AbstractCandidateGenerator.php b/vendor/ruflin/elastica/lib/Elastica/Suggest/CandidateGenerator/AbstractCandidateGenerator.php new file mode 100644 index 00000000..d9e6ac7c --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Suggest/CandidateGenerator/AbstractCandidateGenerator.php @@ -0,0 +1,11 @@ +<?php + +namespace Elastica\Suggest\CandidateGenerator; + + +use Elastica\Param; + +class AbstractCandidateGenerator extends Param +{ + +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Suggest/CandidateGenerator/DirectGenerator.php b/vendor/ruflin/elastica/lib/Elastica/Suggest/CandidateGenerator/DirectGenerator.php new file mode 100644 index 00000000..0277a5ac --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Suggest/CandidateGenerator/DirectGenerator.php @@ -0,0 +1,127 @@ +<?php + +namespace Elastica\Suggest\CandidateGenerator; + + +/** + * Class DirectGenerator + * @package Elastica\Suggest\Phrase + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters-phrase.html#_direct_generators + */ +class DirectGenerator extends AbstractCandidateGenerator +{ + const SUGGEST_MODE_MISSING = 'missing'; + const SUGGEST_MODE_POPULAR = 'popular'; + const SUGGEST_MODE_ALWAYS = 'always'; + + /** + * @param string $field + */ + public function __construct($field) + { + $this->setField($field); + } + + /** + * Set the field name from which to fetch candidate suggestions + * @param string $field + * @return DirectGenerator + */ + public function setField($field) + { + return $this->setParam("field", $field); + } + + /** + * Set the maximum corrections to be returned per suggest text token + * @param int $size + * @return DirectGenerator + */ + public function setSize($size) + { + return $this->setParam("size", $size); + } + + /** + * @param string $mode see SUGGEST_MODE_* constants for options + * @return DirectGenerator + */ + public function setSuggestMode($mode) + { + return $this->setParam("suggest_mode", $mode); + } + + /** + * @param int $max can only be a value between 1 and 2. Defaults to 2. + * @return DirectGenerator + */ + public function setMaxEdits($max) + { + return $this->setParam("max_edits", $max); + } + + /** + * @param int $length defaults to 1 + * @return DirectGenerator + */ + public function setPrefixLength($length) + { + return $this->setParam("prefix_len", $length); + } + + /** + * @param int $min defaults to 4 + * @return DirectGenerator + */ + public function setMinWordLength($min) + { + return $this->setParam("min_word_len", $min); + } + + /** + * @param int $max + * @return DirectGenerator + */ + public function setMaxInspections($max) + { + return $this->setParam("max_inspections", $max); + } + + /** + * @param float $min + * @return DirectGenerator + */ + public function setMinDocFrequency($min) + { + return $this->setParam("min_doc_freq", $min); + } + + /** + * @param float $max + * @return DirectGenerator + */ + public function setMaxTermFrequency($max) + { + return $this->setParam("max_term_freq", $max); + } + + /** + * Set an analyzer to be applied to the original token prior to candidate generation + * @param string $pre an analyzer + * @return DirectGenerator + */ + public function setPreFilter($pre) + { + return $this->setParam("pre_filter", $pre); + } + + /** + * Set an analyzer to be applied to generated tokens before they are passed to the phrase scorer + * @param string $post + * @return DirectGenerator + */ + public function setPostFilter($post) + { + return $this->setParam("post_filter", $post); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Suggest/Phrase.php b/vendor/ruflin/elastica/lib/Elastica/Suggest/Phrase.php new file mode 100644 index 00000000..14630dc1 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Suggest/Phrase.php @@ -0,0 +1,148 @@ +<?php + +namespace Elastica\Suggest; + +use Elastica\Suggest\CandidateGenerator\AbstractCandidateGenerator; + + +/** + * Class Phrase + * @package Elastica\Suggest + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters-phrase.html + */ +class Phrase extends AbstractSuggest +{ + /** + * @param string $analyzer + * @return \Elastica\Suggest\Phrase + */ + public function setAnalyzer($analyzer) + { + return $this->setParam("analyzer", $analyzer); + } + + /** + * Set the max size of the n-grams (shingles) in the field + * @param int $size + * @return \Elastica\Suggest\Phrase + */ + public function setGramSize($size) + { + return $this->setParam("gram_size", $size); + } + + /** + * Set the likelihood of a term being misspelled even if the term exists in the dictionary + * @param float $likelihood Defaults to 0.95, meaning 5% of the words are misspelled. + * @return \Elastica\Suggest\Phrase + */ + public function setRealWorldErrorLikelihood($likelihood) + { + return $this->setParam("real_world_error_likelihood", $likelihood); + } + + /** + * Set the factor applied to the input phrases score to be used as a threshold for other suggestion candidates. + * Only candidates which score higher than this threshold will be included in the result. + * @param float $confidence Defaults to 1.0. + * @return \Elastica\Suggest\Phrase + */ + public function setConfidence($confidence) + { + return $this->setParam("confidence", $confidence); + } + + /** + * Set the maximum percentage of the terms considered to be misspellings in order to form a correction + * @param float $max + * @return \Elastica\Suggest\Phrase + */ + public function setMaxErrors($max) + { + return $this->setParam("max_errors", $max); + } + + /** + * @param string $separator + * @return \Elastica\Param + */ + public function setSeparator($separator) + { + return $this->setParam("separator", $separator); + } + + /** + * Set suggestion highlighting + * @param string $preTag + * @param string $postTag + * @return \Elastica\Suggest\Phrase + */ + public function setHighlight($preTag, $postTag) + { + return $this->setParam("highlight", array( + 'pre_tag' => $preTag, + 'post_tag' => $postTag + )); + } + + /** + * @param float $discount + * @return \Elastica\Suggest\Phrase + */ + public function setStupidBackoffSmoothing($discount = 0.4) + { + return $this->setSmoothingModel("stupid_backoff", array( + "discount" => $discount + )); + } + + /** + * @param float $alpha + * @return \Elastica\Suggest\Phrase + */ + public function setLaplaceSmoothing($alpha = 0.5) + { + return $this->setSmoothingModel("laplace", array( + "alpha" => $alpha + )); + } + + /** + * @param float $trigramLambda + * @param float $bigramLambda + * @param float $unigramLambda + * @return \Elastica\Suggest\Phrase + */ + public function setLinearInterpolationSmoothing($trigramLambda, $bigramLambda, $unigramLambda) + { + return $this->setSmoothingModel("linear_interpolation", array( + "trigram_lambda" => $trigramLambda, + "bigram_lambda" => $bigramLambda, + "unigram_lambda" => $unigramLambda + )); + } + + /** + * @param string $model the name of the smoothing model + * @param array $params + * @return \Elastica\Suggest\Phrase + */ + public function setSmoothingModel($model, array $params) + { + return $this->setParam("smoothing", array( + $model => $params + )); + } + + /** + * @param AbstractCandidateGenerator $generator + * @return \Elastica\Suggest\Phrase + */ + public function addCandidateGenerator(AbstractCandidateGenerator $generator) + { + $generator = $generator->toArray(); + $keys = array_keys($generator); + $values = array_values($generator); + return $this->addParam($keys[0], $values[0]); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Suggest/Term.php b/vendor/ruflin/elastica/lib/Elastica/Suggest/Term.php new file mode 100644 index 00000000..3fca1731 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Suggest/Term.php @@ -0,0 +1,115 @@ +<?php + +namespace Elastica\Suggest; + + +/** + * Class Term + * @package Elastica\Suggest + * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters-term.html + */ +class Term extends AbstractSuggest +{ + const SORT_SCORE = 'score'; + const SORT_FREQUENCY = 'frequency'; + + const SUGGEST_MODE_MISSING = 'missing'; + const SUGGEST_MODE_POPULAR = 'popular'; + const SUGGEST_MODE_ALWAYS = 'always'; + + /** + * @param string $analyzer + * @return \Elastica\Suggest\Term + */ + public function setAnalyzer($analyzer) + { + return $this->setParam("analyzer", $analyzer); + } + + /** + * @param string $sort see SORT_* constants for options + * @return \Elastica\Suggest\Term + */ + public function setSort($sort) + { + return $this->setParam("sort", $sort); + } + + /** + * @param string $mode see SUGGEST_MODE_* constants for options + * @return \Elastica\Suggest\Term + */ + public function setSuggestMode($mode) + { + return $this->setParam("suggest_mode", $mode); + } + + /** + * If true, suggest terms will be lower cased after text analysis + * @param bool $lowercase + * @return \Elastica\Suggest\Term + */ + public function setLowercaseTerms($lowercase = true) + { + return $this->setParam("lowercase_terms", (bool)$lowercase); + } + + /** + * Set the maximum edit distance candidate suggestions can have in order to be considered as a suggestion + * @param int $max Either 1 or 2. Any other value will result in an error. + * @return \Elastica\Suggest\Term + */ + public function setMaxEdits($max) + { + return $this->setParam("max_edits", (int)$max); + } + + /** + * The number of minimum prefix characters that must match in order to be a suggestion candidate + * @param int $length Defaults to 1. + * @return \Elastica\Suggest\Term + */ + public function setPrefixLength($length) + { + return $this->setParam("prefix_len", (int)$length); + } + + /** + * The minimum length a suggest text term must have in order to be included. + * @param int $length Defaults to 4. + * @return \Elastica\Suggest\Term + */ + public function setMinWordLength($length) + { + return $this->setParam("min_word_len", (int)$length); + } + + /** + * @param int $max Defaults to 5. + * @return \Elastica\Suggest\Term + */ + public function setMaxInspections($max) + { + return $this->setParam("max_inspections", $max); + } + + /** + * Set the minimum number of documents in which a suggestion should appear + * @param int|float $min Defaults to 0. If the value is greater than 1, it must be a whole number. + * @return \Elastica\Suggest\Term + */ + public function setMinDocFrequency($min) + { + return $this->setParam("min_doc_freq", $min); + } + + /** + * Set the maximum number of documents in which a suggest text token can exist in order to be included + * @param float $max + * @return \Elastica\Suggest\Term + */ + public function setMaxTermFrequency($max) + { + return $this->setParam("max_term_freq", $max); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/lib/Elastica/Transport/AbstractTransport.php b/vendor/ruflin/elastica/lib/Elastica/Transport/AbstractTransport.php new file mode 100644 index 00000000..d2ce0fb2 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Transport/AbstractTransport.php @@ -0,0 +1,109 @@ +<?php + +namespace Elastica\Transport; + +use Elastica\Connection; +use Elastica\Request; +use Elastica\Exception\InvalidException; +use Elastica\Param; + +/** + * Elastica Abstract Transport object + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +abstract class AbstractTransport extends Param +{ + /** + * @var \Elastica\Connection + */ + protected $_connection; + + /** + * Construct transport + * + * @param \Elastica\Connection $connection Connection object + */ + public function __construct(Connection $connection = null) + { + if ($connection) { + $this->setConnection($connection); + } + } + + /** + * @return \Elastica\Connection Connection object + */ + public function getConnection() + { + return $this->_connection; + } + + /** + * @param \Elastica\Connection $connection Connection object + */ + public function setConnection(Connection $connection) + { + $this->_connection = $connection; + } + + /** + * Executes the transport request + * + * @param \Elastica\Request $request Request object + * @param array $params Hostname, port, path, ... + * @return \Elastica\Response Response object + */ + abstract public function exec(Request $request, array $params); + + /** + * Create a transport + * + * The $transport parameter can be one of the following values: + * + * * string: The short name of a transport. For instance "Http", "Memcache" or "Thrift" + * * object: An already instantiated instance of a transport + * * array: An array with a "type" key which must be set to one of the two options. All other + * keys in the array will be set as parameters in the transport instance + * + * @param mixed $transport A transport definition + * @param \Elastica\Connection $connection A connection instance + * @param array $params Parameters for the transport class + * @throws \Elastica\Exception\InvalidException + * @return AbstractTransport + */ + public static function create($transport, Connection $connection, array $params = array()) + { + if (is_array($transport) && isset($transport['type'])) { + $transportParams = $transport; + unset($transportParams['type']); + + $params = array_replace($params, $transportParams); + $transport = $transport['type']; + } + + if (is_string($transport)) { + $className = 'Elastica\\Transport\\' . $transport; + + if (!class_exists($className)) { + throw new InvalidException('Invalid transport'); + } + + $transport = new $className; + } + + if ($transport instanceof AbstractTransport) { + $transport->setConnection($connection); + + foreach ($params as $key => $value) { + $transport->setParam($key, $value); + } + } else { + throw new InvalidException('Invalid transport'); + } + + return $transport; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Transport/Guzzle.php b/vendor/ruflin/elastica/lib/Elastica/Transport/Guzzle.php new file mode 100644 index 00000000..96ad8971 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Transport/Guzzle.php @@ -0,0 +1,179 @@ +<?php + +namespace Elastica\Transport; + +use Elastica\Exception\Connection\HttpException; +use Elastica\Exception\Connection\GuzzleException; +use Elastica\Exception\PartialShardFailureException; +use Elastica\Exception\ResponseException; +use Elastica\Exception\InvalidException; +use Elastica\Connection; +use Elastica\Request; +use Elastica\Response; +use Elastica\JSON; +use GuzzleHttp\Client; +use GuzzleHttp\Exception\TransferException; +use GuzzleHttp\Exception\ClientException; +use GuzzleHttp\Stream\Stream; + +/** + * Elastica Guzzle Transport object + * + * @package Elastica + * @author Milan Magudia <milan@magudia.com> + */ +class Guzzle extends AbstractTransport +{ + /** + * Http scheme + * + * @var string Http scheme + */ + protected $_scheme = 'http'; + + /** + * Curl resource to reuse + * + * @var resource Guzzle resource to reuse + */ + protected static $_guzzleClientConnection = null; + + /** + * Makes calls to the elasticsearch server + * + * All calls that are made to the server are done through this function + * + * @param \Elastica\Request $request + * @param array $params Host, Port, ... + * @throws \Elastica\Exception\ConnectionException + * @throws \Elastica\Exception\ResponseException + * @throws \Elastica\Exception\Connection\HttpException + * @return \Elastica\Response Response object + */ + public function exec(Request $request, array $params) + { + $connection = $this->getConnection(); + + try { + $client = $this->_getGuzzleClient($this->_getBaseUrl($connection), $connection->isPersistent()); + + $options = array(); + if ($connection->getTimeout()) { + $options['timeout'] = $connection->getTimeout(); + } + + if ($connection->getProxy()) { + $options['proxy'] = $connection->getProxy(); + } + + $req = $client->createRequest($request->getMethod(), $this->_getActionPath($request), $options); + $req->setHeaders($connection->hasConfig('headers') ?: array()); + + $data = $request->getData(); + if (!empty($data) || '0' === $data) { + + if ($req->getMethod() == Request::GET) { + $req->setMethod(Request::POST); + } + + if ($this->hasParam('postWithRequestBody') && $this->getParam('postWithRequestBody') == true) { + $request->setMethod(Request::POST); + $req->setMethod(Request::POST); + } + + if (is_array($data)) { + $content = JSON::stringify($data, 'JSON_ELASTICSEARCH'); + } else { + $content = $data; + } + $req->setBody(Stream::factory($content)); + } + + $start = microtime(true); + $res = $client->send($req); + $end = microtime(true); + + $response = new Response((string)$res->getBody(), $res->getStatusCode()); + + if (defined('DEBUG') && DEBUG) { + $response->setQueryTime($end - $start); + } + + $response->setTransferInfo( + array( + 'request_header' => $request->getMethod(), + 'http_code' => $res->getStatusCode() + ) + ); + + if ($response->hasError()) { + throw new ResponseException($request, $response); + } + + if ($response->hasFailedShards()) { + throw new PartialShardFailureException($request, $response); + } + + return $response; + + } catch (ClientException $e) { + // ignore 4xx errors + } catch (TransferException $e) { + throw new GuzzleException($e, $request, new Response($e->getMessage())); + } + + } + + /** + * Return Guzzle resource + * + * @param bool $persistent False if not persistent connection + * @return resource Connection resource + */ + protected function _getGuzzleClient($baseUrl, $persistent = true) + { + if (!$persistent || !self::$_guzzleClientConnection) { + self::$_guzzleClientConnection = new Client(array('base_url' => $baseUrl)); + } + + return self::$_guzzleClientConnection; + } + + /** + * Builds the base url for the guzzle connection + * + * @param \Elastica\Connection $connection + */ + protected function _getBaseUrl(Connection $connection) + { + // If url is set, url is taken. Otherwise port, host and path + $url = $connection->hasConfig('url') ? $connection->getConfig('url') : ''; + + if (!empty($url)) { + $baseUri = $url; + } else { + $baseUri = $this->_scheme . '://' . $connection->getHost() . ':' . $connection->getPort() . '/' . $connection->getPath(); + } + return rtrim($baseUri, '/'); + } + + /** + * Builds the action path url for each request + * + * @param \Elastica\Request $request + */ + protected function _getActionPath(Request $request) + { + $action = $request->getPath(); + if ($action) { + $action = '/'. ltrim($action, '/'); + } + $query = $request->getQuery(); + + if (!empty($query)) { + $action .= '?' . http_build_query($query); + } + + return $action; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Transport/Http.php b/vendor/ruflin/elastica/lib/Elastica/Transport/Http.php new file mode 100644 index 00000000..5606dbbc --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Transport/Http.php @@ -0,0 +1,188 @@ +<?php + +namespace Elastica\Transport; + +use Elastica\Exception\Connection\HttpException; +use Elastica\Exception\PartialShardFailureException; +use Elastica\Exception\ResponseException; +use Elastica\JSON; +use Elastica\Request; +use Elastica\Response; + +/** + * Elastica Http Transport object + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class Http extends AbstractTransport +{ + /** + * Http scheme + * + * @var string Http scheme + */ + protected $_scheme = 'http'; + + /** + * Curl resource to reuse + * + * @var resource Curl resource to reuse + */ + protected static $_curlConnection = null; + + /** + * Makes calls to the elasticsearch server + * + * All calls that are made to the server are done through this function + * + * @param \Elastica\Request $request + * @param array $params Host, Port, ... + * @throws \Elastica\Exception\ConnectionException + * @throws \Elastica\Exception\ResponseException + * @throws \Elastica\Exception\Connection\HttpException + * @return \Elastica\Response Response object + */ + public function exec(Request $request, array $params) + { + $connection = $this->getConnection(); + + $conn = $this->_getConnection($connection->isPersistent()); + + // If url is set, url is taken. Otherwise port, host and path + $url = $connection->hasConfig('url') ? $connection->getConfig('url') : ''; + + if (!empty($url)) { + $baseUri = $url; + } else { + $baseUri = $this->_scheme . '://' . $connection->getHost() . ':' . $connection->getPort() . '/' . $connection->getPath(); + } + + $baseUri .= $request->getPath(); + + $query = $request->getQuery(); + + if (!empty($query)) { + $baseUri .= '?' . http_build_query($query); + } + + curl_setopt($conn, CURLOPT_URL, $baseUri); + curl_setopt($conn, CURLOPT_TIMEOUT, $connection->getTimeout()); + curl_setopt($conn, CURLOPT_FORBID_REUSE, 0); + + $proxy = $connection->getProxy(); + if (!is_null($proxy)) { + curl_setopt($conn, CURLOPT_PROXY, $proxy); + } + + $this->_setupCurl($conn); + + $headersConfig = $connection->hasConfig('headers') ? $connection->getConfig('headers') : array(); + + if (!empty($headersConfig)) { + $headers = array(); + while (list($header, $headerValue) = each($headersConfig)) { + array_push($headers, $header . ': ' . $headerValue); + } + + curl_setopt($conn, CURLOPT_HTTPHEADER, $headers); + } + + // TODO: REFACTOR + $data = $request->getData(); + $httpMethod = $request->getMethod(); + + if (!empty($data) || '0' === $data) { + if ($this->hasParam('postWithRequestBody') && $this->getParam('postWithRequestBody') == true) { + $httpMethod = Request::POST; + } + + if (is_array($data)) { + $content = JSON::stringify($data, 'JSON_ELASTICSEARCH'); + } else { + $content = $data; + } + + // Escaping of / not necessary. Causes problems in base64 encoding of files + $content = str_replace('\/', '/', $content); + + curl_setopt($conn, CURLOPT_POSTFIELDS, $content); + } else { + curl_setopt($conn, CURLOPT_POSTFIELDS, ''); + } + + curl_setopt($conn, CURLOPT_NOBODY, $httpMethod == 'HEAD'); + + curl_setopt($conn, CURLOPT_CUSTOMREQUEST, $httpMethod); + + if (defined('DEBUG') && DEBUG) { + // Track request headers when in debug mode + curl_setopt($conn, CURLINFO_HEADER_OUT, true); + } + + $start = microtime(true); + + // cURL opt returntransfer leaks memory, therefore OB instead. + ob_start(); + curl_exec($conn); + $responseString = ob_get_clean(); + + $end = microtime(true); + + // Checks if error exists + $errorNumber = curl_errno($conn); + + $response = new Response($responseString, curl_getinfo($this->_getConnection(), CURLINFO_HTTP_CODE)); + + if (defined('DEBUG') && DEBUG) { + $response->setQueryTime($end - $start); + } + + $response->setTransferInfo(curl_getinfo($conn)); + + + if ($response->hasError()) { + throw new ResponseException($request, $response); + } + + if ($response->hasFailedShards()) { + throw new PartialShardFailureException($request, $response); + } + + if ($errorNumber > 0) { + throw new HttpException($errorNumber, $request, $response); + } + + return $response; + } + + /** + * Called to add additional curl params + * + * @param resource $curlConnection Curl connection + */ + protected function _setupCurl($curlConnection) + { + if ($this->getConnection()->hasConfig('curl')) { + foreach ($this->getConnection()->getConfig('curl') as $key => $param) { + curl_setopt($curlConnection, $key, $param); + } + } + } + + /** + * Return Curl resource + * + * @param bool $persistent False if not persistent connection + * @return resource Connection resource + */ + protected function _getConnection($persistent = true) + { + if (!$persistent || !self::$_curlConnection) { + self::$_curlConnection = curl_init(); + } + + return self::$_curlConnection; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Transport/Https.php b/vendor/ruflin/elastica/lib/Elastica/Transport/Https.php new file mode 100644 index 00000000..64704039 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Transport/Https.php @@ -0,0 +1,30 @@ +<?php + +namespace Elastica\Transport; + +/** + * Elastica Http Transport object + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class Https extends Http +{ + /** + * Https scheme + * + * @var string https scheme + */ + protected $_scheme = 'https'; + + /** + * Overloads setupCurl to set SSL params + * + * @param resource $connection Curl connection resource + */ + protected function _setupCurl($connection) + { + parent::_setupCurl($connection); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Transport/Memcache.php b/vendor/ruflin/elastica/lib/Elastica/Transport/Memcache.php new file mode 100644 index 00000000..cf047b58 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Transport/Memcache.php @@ -0,0 +1,82 @@ +<?php + +namespace Elastica\Transport; + +use Elastica\Exception\InvalidException; +use Elastica\Exception\PartialShardFailureException; +use Elastica\Exception\ResponseException; +use Elastica\JSON; +use Elastica\Request; +use Elastica\Response; + +/** + * Elastica Memcache Transport object + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class Memcache extends AbstractTransport +{ + /** + * Makes calls to the elasticsearch server + * + * @param \Elastica\Request $request + * @param array $params Host, Port, ... + * @throws \Elastica\Exception\ResponseException + * @throws \Elastica\Exception\InvalidException + * @return \Elastica\Response Response object + */ + public function exec(Request $request, array $params) + { + $memcache = new \Memcache(); + $memcache->connect($this->getConnection()->getHost(), $this->getConnection()->getPort()); + + // Finds right function name + $function = strtolower($request->getMethod()); + + $data = $request->getData(); + + $content = ''; + + if (!empty($data) || '0' === $data) { + if (is_array($data)) { + $content = JSON::stringify($data); + } else { + $content = $data; + } + + // Escaping of / not necessary. Causes problems in base64 encoding of files + $content = str_replace('\/', '/', $content); + } + + $responseString = ''; + + switch ($function) { + case 'post': + case 'put': + $memcache->set($request->getPath(), $content); + break; + case 'get': + $responseString = $memcache->get($request->getPath() . '?source=' . $content); + break; + case 'delete': + break; + default: + throw new InvalidException('Method ' . $function . ' is not supported in memcache transport'); + + } + + $response = new Response($responseString); + + if ($response->hasError()) { + throw new ResponseException($request, $response); + } + + if ($response->hasFailedShards()) { + throw new PartialShardFailureException($request, $response); + } + + return $response; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Transport/Null.php b/vendor/ruflin/elastica/lib/Elastica/Transport/Null.php new file mode 100644 index 00000000..704e0e12 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Transport/Null.php @@ -0,0 +1,44 @@ +<?php + +namespace Elastica\Transport; + +use Elastica\JSON; +use Elastica\Request; +use Elastica\Response; + +/** + * Elastica Null Transport object + * + * @package Elastica + * @author James Boehmer <james.boehmer@jamesboehmer.com> + */ +class Null extends AbstractTransport +{ + /** + * Null transport. + * + * @param \Elastica\Request $request + * @param array $params Hostname, port, path, ... + * @return \Elastica\Response Response empty object + */ + public function exec(Request $request, array $params) + { + $response = array( + "took" => 0, + "timed_out" => FALSE, + "_shards" => array( + "total" => 0, + "successful" => 0, + "failed" => 0 + ), + "hits" => array( + "total" => 0, + "max_score" => NULL, + "hits" => array() + ), + "params" => $params + ); + + return new Response(JSON::stringify($response)); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Transport/Thrift.php b/vendor/ruflin/elastica/lib/Elastica/Transport/Thrift.php new file mode 100644 index 00000000..f58c51a2 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Transport/Thrift.php @@ -0,0 +1,173 @@ +<?php + +namespace Elastica\Transport; + +use Elastica\Exception\Connection\ThriftException; +use Elastica\Exception\PartialShardFailureException; +use Elastica\Exception\ResponseException; +use Elastica\Exception\RuntimeException; +use Elastica\JSON; +use Elastica\Request; +use Elastica\Response; +use Elastica\Connection; +use Elasticsearch\Method; +use Elasticsearch\RestResponse; +use Elasticsearch\RestClient; +use Elasticsearch\RestRequest; +use Thrift\Transport\TSocket; +use Thrift\Transport\TFramedTransport; +use Thrift\Transport\TBufferedTransport; +use Thrift\Protocol\TBinaryProtocolAccelerated; +use Thrift\Exception\TException; + +/** + * Elastica Thrift Transport object + * + * @category Xodoa + * @package Elastica + * @author Mikhail Shamin <munk13@gmail.com> + */ +class Thrift extends AbstractTransport +{ + /** + * @var RestClient[] + */ + protected $_clients = array(); + + /** + * Construct transport + * + * @param \Elastica\Connection $connection Connection object + * @throws \Elastica\Exception\RuntimeException + */ + public function __construct(Connection $connection = null) + { + parent::__construct($connection); + if (!class_exists('Elasticsearch\\RestClient')) { + throw new RuntimeException('Elasticsearch\\RestClient class not found. Check that suggested package munkie/elasticsearch-thrift-php is required in composer.json'); + } + } + + /** + * @param string $host + * @param int $port + * @param int $sendTimeout msec + * @param int $recvTimeout msec + * @param bool $framedTransport + * @return \Elasticsearch\RestClient + */ + protected function _createClient($host, $port, $sendTimeout = null, $recvTimeout = null, $framedTransport = false) + { + $socket = new TSocket($host, $port, true); + + if (null !== $sendTimeout) { + $socket->setSendTimeout($sendTimeout); + } + + if (null !== $recvTimeout) { + $socket->setRecvTimeout($recvTimeout); + } + + if ($framedTransport) { + $transport = new TFramedTransport($socket); + } else { + $transport = new TBufferedTransport($socket); + } + $protocol = new TBinaryProtocolAccelerated($transport); + + $client = new RestClient($protocol); + + $transport->open(); + + return $client; + } + + /** + * @param string $host + * @param int $port + * @param int $sendTimeout + * @param int $recvTimeout + * @param bool $framedTransport + * @return \Elasticsearch\RestClient + */ + protected function _getClient($host, $port, $sendTimeout = null, $recvTimeout = null, $framedTransport = false) + { + $key = $host . ':' . $port; + if (!isset($this->_clients[$key])) { + $this->_clients[$key] = $this->_createClient($host, $port, $sendTimeout, $recvTimeout, $framedTransport); + } + return $this->_clients[$key]; + } + + /** + * Makes calls to the elasticsearch server + * + * @param \Elastica\Request $request + * @param array $params Host, Port, ... + * @throws \Elastica\Exception\Connection\ThriftException + * @throws \Elastica\Exception\ResponseException + * @return \Elastica\Response Response object + */ + public function exec(Request $request, array $params) + { + $connection = $this->getConnection(); + + $sendTimeout = $connection->hasConfig('sendTimeout') ? $connection->getConfig('sendTimeout') : null; + $recvTimeout = $connection->hasConfig('recvTimeout') ? $connection->getConfig('recvTimeout') : null; + $framedTransport = $connection->hasConfig('framedTransport') ? (bool) $connection->getConfig('framedTransport') : false; + + try { + $client = $this->_getClient( + $connection->getHost(), + $connection->getPort(), + $sendTimeout, + $recvTimeout, + $framedTransport + ); + + $restRequest = new RestRequest(); + $restRequest->method = array_search($request->getMethod(), Method::$__names); + $restRequest->uri = $request->getPath(); + + $query = $request->getQuery(); + if (!empty($query)) { + $restRequest->parameters = $query; + } + + $data = $request->getData(); + if (!empty($data) || '0' === $data) { + if (is_array($data)) { + $content = JSON::stringify($data); + } else { + $content = $data; + } + $restRequest->body = $content; + } + + /* @var $result RestResponse */ + $start = microtime(true); + + $result = $client->execute($restRequest); + $response = new Response($result->body); + + $end = microtime(true); + } catch (TException $e) { + $response = new Response(''); + throw new ThriftException($e, $request, $response); + } + + if (defined('DEBUG') && DEBUG) { + $response->setQueryTime($end - $start); + } + + if ($response->hasError()) { + throw new ResponseException($request, $response); + } + + if ($response->hasFailedShards()) { + throw new PartialShardFailureException($request, $response); + } + + return $response; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Type.php b/vendor/ruflin/elastica/lib/Elastica/Type.php new file mode 100644 index 00000000..1ed952db --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Type.php @@ -0,0 +1,537 @@ +<?php + +namespace Elastica; + +use Elastica\Document; +use Elastica\Exception\RuntimeException; +use Elastica\Exception\InvalidException; +use Elastica\Exception\NotFoundException; +use Elastica\Exception\ResponseException; +use Elastica\Type\Mapping; + +/** + * Elastica type object + * + * elasticsearch has for every types as a substructure. This object + * represents a type inside a context + * The hierarchy is as following: client -> index -> type -> document + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +class Type implements SearchableInterface +{ + /** + * Index + * + * @var \Elastica\Index Index object + */ + protected $_index = null; + + /** + * Type name + * + * @var string Type name + */ + protected $_name = ''; + + /** + * @var array|string A callable that serializes an object passed to it + */ + protected $_serializer; + + /** + * Creates a new type object inside the given index + * + * @param \Elastica\Index $index Index Object + * @param string $name Type name + */ + public function __construct(Index $index, $name) + { + $this->_index = $index; + $this->_name = $name; + } + + /** + * Adds the given document to the search index + * + * @param \Elastica\Document $doc Document with data + * @return \Elastica\Response + */ + public function addDocument(Document $doc) + { + $path = urlencode($doc->getId()); + + $type = Request::PUT; + + // If id is empty, POST has to be used to automatically create id + if (empty($path)) { + $type = Request::POST; + } + + $options = $doc->getOptions( + array( + 'version', + 'version_type', + 'routing', + 'percolate', + 'parent', + 'ttl', + 'timestamp', + 'op_type', + 'consistency', + 'replication', + 'refresh', + 'timeout', + ) + ); + + $response = $this->request($path, $type, $doc->getData(), $options); + + $data = $response->getData(); + // set autogenerated id to document + if (($doc->isAutoPopulate() + || $this->getIndex()->getClient()->getConfigValue(array('document', 'autoPopulate'), false)) + && $response->isOk() + ) { + if (!$doc->hasId()) { + if (isset($data['_id'])) { + $doc->setId($data['_id']); + } + } + if (isset($data['_version'])) { + $doc->setVersion($data['_version']); + } + } + + return $response; + } + + /** + * @param $object + * @param Document $doc + * @return Response + * @throws Exception\RuntimeException + */ + public function addObject($object, Document $doc = null) + { + if (!isset($this->_serializer)) { + throw new RuntimeException('No serializer defined'); + } + + $data = call_user_func($this->_serializer, $object); + if (!$doc) { + $doc = new Document(); + } + $doc->setData($data); + + return $this->addDocument($doc); + } + + /** + * Update document, using update script. Requires elasticsearch >= 0.19.0 + * + * @param \Elastica\Document|\Elastica\Script $data Document with update data + * @throws \Elastica\Exception\InvalidException + * @return \Elastica\Response + * @link http://www.elasticsearch.org/guide/reference/api/update.html + */ + public function updateDocument($data) + { + if (!($data instanceof Document) && !($data instanceof Script)) { + throw new \InvalidArgumentException("Data should be a Document or Script"); + } + + if (!$data->hasId()) { + throw new InvalidException('Document or Script id is not set'); + } + + return $this->getIndex()->getClient()->updateDocument( + $data->getId(), + $data, + $this->getIndex()->getName(), + $this->getName() + ); + } + + /** + * Uses _bulk to send documents to the server + * + * @param array|\Elastica\Document[] $docs Array of Elastica\Document + * @return \Elastica\Bulk\ResponseSet + * @link http://www.elasticsearch.org/guide/reference/api/bulk.html + */ + public function updateDocuments(array $docs) + { + foreach ($docs as $doc) { + $doc->setType($this->getName()); + } + + return $this->getIndex()->updateDocuments($docs); + } + + /** + * Uses _bulk to send documents to the server + * + * @param array|\Elastica\Document[] $docs Array of Elastica\Document + * @return \Elastica\Bulk\ResponseSet + * @link http://www.elasticsearch.org/guide/reference/api/bulk.html + */ + public function addDocuments(array $docs) + { + foreach ($docs as $doc) { + $doc->setType($this->getName()); + } + + return $this->getIndex()->addDocuments($docs); + } + + /** + * Uses _bulk to send documents to the server + * + * @param objects[] $objects + * @return \Elastica\Bulk\ResponseSet + * @link http://www.elasticsearch.org/guide/reference/api/bulk.html + */ + public function addObjects(array $objects) + { + if (!isset($this->_serializer)) { + throw new RuntimeException('No serializer defined'); + } + + $docs = array(); + foreach ($objects as $object) { + $data = call_user_func($this->_serializer, $object); + $doc = new Document(); + $doc->setData($data); + $doc->setType($this->getName()); + $docs[] = $doc; + } + + return $this->getIndex()->addDocuments($docs); + } + + /** + * Get the document from search index + * + * @param string $id Document id + * @param array $options Options for the get request. + * @throws \Elastica\Exception\NotFoundException + * @return \Elastica\Document + */ + public function getDocument($id, $options = array()) + { + $path = urlencode($id); + + try { + $response = $this->request($path, Request::GET, array(), $options); + $result = $response->getData(); + } catch (ResponseException $e) { + throw new NotFoundException('doc id ' . $id . ' not found'); + } + + $info = $response->getTransferInfo(); + if ($info['http_code'] !== 200) { + throw new NotFoundException('doc id ' . $id . ' not found'); + } + + if (isset($result['fields'])) { + $data = $result['fields']; + } elseif (isset($result['_source'])) { + $data = $result['_source']; + } else { + $data = array(); + } + + $document = new Document($id, $data, $this->getName(), $this->getIndex()); + $document->setVersion($result['_version']); + + return $document; + } + + /** + * @param string $id + * @param array|string $data + * @return Document + */ + public function createDocument($id = '', $data = array()) + { + $document = new Document($id, $data); + $document->setType($this); + + return $document; + } + + /** + * Returns the type name + * + * @return string Type name + */ + public function getName() + { + return $this->_name; + } + + /** + * Sets value type mapping for this type + * + * @param \Elastica\Type\Mapping|array $mapping Elastica\Type\MappingType object or property array with all mappings + * @return \Elastica\Response + */ + public function setMapping($mapping) + { + $mapping = Mapping::create($mapping); + $mapping->setType($this); + + return $mapping->send(); + } + + /** + * Returns current mapping for the given type + * + * @return array Current mapping + */ + public function getMapping() + { + $path = '_mapping'; + + $response = $this->request($path, Request::GET); + $data = $response->getData(); + + $mapping = array_shift($data); + if (isset($mapping['mappings'])) { + return $mapping['mappings']; + } + + return array(); + } + + /** + * Create search object + * + * @param string|array|\Elastica\Query $query Array with all query data inside or a Elastica\Query object + * @param int|array $options OPTIONAL Limit or associative array of options (option=>value) + * @return \Elastica\Search + */ + public function createSearch($query = '', $options = null) + { + $search = new Search($this->getIndex()->getClient()); + $search->addIndex($this->getIndex()); + $search->addType($this); + $search->setOptionsAndQuery($options, $query); + + return $search; + } + + /** + * Do a search on this type + * + * @param string|array|\Elastica\Query $query Array with all query data inside or a Elastica\Query object + * @param int|array $options OPTIONAL Limit or associative array of options (option=>value) + * @return \Elastica\ResultSet ResultSet with all results inside + * @see \Elastica\SearchableInterface::search + */ + public function search($query = '', $options = null) + { + $search = $this->createSearch($query, $options); + + return $search->search(); + } + + /** + * Count docs by query + * + * @param string|array|\Elastica\Query $query Array with all query data inside or a Elastica\Query object + * @return int number of documents matching the query + * @see \Elastica\SearchableInterface::count + */ + public function count($query = '') + { + $search = $this->createSearch($query); + + return $search->count(); + } + + /** + * Returns index client + * + * @return \Elastica\Index Index object + */ + public function getIndex() + { + return $this->_index; + } + + /** + * @param \Elastica\Document $document + * @return \Elastica\Response + */ + public function deleteDocument(Document $document) + { + $options = $document->getOptions( + array( + 'version', + 'version_type', + 'routing', + 'parent', + 'replication', + 'consistency', + 'refresh', + 'timeout' + ) + ); + return $this->deleteById($document->getId(), $options); + } + + /** + * Uses _bulk to delete documents from the server + * + * @param array|\Elastica\Document[] $docs Array of Elastica\Document + * @return \Elastica\Bulk\ResponseSet + * @link http://www.elasticsearch.org/guide/reference/api/bulk.html + */ + public function deleteDocuments(array $docs) + { + foreach ($docs as $doc) { + $doc->setType($this->getName()); + } + + return $this->getIndex()->deleteDocuments($docs); + } + + /** + * Deletes an entry by its unique identifier + * + * @param int|string $id Document id + * @param array $options + * @throws \InvalidArgumentException + * @throws \Elastica\Exception\NotFoundException + * @return \Elastica\Response Response object + * @link http://www.elasticsearch.org/guide/reference/api/delete.html + */ + public function deleteById($id, array $options = array()) + { + if (empty($id) || !trim($id)) { + throw new \InvalidArgumentException(); + } + + $id = urlencode($id); + + $response = $this->request($id, Request::DELETE, array(), $options); + + $responseData = $response->getData(); + + if (isset($responseData['found']) && false == $responseData['found']) { + throw new NotFoundException('Doc id ' . $id . ' not found and can not be deleted'); + } + + return $response; + } + + /** + * Deletes the given list of ids from this type + * + * @param array $ids + * @param string|false $routing Optional routing key for all ids + * @return \Elastica\Response Response object + */ + public function deleteIds(array $ids, $routing = false) + { + return $this->getIndex()->getClient()->deleteIds($ids, $this->getIndex(), $this, $routing); + } + + /** + * Deletes entries in the db based on a query + * + * @param \Elastica\Query|string $query Query object + * @param array $options Optional params + * @return \Elastica\Response + * @link http://www.elasticsearch.org/guide/reference/api/delete-by-query.html + */ + public function deleteByQuery($query, array $options = array()) + { + if (is_string($query)) { + // query_string queries are not supported for delete by query operations + $options['q'] = $query; + return $this->request('_query', Request::DELETE, array(), $options); + } + $query = Query::create($query); + + return $this->request('_query', Request::DELETE, array('query' => $query->getQuery()), $options); + } + + /** + * Deletes the index type. + * + * @return \Elastica\Response + */ + public function delete() + { + $response = $this->request('', Request::DELETE); + + return $response; + } + + /** + * More like this query based on the given object + * + * The id in the given object has to be set + * + * @param \Elastica\Document $doc Document to query for similar objects + * @param array $params OPTIONAL Additional arguments for the query + * @param string|array|\Elastica\Query $query OPTIONAL Query to filter the moreLikeThis results + * @return \Elastica\ResultSet ResultSet with all results inside + * @link http://www.elasticsearch.org/guide/reference/api/more-like-this.html + */ + public function moreLikeThis(Document $doc, $params = array(), $query = array()) + { + $path = $doc->getId() . '/_mlt'; + + $query = Query::create($query); + + $response = $this->request($path, Request::GET, $query->toArray(), $params); + + return new ResultSet($response, $query); + } + + /** + * Makes calls to the elasticsearch server based on this type + * + * @param string $path Path to call + * @param string $method Rest method to use (GET, POST, DELETE, PUT) + * @param array $data OPTIONAL Arguments as array + * @param array $query OPTIONAL Query params + * @return \Elastica\Response Response object + */ + public function request($path, $method, $data = array(), array $query = array()) + { + $path = $this->getName() . '/' . $path; + + return $this->getIndex()->request($path, $method, $data, $query); + } + + /** + * Sets the serializer callable used in addObject + * @see \Elastica\Type::addObject + * + * @param array|string $serializer @see \Elastica\Type::_serializer + */ + public function setSerializer($serializer) + { + $this->_serializer = $serializer; + } + + /** + * Checks if the given type exists in Index + * + * @return bool True if type exists + */ + public function exists() + { + $response = $this->getIndex()->request($this->getName(), Request::HEAD); + $info = $response->getTransferInfo(); + + return (bool)($info['http_code'] == 200); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Type/AbstractType.php b/vendor/ruflin/elastica/lib/Elastica/Type/AbstractType.php new file mode 100644 index 00000000..ba2e0430 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Type/AbstractType.php @@ -0,0 +1,200 @@ +<?php + +namespace Elastica\Type; + +use Elastica\Client; +use Elastica\Exception\InvalidException; +use Elastica\Index; +use Elastica\SearchableInterface; +use Elastica\Type as BaseType; +use Elastica\Util; + +/** + * Abstract helper class to implement search indices based on models. + * + * This abstract model should help creating search index and a subtype + * with some easy config entries that are overloaded. + * + * The following variables have to be set: + * - $_indexName + * - $_typeName + * + * The following variables can be set for additional configuration + * - $_mapping: Value type mapping for the given type + * - $_indexParams: Parameters for the index + * + * @todo Add some settings examples to code + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + */ +abstract class AbstractType implements SearchableInterface +{ + const MAX_DOCS_PER_REQUEST = 1000; + + /** + * Index name + * + * @var string Index name + */ + protected $_indexName = ''; + + /** + * Index name + * + * @var string Index name + */ + protected $_typeName = ''; + + /** + * Client + * + * @var \Elastica\Client Client object + */ + protected $_client = null; + + /** + * Index + * + * @var \Elastica\Index Index object + */ + protected $_index = null; + + /** + * Type + * + * @var \Elastica\Type Type object + */ + protected $_type = null; + + /** + * Mapping + * + * @var array Mapping + */ + protected $_mapping = array(); + + /** + * Index params + * + * @var array Index params + */ + protected $_indexParams = array(); + + /** + * Source + * + * @var boolean Source + */ + protected $_source = true; + + /** + * Creates index object with client connection + * + * Reads index and type name from protected vars _indexName and _typeName. + * Has to be set in child class + * + * @param \Elastica\Client $client OPTIONAL Client object + * @throws \Elastica\Exception\InvalidException + */ + public function __construct(Client $client = null) + { + if (!$client) { + $client = new Client(); + } + + if (empty($this->_indexName)) { + throw new InvalidException('Index name has to be set'); + } + + if (empty($this->_typeName)) { + throw new InvalidException('Type name has to be set'); + } + + $this->_client = $client; + $this->_index = new Index($this->_client, $this->_indexName); + $this->_type = new BaseType($this->_index, $this->_typeName); + } + + /** + * Creates the index and sets the mapping for this type + * + * @param bool $recreate OPTIONAL Recreates the index if true (default = false) + */ + public function create($recreate = false) + { + $this->getIndex()->create($this->_indexParams, $recreate); + + $mapping = new Mapping($this->getType()); + $mapping->setProperties($this->_mapping); + $mapping->setSource(array('enabled' => $this->_source)); + $mapping->send(); + } + + /** + * @param \Elastica\Query $query + * @param array|int $options + * @return \Elastica\Search + */ + public function createSearch($query = '', $options = null) + { + return $this->getType()->createSearch($query, $options); + } + + /** + * Search on the type + * + * @param string|array|\Elastica\Query $query Array with all query data inside or a Elastica\Query object + * @return \Elastica\ResultSet ResultSet with all results inside + * @see \Elastica\SearchableInterface::search + */ + public function search($query = '', $options = null) + { + return $this->getType()->search($query, $options = null); + } + + /** + * Count docs in the type based on query + * + * @param string|array|\Elastica\Query $query Array with all query data inside or a Elastica\Query object + * @return int number of documents matching the query + * @see \Elastica\SearchableInterface::count + */ + public function count($query = '') + { + return $this->getType()->count($query); + } + + /** + * Returns the search index + * + * @return \Elastica\Index Index object + */ + public function getIndex() + { + return $this->_index; + } + + /** + * Returns type object + * + * @return \Elastica\Type Type object + */ + public function getType() + { + return $this->_type; + } + + /** + * Converts given time to format: 1995-12-31T23:59:59Z + * + * This is the lucene date format + * + * @param int $date Date input (could be string etc.) -> must be supported by strtotime + * @return string Converted date string + */ + public function convertDate($date) + { + return Util::convertDate($date); + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Type/Mapping.php b/vendor/ruflin/elastica/lib/Elastica/Type/Mapping.php new file mode 100644 index 00000000..920093fb --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Type/Mapping.php @@ -0,0 +1,280 @@ +<?php + +namespace Elastica\Type; + +use Elastica\Exception\InvalidException; +use Elastica\Request; +use Elastica\Type; + +/** + * Elastica Mapping object + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @link http://www.elasticsearch.org/guide/reference/mapping/ + */ +class Mapping +{ + /** + * Mapping + * + * @var array Mapping + */ + protected $_mapping = array(); + + /** + * Type + * + * @var \Elastica\Type Type object + */ + protected $_type = null; + + /** + * Construct Mapping + * + * @param \Elastica\Type $type OPTIONAL Type object + * @param array $properties OPTIONAL Properties + */ + public function __construct(Type $type = null, array $properties = array()) + { + if ($type) { + $this->setType($type); + } + + if (!empty($properties)) { + $this->setProperties($properties); + } + } + + /** + * Sets the mapping type + * Enter description here ... + * @param \Elastica\Type $type Type object + * @return \Elastica\Type\Mapping Current object + */ + public function setType(Type $type) + { + $this->_type = $type; + + return $this; + } + + /** + * Sets the mapping properties + * + * @param array $properties Properties + * @return \Elastica\Type\Mapping Mapping object + */ + public function setProperties(array $properties) + { + return $this->setParam('properties', $properties); + } + + /** + * Gets the mapping properties + * + * @return array $properties Properties + */ + public function getProperties() + { + return $this->getParam('properties'); + } + + /** + * Sets the mapping _meta + * @param array $meta metadata + * @return \Elastica\Type\Mapping Mapping object + * @link http://www.elasticsearch.org/guide/reference/mapping/meta.html + */ + public function setMeta(array $meta) + { + return $this->setParam('_meta', $meta); + } + + /** + * Returns mapping type + * + * @return \Elastica\Type Type + */ + public function getType() + { + return $this->_type; + } + + /** + * Sets source values + * + * To disable source, argument is + * array('enabled' => false) + * + * @param array $source Source array + * @return \Elastica\Type\Mapping Current object + * @link http://www.elasticsearch.org/guide/reference/mapping/source-field.html + */ + public function setSource(array $source) + { + return $this->setParam('_source', $source); + } + + /** + * Disables the source in the index + * + * Param can be set to true to enable again + * + * @param bool $enabled OPTIONAL (default = false) + * @return \Elastica\Type\Mapping Current object + */ + public function disableSource($enabled = false) + { + return $this->setSource(array('enabled' => $enabled)); + } + + /** + * Sets raw parameters + * + * Possible options: + * _uid + * _id + * _type + * _source + * _all + * _analyzer + * _boost + * _parent + * _routing + * _index + * _size + * properties + * + * @param string $key Key name + * @param mixed $value Key value + * @return \Elastica\Type\Mapping Current object + */ + public function setParam($key, $value) + { + $this->_mapping[$key] = $value; + + return $this; + } + + /** + * Get raw parameters + * + * @see setParam + * @param string $key Key name + * @return mixed $value Key value + */ + public function getParam($key) + { + return isset($this->_mapping[$key])?$this->_mapping[$key]:null; + } + + /** + * Sets params for the "_all" field + * + * @param array $params _all Params (enabled, store, term_vector, analyzer) + * @return \Elastica\Type\Mapping + */ + public function setAllField(array $params) + { + return $this->setParam('_all', $params); + } + + /** + * Enables the "_all" field + * + * @param bool $enabled OPTIONAL (default = true) + * @return \Elastica\Type\Mapping + */ + public function enableAllField($enabled = true) + { + return $this->setAllField(array('enabled' => $enabled)); + } + + /** + * Set TTL + * + * @param array $params TTL Params (enabled, default, ...) + * @return \Elastica\Type\Mapping + */ + public function setTtl(array $params) + { + return $this->setParam('_ttl', $params); + + } + + /** + * Enables TTL for all documents in this type + * + * @param bool $enabled OPTIONAL (default = true) + * @return \Elastica\Type\Mapping + */ + public function enableTtl($enabled = true) + { + return $this->setTTL(array('enabled' => $enabled)); + } + + /** + * Set parent type + * + * @param string $type Parent type + * @return \Elastica\Type\Mapping + */ + public function setParent($type) + { + return $this->setParam('_parent', array('type' => $type)); + } + + /** + * Converts the mapping to an array + * + * @throws \Elastica\Exception\InvalidException + * @return array Mapping as array + */ + public function toArray() + { + $type = $this->getType(); + + if (empty($type)) { + throw new InvalidException('Type has to be set'); + } + + return array($type->getName() => $this->_mapping); + } + + /** + * Submits the mapping and sends it to the server + * + * @return \Elastica\Response Response object + */ + public function send() + { + $path = '_mapping'; + + return $this->getType()->request($path, Request::PUT, $this->toArray()); + } + + /** + * Creates a mapping object + * + * @param array|\Elastica\Type\Mapping $mapping Mapping object or properties array + * @return \Elastica\Type\Mapping Mapping object + * @throws \Elastica\Exception\InvalidException If invalid type + */ + public static function create($mapping) + { + if (is_array($mapping)) { + $mappingObject = new Mapping(); + $mappingObject->setProperties($mapping); + } else { + $mappingObject = $mapping; + } + + if (!$mappingObject instanceof Mapping) { + throw new InvalidException('Invalid object type'); + } + + return $mappingObject; + } +} diff --git a/vendor/ruflin/elastica/lib/Elastica/Util.php b/vendor/ruflin/elastica/lib/Elastica/Util.php new file mode 100644 index 00000000..679bd558 --- /dev/null +++ b/vendor/ruflin/elastica/lib/Elastica/Util.php @@ -0,0 +1,171 @@ +<?php + +namespace Elastica; + +use Elastica\JSON; + +/** + * Elastica tools + * + * @category Xodoa + * @package Elastica + * @author Nicolas Ruflin <spam@ruflin.com> + * @author Thibault Duplessis <thibault.duplessis@gmail.com> + * @author Oleg Zinchenko <olegz@default-value.com> + */ +class Util +{ + /** + * Replace the following reserved words: AND OR NOT + * and + * escapes the following terms: + - && || ! ( ) { } [ ] ^ " ~ * ? : \ + * + * @param string $term Query term to replace and escape + * @return string Replaced and escaped query term + * @link http://lucene.apache.org/java/2_4_0/queryparsersyntax.html#Boolean%20operators + * @link http://lucene.apache.org/java/2_4_0/queryparsersyntax.html#Escaping%20Special%20Characters + */ + public static function replaceBooleanWordsAndEscapeTerm($term) + { + $result = $term; + $result = self::replaceBooleanWords($result); + $result = self::escapeTerm($result); + + return $result; + } + + /** + * Escapes the following terms (because part of the query language) + * + - && || ! ( ) { } [ ] ^ " ~ * ? : \ + * + * @param string $term Query term to escape + * @return string Escaped query term + * @link http://lucene.apache.org/java/2_4_0/queryparsersyntax.html#Escaping%20Special%20Characters + */ + public static function escapeTerm($term) + { + $result = $term; + // \ escaping has to be first, otherwise escaped later once again + $chars = array('\\', '+', '-', '&&', '||', '!', '(', ')', '{', '}', '[', ']', '^', '"', '~', '*', '?', ':'); + + foreach ($chars as $char) { + $result = str_replace($char, '\\' . $char, $result); + } + + // since elasticsearch uses lucene 4.0 / needs to be escaped by \\ + $result = str_replace('/', '\\\\/', $result); + + return $result; + } + + /** + * Replace the following reserved words (because part of the query language) + * AND OR NOT + * + * @param string $term Query term to replace + * @return string Replaced query term + * @link http://lucene.apache.org/java/2_4_0/queryparsersyntax.html#Boolean%20operators + */ + public static function replaceBooleanWords($term) + { + $replacementMap = array('AND'=>'&&', 'OR'=>'||', 'NOT'=>'!'); + $result = strtr($term, $replacementMap); + + return $result; + } + + /** + * Converts a snake_case string to CamelCase + * + * For example: hello_world to HelloWorld + * + * @param string $string snake_case string + * @return string CamelCase string + */ + public static function toCamelCase($string) + { + return str_replace(" ", "", ucwords(str_replace("_", " ", $string))); + } + + /** + * Converts a CamelCase string to snake_case + * + * For Example HelloWorld to hello_world + * + * @param string $string CamelCase String to Convert + * @return string SnakeCase string + */ + public static function toSnakeCase($string) + { + $string = preg_replace('/([A-Z])/', '_$1', $string); + + return strtolower(substr($string,1)); + } + + /** + * Converts given time to format: 1995-12-31T23:59:59Z + * + * This is the lucene date format + * + * @param int $date Date input (could be string etc.) -> must be supported by strtotime + * @return string Converted date string + */ + public static function convertDate($date) + { + if (is_int($date)) { + $timestamp = $date; + } else { + $timestamp = strtotime($date); + } + $string = date('Y-m-d\TH:i:s\Z', $timestamp); + + return $string; + } + + /** + * Tries to guess the name of the param, based on its class + * Example: \Elastica\Filter\HasChildFilter => has_child + * + * @param string|object Class or Class name + * @return string parameter name + */ + public static function getParamName($class) + { + if (is_object($class)) { + $class = get_class($class); + } + + $parts = explode('\\', $class); + $last = array_pop($parts); + $last = preg_replace('/(Facet|Query|Filter)$/', '', $last); + $name = self::toSnakeCase($last); + + return $name; + } + + /** + * Converts Request to Curl console command + * + * @param Request $request + * @return string + */ + public static function convertRequestToCurlCommand(Request $request) + { + $message = 'curl -X' . strtoupper($request->getMethod()) . ' '; + $message .= '\'http://' . $request->getConnection()->getHost() . ':' . $request->getConnection()->getPort() . '/'; + $message .= $request->getPath(); + + $query = $request->getQuery(); + if (!empty($query)) { + $message .= '?' . http_build_query($query); + } + + $message .= '\''; + + $data = $request->getData(); + if (!empty($data)) { + $message .= ' -d \'' . JSON::stringify($data) . '\''; + } + return $message; + } +} diff --git a/vendor/ruflin/elastica/phpdoc.dist.xml b/vendor/ruflin/elastica/phpdoc.dist.xml new file mode 100644 index 00000000..585a4687 --- /dev/null +++ b/vendor/ruflin/elastica/phpdoc.dist.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<docblox> + <title>Elastica</title> + <parser> + <target>./build/api</target> + </parser> + <transformer> + <target>./build/api</target> + </transformer> + <files> + <directory>./lib</directory> + </files> +</docblox> diff --git a/vendor/ruflin/elastica/test/benchmark/BulkMemoryUsageTest.php b/vendor/ruflin/elastica/test/benchmark/BulkMemoryUsageTest.php new file mode 100644 index 00000000..23e6521f --- /dev/null +++ b/vendor/ruflin/elastica/test/benchmark/BulkMemoryUsageTest.php @@ -0,0 +1,46 @@ +<?php + +use Elastica\Client; +use Elastica\Document; + +class BulkMemoryUsageTest extends \PHPUnit_Framework_TestCase +{ + + /** + * Some memory usage stats + * + * Really simple and quite stupid ... + */ + public function testServersArray() + { + $client = new Client(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('test'); + + $data = array( + 'text1' => 'Very long text for a string', + 'text2' => 'But this is not very long', + 'text3' => 'random or not random?', + ); + + $startMemory = memory_get_usage(); + + for ($n = 1; $n < 10; $n++) { + $docs = array(); + + for ($i = 1; $i <= 3000; $i++) { + $docs[] = new Document(uniqid(), $data); + } + + $type->addDocuments($docs); + $docs = array(); + } + + unset($docs); + + $endMemory = memory_get_usage(); + + $this->assertLessThan(1.2, $endMemory/$startMemory); + } +} diff --git a/vendor/ruflin/elastica/test/benchmark/ClientTest.php b/vendor/ruflin/elastica/test/benchmark/ClientTest.php new file mode 100644 index 00000000..e7a040f7 --- /dev/null +++ b/vendor/ruflin/elastica/test/benchmark/ClientTest.php @@ -0,0 +1,31 @@ +<?php + +use Elastica\Client; +use Elastica\Document; + +class ClientTest extends \PHPUnit_Framework_TestCase +{ + + public function testServersArray() + { + $client = new Client(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('test'); + + $start = microtime(true); + + for ($i = 1; $i <= 10000; $i++) { + $doc = new Document($i, array('test' => 1)); + $type->addDocument($doc); + } + + // Refresh index + $index->refresh(); + + $end = microtime(true); + + //echo $end - $start; + + } +} diff --git a/vendor/ruflin/elastica/test/benchmark/TransportTest.php b/vendor/ruflin/elastica/test/benchmark/TransportTest.php new file mode 100644 index 00000000..42d6ac0c --- /dev/null +++ b/vendor/ruflin/elastica/test/benchmark/TransportTest.php @@ -0,0 +1,252 @@ +<?php + +use Elastica\Client; +use Elastica\Request; +use Elastica\Document; +use Elastica\Query; +use Elastica\Type\Mapping; +use Elastica\Query\MatchAll as MatchAllQuery; +use Elastica\Filter\Term as TermFilter; + +class TransportTest extends \PHPUnit_Framework_TestCase +{ + protected $_max = 1000; + + protected $_maxData = 20; + + static protected $_results = array(); + + public static function setUpBeforeClass() + { + if (!defined('DEBUG')) { + define('DEBUG', true); + } else if (false == DEBUG) { + self::markTestIncomplete('DEBUG const is set to false, it prevents query time measuring.'); + } + } + + public static function tearDownAfterClass() + { + self::printResults(); + } + + /** + * @param array $config + * @return \Elastica\Type + */ + protected function getType(array $config) + { + $client = new Client($config); + $index = $client->getIndex('test'); + return $index->getType('test'); + } + + /** + * @dataProvider providerTransport + */ + public function testAddDocument(array $config, $transport) + { + $type = $this->getType($config); + $index = $type->getIndex(); + $index->create(array(), true); + + $times = array(); + for ($i = 0; $i < $this->_max; $i++) { + $data = $this->getData($i); + $doc = new Document($i, $data); + $result = $type->addDocument($doc); + $times[] = $result->getQueryTime(); + $this->assertTrue($result->isOk()); + } + + $index->refresh(); + + self::logResults('insert', $transport, $times); + } + + /** + * @depends testAddDocument + * @dataProvider providerTransport + */ + public function testRandomRead(array $config, $transport) + { + $type = $this->getType($config); + + $type->search('test'); + + $times = array(); + for ($i = 0; $i < $this->_max; $i++) { + $test = rand(1, $this->_max); + $query = new Query(); + $query->setQuery(new MatchAllQuery()); + $query->setFilter(new TermFilter(array('test' => $test))); + $result = $type->search($query); + $times[] = $result->getResponse()->getQueryTime(); + } + + self::logResults('random read', $transport, $times); + } + + /** + * @depends testAddDocument + * @dataProvider providerTransport + */ + public function testBulk(array $config, $transport) + { + $type = $this->getType($config); + + $times = array(); + for ($i = 0; $i < $this->_max; $i++) { + $docs = array(); + for ($j = 0; $j < 10; $j++) { + $data = $this->getData($i . $j); + $docs[] = new Document($i, $data); + } + + $result = $type->addDocuments($docs); + $times[] = $result->getQueryTime(); + } + + self::logResults('bulk', $transport, $times); + } + + /** + * @dataProvider providerTransport + */ + public function testGetMapping(array $config, $transport) + { + $client = new Client($config); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('mappingTest'); + + // Define mapping + $mapping = new Mapping(); + $mapping->setParam('_boost', array('name' => '_boost', 'null_value' => 1.0)); + $mapping->setProperties(array( + 'id' => array('type' => 'integer', 'include_in_all' => FALSE), + 'user' => array( + 'type' => 'object', + 'properties' => array( + 'name' => array('type' => 'string', 'include_in_all' => TRUE), + 'fullName' => array('type' => 'string', 'include_in_all' => TRUE) + ), + ), + 'msg' => array('type' => 'string', 'include_in_all' => TRUE), + 'tstamp' => array('type' => 'date', 'include_in_all' => FALSE), + 'location'=> array('type' => 'geo_point', 'include_in_all' => FALSE), + '_boost' => array('type' => 'float', 'include_in_all' => FALSE) + )); + + $type->setMapping($mapping); + $index->refresh(); + + $times = array(); + for ($i = 0; $i < $this->_max; $i++) { + $response = $type->request('_mapping', Request::GET); + $times[] = $response->getQueryTime(); + } + self::logResults('get mapping', $transport, $times); + } + + public function providerTransport() + { + return array( + array( + array( + 'transport' => 'Http', + 'host' => 'localhost', + 'port' => 9200, + 'persistent' => false, + ), + 'Http:NotPersistent' + ), + array( + array( + 'transport' => 'Http', + 'host' => 'localhost', + 'port' => 9200, + 'persistent' => true, + ), + 'Http:Persistent' + ), + array( + array( + 'transport' => 'Thrift', + 'host' => 'localhost', + 'port' => 9500, + 'config' => array( + 'framedTransport' => false, + ), + ), + 'Thrift:Buffered' + ), + ); + } + + /** + * @param string $test + * @return array + */ + protected function getData($test) + { + $data = array( + 'test' => $test, + 'name' => array(), + ); + for ($i = 0; $i < $this->_maxData; $i++) { + $data['name'][] = uniqid(); + } + return $data; + } + + /** + * @param $name + * @param $transport + * @param array $times + */ + protected static function logResults($name, $transport, array $times) + { + self::$_results[$name][$transport] = array( + 'count' => count($times), + 'max' => max($times) * 1000, + 'min' => min($times) * 1000, + 'mean' => (array_sum($times) / count($times)) * 1000, + ); + } + + protected static function printResults() + { + echo sprintf( + "\n%-12s | %-20s | %-12s | %-12s | %-12s | %-12s\n\n", + 'NAME', + 'TRANSPORT', + 'COUNT', + 'MAX', + 'MIN', + 'MEAN', + '%' + ); + foreach (self::$_results as $name => $values) { + $means = array(); + foreach ($values as $times) { + $means[] = $times['mean']; + } + $minMean = min($means); + foreach ($values as $transport => $times) { + $perc = (($times['mean'] - $minMean) / $minMean) * 100; + echo sprintf( + "%-12s | %-20s | %-12d | %-12.2f | %-12.2f | %-12.2f | %+03.2f\n", + $name, + $transport, + $times['count'], + $times['max'], + $times['min'], + $times['mean'], + $perc + ); + } + echo "\n"; + } + } +} diff --git a/vendor/ruflin/elastica/test/benchmark/phpunit.benchmark.xml b/vendor/ruflin/elastica/test/benchmark/phpunit.benchmark.xml new file mode 100644 index 00000000..a530de35 --- /dev/null +++ b/vendor/ruflin/elastica/test/benchmark/phpunit.benchmark.xml @@ -0,0 +1,10 @@ +<phpunit backupGlobals="false" + backupStaticAttributes="false" + bootstrap="../bootstrap.php" + colors="true"> + <testsuites> + <testsuite name="Transport"> + <file>TransportTest.php</file> + </testsuite> + </testsuites> +</phpunit>
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/benchmark/phpunit.xhprof.xml b/vendor/ruflin/elastica/test/benchmark/phpunit.xhprof.xml new file mode 100644 index 00000000..2293155a --- /dev/null +++ b/vendor/ruflin/elastica/test/benchmark/phpunit.xhprof.xml @@ -0,0 +1,39 @@ +<phpunit backupGlobals="false" + backupStaticAttributes="true" + bootstrap="../bootstrap.php" + colors="true"> + <testsuites> + <testsuite name="Transport"> + <file>TransportTest.php</file> + </testsuite> + </testsuites> + <listeners> + <listener class="PHPUnit_Util_Log_XHProf" file="/home/munkie/Projects/phpunit-testlistener-xhprof/PHPUnit/Util/Log/XHProf.php"> + <arguments> + <array> + <element key="xhprofLibFile"> + <string>/var/www/xhprof/xhprof_lib/utils/xhprof_lib.php</string> + </element> + <element key="xhprofRunsFile"> + <string>/var/www/xhprof/xhprof_lib/utils/xhprof_runs.php</string> + </element> + <element key="xhprofWeb"> + <string>http://xhprof.local/</string> + </element> + <element key="appNamespace"> + <string>Elastica</string> + </element> + <element key="xhprofFlags"> + <string>XHPROF_FLAGS_CPU,XHPROF_FLAGS_MEMORY</string> + </element> + <element key="xhprofConfigFile"> + <string>/var/www/xhprof/xhprof_lib/config.php</string> + </element> + <element key="xhprofIgnore"> + <string>call_user_func,call_user_func_array</string> + </element> + </array> + </arguments> + </listener> + </listeners> +</phpunit>
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/bin/install_php_memcache.sh b/vendor/ruflin/elastica/test/bin/install_php_memcache.sh new file mode 100644 index 00000000..dd046a56 --- /dev/null +++ b/vendor/ruflin/elastica/test/bin/install_php_memcache.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# Build and install PHP Memcache extension +wget http://pecl.php.net/get/memcache-${MEMCACHE_VER}.tgz +tar -xzf memcache-${MEMCACHE_VER}.tgz +sh -c "cd memcache-${MEMCACHE_VER} && phpize && ./configure --enable-memcache && make && sudo make install" +echo "extension=memcache.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"` + diff --git a/vendor/ruflin/elastica/test/bin/run_elasticsearch.sh b/vendor/ruflin/elastica/test/bin/run_elasticsearch.sh new file mode 100644 index 00000000..ddbbef35 --- /dev/null +++ b/vendor/ruflin/elastica/test/bin/run_elasticsearch.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +check_port_http_code() { + http_code=`echo $(curl -s -o /dev/null -w "%{http_code}" "http://localhost:$1")` + return `test $http_code = "$2"` +} + +wget http://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-${ES_VER}.tar.gz +tar -xzf elasticsearch-${ES_VER}.tar.gz + +elasticsearch-${ES_VER}/bin/plugin -install elasticsearch/elasticsearch-mapper-attachments/${ES_MAPPER_ATTACHMENTS_VER} +#elasticsearch-${ES_VER}/bin/plugin -install elasticsearch/elasticsearch-transport-thrift/${ES_TRANSPORT_THRIFT_VER} +elasticsearch-${ES_VER}/bin/plugin -install geocluster-facet --url https://github.com/zenobase/geocluster-facet/releases/download/${ES_GEOCLUSTER_FACET_VER}/geocluster-facet-${ES_GEOCLUSTER_FACET_VER}.jar + +export JAVA_OPTS="-server" + +# start 3 elasticsearch instances +for i in 0 1 2 +do + echo "Setup node #$i" + + let "http_port = 9200 + $i" + let "thrift_port = 9500 + $i" + + config_yml=elasticsearch-${ES_VER}/config/elasticsearch-$http_port.yml + + echo "Creating config $config_yml" + + cp elasticsearch-${ES_VER}/config/elasticsearch.yml $config_yml + + echo "index.number_of_shards: 2" >> $config_yml + echo "index.number_of_replicas: 0" >> $config_yml + echo "discovery.zen.ping.multicast.enabled: false" >> $config_yml + echo "http.port: $http_port" >> $config_yml + echo "thrift.port: $thrift_port" >> $config_yml + + # enable udp + echo "bulk.udp.enabled: true" >> $config_yml + echo "bulk.udp.bulk_actions: 5" >> $config_yml + + # enable dynamic scripting + echo "script.disable_dynamic: false" >> $config_yml + + echo "Starting server on http port: $http_port" + + elasticsearch-${ES_VER}/bin/elasticsearch -d -Des.config=$config_yml & + + while ! check_port_http_code $http_port 200; do + echo -n "." + sleep 2s + done + echo "" + echo "Server #$i is up" +done + +echo "three elasticsearch nodes are up" diff --git a/vendor/ruflin/elastica/test/bin/run_proxy.sh b/vendor/ruflin/elastica/test/bin/run_proxy.sh new file mode 100644 index 00000000..c62db8cd --- /dev/null +++ b/vendor/ruflin/elastica/test/bin/run_proxy.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +sudo killall nginx 2>/dev/null + +echo "installing nginx" + +sudo apt-get install nginx + +echo "stopping stock nginx" + +/etc/init.d/nginx stop + +echo "running nginx" + +sudo nginx -p test/nginx/ -c nginx.conf diff --git a/vendor/ruflin/elastica/test/bin/show_logs.sh b/vendor/ruflin/elastica/test/bin/show_logs.sh new file mode 100644 index 00000000..0130d2a5 --- /dev/null +++ b/vendor/ruflin/elastica/test/bin/show_logs.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +cat elasticsearch-${ES_VER}/logs/*
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/bootstrap.php b/vendor/ruflin/elastica/test/bootstrap.php new file mode 100644 index 00000000..5903f805 --- /dev/null +++ b/vendor/ruflin/elastica/test/bootstrap.php @@ -0,0 +1,5 @@ +<?php + +defined('BASE_PATH') || define('BASE_PATH', realpath(__DIR__)); + +require dirname(__DIR__) . '/vendor/autoload.php'; diff --git a/vendor/ruflin/elastica/test/data/test.doc b/vendor/ruflin/elastica/test/data/test.doc Binary files differnew file mode 100644 index 00000000..d90d83c1 --- /dev/null +++ b/vendor/ruflin/elastica/test/data/test.doc diff --git a/vendor/ruflin/elastica/test/data/test.docx b/vendor/ruflin/elastica/test/data/test.docx Binary files differnew file mode 100644 index 00000000..924c1066 --- /dev/null +++ b/vendor/ruflin/elastica/test/data/test.docx diff --git a/vendor/ruflin/elastica/test/data/test.pdf b/vendor/ruflin/elastica/test/data/test.pdf Binary files differnew file mode 100644 index 00000000..e94c3f67 --- /dev/null +++ b/vendor/ruflin/elastica/test/data/test.pdf diff --git a/vendor/ruflin/elastica/test/data/test.txt b/vendor/ruflin/elastica/test/data/test.txt new file mode 100644 index 00000000..839b72a1 --- /dev/null +++ b/vendor/ruflin/elastica/test/data/test.txt @@ -0,0 +1 @@ +Wie geht es ihnen?
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/AvgTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/AvgTest.php new file mode 100644 index 00000000..5c6fe13d --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/AvgTest.php @@ -0,0 +1,38 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Aggregation\Avg; +use Elastica\Document; +use Elastica\Index; +use Elastica\Query; + +class AvgTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex('avg'); + $docs = array( + new Document('1', array('price' => 5)), + new Document('2', array('price' => 8)), + new Document('3', array('price' => 1)), + new Document('4', array('price' => 3)), + ); + $this->_index->getType('test')->addDocuments($docs); + $this->_index->refresh(); + } + + public function testAvgAggregation() + { + $agg = new Avg("avg"); + $agg->setField('price'); + + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregations(); + $this->assertEquals((5 + 8 + 1 + 3) / 4.0, $results['avg']['value']); + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/BaseAggregationTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/BaseAggregationTest.php new file mode 100644 index 00000000..5569ca78 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/BaseAggregationTest.php @@ -0,0 +1,28 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Index; +use Elastica\Test\Base; + +abstract class BaseAggregationTest extends Base +{ + /** + * @var Index + */ + protected $_index; + + protected function tearDown() + { + parent::tearDown(); + if ($this->_index instanceof Index) { + $this->_index->delete(); + } + } + + protected function _createIndex($name = 'test', $delete = true, $shards = 1) + { + return parent::_createIndex('test_aggregation_' . $name, $delete, $shards); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/CardinalityTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/CardinalityTest.php new file mode 100644 index 00000000..d2f4d2be --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/CardinalityTest.php @@ -0,0 +1,38 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Aggregation\Cardinality; +use Elastica\Document; +use Elastica\Query; + +class CardinalityTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex("cardinality"); + $docs = array( + new Document("1", array("color" => "blue")), + new Document("2", array("color" => "blue")), + new Document("3", array("color" => "red")), + new Document("4", array("color" => "green")), + ); + $this->_index->getType("test")->addDocuments($docs); + $this->_index->refresh(); + } + + public function testCardinalityAggregation() + { + $agg = new Cardinality("cardinality"); + $agg->setField("color"); + + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregation("cardinality"); + + $this->assertEquals(3, $results['value']); + } +} + diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/DateHistogramTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/DateHistogramTest.php new file mode 100644 index 00000000..d5bd878c --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/DateHistogramTest.php @@ -0,0 +1,43 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Aggregation\DateHistogram; +use Elastica\Document; +use Elastica\Query; +use Elastica\Type\Mapping; + +class DateHistogramTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex("date_histogram"); + $mapping = new Mapping(); + $mapping->setProperties(array( + "created" => array("type" => "date") + )); + $type = $this->_index->getType("test"); + $type->setMapping($mapping); + $docs = array( + new Document("1", array("created" => 1390962135000)), + new Document("2", array("created" => 1390965735000)), + new Document("3", array("created" => 1390954935000)), + ); + $type->addDocuments($docs); + $this->_index->refresh(); + } + + public function testDateHistogramAggregation() + { + $agg = new DateHistogram("hist", "created", "1h"); + + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregation("hist"); + + $this->assertEquals(3, sizeof($results['buckets'])); + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/DateRangeTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/DateRangeTest.php new file mode 100644 index 00000000..781f2112 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/DateRangeTest.php @@ -0,0 +1,51 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Aggregation\DateRange; +use Elastica\Document; +use Elastica\Query; +use Elastica\Type\Mapping; + +class DateRangeTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex("date_range"); + $mapping = new Mapping(); + $mapping->setProperties(array( + "created" => array("type" => "date") + )); + $type = $this->_index->getType("test"); + $type->setMapping($mapping); + $docs = array( + new Document("1", array("created" => 1390962135000)), + new Document("2", array("created" => 1390965735000)), + new Document("3", array("created" => 1390954935000)), + ); + $type->addDocuments($docs); + $this->_index->refresh(); + } + + public function testDateRangeAggregation() + { + $agg = new DateRange("date"); + $agg->setField("created"); + $agg->addRange(1390958535000)->addRange(null, 1390958535000); + + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregation("date"); + + foreach ($results['buckets'] as $bucket) { + if (array_key_exists('to', $bucket)) { + $this->assertEquals(1, $bucket['doc_count']); + } else if (array_key_exists('from', $bucket)) { + $this->assertEquals(2, $bucket['doc_count']); + } + } + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/ExtendedStatsTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/ExtendedStatsTest.php new file mode 100644 index 00000000..e125c9c9 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/ExtendedStatsTest.php @@ -0,0 +1,43 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Aggregation\ExtendedStats; +use Elastica\Document; +use Elastica\Query; + +class ExtendedStatsTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex("extended_stats"); + $docs = array( + new Document("1", array("price" => 5)), + new Document("2", array("price" => 8)), + new Document("3", array("price" => 1)), + new Document("4", array("price" => 3)), + ); + $this->_index->getType("test")->addDocuments($docs); + $this->_index->refresh(); + } + + public function testExtendedStatsAggregation() + { + $agg = new ExtendedStats("stats"); + $agg->setField("price"); + + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregation("stats"); + + $this->assertEquals(4, $results['count']); + $this->assertEquals(1, $results['min']); + $this->assertEquals(8, $results['max']); + $this->assertEquals((5 + 8 + 1 + 3) / 4.0, $results['avg']); + $this->assertEquals((5 + 8 + 1 + 3), $results['sum']); + $this->assertTrue(array_key_exists('sum_of_squares', $results)); + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/FilterTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/FilterTest.php new file mode 100644 index 00000000..dd4d4c2d --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/FilterTest.php @@ -0,0 +1,78 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Aggregation\Avg; +use Elastica\Aggregation\Filter; +use Elastica\Document; +use Elastica\Filter\Range; +use Elastica\Filter\Term; +use Elastica\Query; + +class FilterTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex("filter"); + $docs = array( + new Document("1", array("price" => 5, "color" => "blue")), + new Document("2", array("price" => 8, "color" => "blue")), + new Document("3", array("price" => 1, "color" => "red")), + new Document("4", array("price" => 3, "color" => "green")), + ); + $this->_index->getType("test")->addDocuments($docs); + $this->_index->refresh(); + } + + public function testToArray() + { + $expected = array( + "filter" => array("range" => array("stock" => array("gt" => 0))), + "aggs" => array( + "avg_price" => array("avg" => array("field" => "price")) + ) + ); + + $agg = new Filter("in_stock_products"); + $agg->setFilter(new Range("stock", array("gt" => 0))); + $avg = new Avg("avg_price"); + $avg->setField("price"); + $agg->addAggregation($avg); + + $this->assertEquals($expected, $agg->toArray()); + } + + public function testFilterAggregation() + { + $agg = new Filter("filter"); + $agg->setFilter(new Term(array("color" => "blue"))); + $avg = new Avg("price"); + $avg->setField("price"); + $agg->addAggregation($avg); + + $query = new Query(); + $query->addAggregation($agg); + + $results = $this->_index->search($query)->getAggregation("filter"); + $results = $results['price']['value']; + + $this->assertEquals((5 + 8) / 2.0, $results); + } + + public function testFilterNoSubAggregation() + { + $agg = new Avg("price"); + $agg->setField("price"); + + $query = new Query(); + $query->addAggregation($agg); + + $results = $this->_index->search($query)->getAggregation("price"); + $results = $results['value']; + + $this->assertEquals((5 + 8 + 1 + 3) / 4.0, $results); + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/GeoDistanceTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/GeoDistanceTest.php new file mode 100644 index 00000000..7fd677b1 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/GeoDistanceTest.php @@ -0,0 +1,45 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Aggregation\GeoDistance; +use Elastica\Document; +use Elastica\Query; +use Elastica\Type\Mapping; + +class GeoDistanceTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex("geo_distance"); + $mapping = new Mapping(); + $mapping->setProperties(array( + "location" => array("type" => "geo_point") + )); + $type = $this->_index->getType("test"); + $type->setMapping($mapping); + $docs = array( + new Document("1", array("location" => array("lat" => 32.849437, "lon" => -117.271732))), + new Document("2", array("location" => array("lat" => 32.798320, "lon" => -117.246648))), + new Document("3", array("location" => array("lat" => 37.782439, "lon" => -122.392560))), + ); + $type->addDocuments($docs); + $this->_index->refresh(); + } + + public function testGeoDistanceAggregation() + { + $agg = new GeoDistance("geo", "location", array("lat" => 32.804654, "lon" => -117.242594)); + $agg->addRange(null, 100); + $agg->setUnit("mi"); + + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregation("geo"); + + $this->assertEquals(2, $results['buckets'][0]['doc_count']); + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/GeohashGridTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/GeohashGridTest.php new file mode 100644 index 00000000..38a047f7 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/GeohashGridTest.php @@ -0,0 +1,45 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Aggregation\GeohashGrid; +use Elastica\Document; +use Elastica\Query; +use Elastica\Type\Mapping; + +class GeohashGridTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex("geohash_grid"); + $mapping = new Mapping(); + $mapping->setProperties(array( + "location" => array("type" => "geo_point") + )); + $type = $this->_index->getType("test"); + $type->setMapping($mapping); + $docs = array( + new Document("1", array("location" => array("lat" => 32.849437, "lon" => -117.271732))), + new Document("2", array("location" => array("lat" => 32.798320, "lon" => -117.246648))), + new Document("3", array("location" => array("lat" => 37.782439, "lon" => -122.392560))), + ); + $type->addDocuments($docs); + $this->_index->refresh(); + } + + public function testGeohashGridAggregation() + { + $agg = new GeohashGrid("hash", "location"); + $agg->setPrecision(3); + + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregation("hash"); + + $this->assertEquals(2, $results['buckets'][0]['doc_count']); + $this->assertEquals(1, $results['buckets'][1]['doc_count']); + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/GlobalAggregationTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/GlobalAggregationTest.php new file mode 100644 index 00000000..80366f50 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/GlobalAggregationTest.php @@ -0,0 +1,27 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Aggregation\Avg; +use Elastica\Aggregation\GlobalAggregation; + +class GlobalAggregationTest extends BaseAggregationTest +{ + public function testToArray() + { + $expected = array( + "global" => new \stdClass(), + "aggs" => array( + "avg_price" => array("avg" => array("field" => "price")) + ) + ); + + $agg = new GlobalAggregation("all_products"); + $avg = new Avg("avg_price"); + $avg->setField("price"); + $agg->addAggregation($avg); + $this->assertEquals($expected, $agg->toArray()); + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/HistogramTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/HistogramTest.php new file mode 100644 index 00000000..35032f43 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/HistogramTest.php @@ -0,0 +1,45 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Document; +use Elastica\Aggregation\Histogram; +use Elastica\Query; + +class HistogramTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex("histogram"); + $docs = array( + new Document("1", array("price" => 5, "color" => "blue")), + new Document("2", array("price" => 8, "color" => "blue")), + new Document("3", array("price" => 1, "color" => "red")), + new Document("4", array("price" => 30, "color" => "green")), + new Document("5", array("price" => 40, "color" => "red")), + new Document("6", array("price" => 35, "color" => "green")), + new Document("7", array("price" => 42, "color" => "red")), + new Document("8", array("price" => 41, "color" => "blue")), + ); + $this->_index->getType("test")->addDocuments($docs); + $this->_index->refresh(); + } + + public function testHistogramAggregation() + { + $agg = new Histogram("hist", "price", 10); + $agg->setMinimumDocumentCount(0); // should return empty buckets + + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregation("hist"); + + $buckets = $results['buckets']; + $this->assertEquals(5, sizeof($buckets)); + $this->assertEquals(30, $buckets[3]['key']); + $this->assertEquals(2, $buckets[3]['doc_count']); + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/IpRangeTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/IpRangeTest.php new file mode 100644 index 00000000..fce6f857 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/IpRangeTest.php @@ -0,0 +1,56 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Aggregation\IpRange; +use Elastica\Document; +use Elastica\Query; +use Elastica\Type\Mapping; + +class IpRangeTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex("ip_range"); + $mapping = new Mapping(); + $mapping->setProperties(array( + "address" => array("type" => "ip") + )); + $type = $this->_index->getType("test"); + $type->setMapping($mapping); + $docs = array( + new Document("1", array("address" => "192.168.1.100")), + new Document("2", array("address" => "192.168.1.150")), + new Document("3", array("address" => "192.168.1.200")), + ); + $type->addDocuments($docs); + $this->_index->refresh(); + } + + public function testIpRangeAggregation() + { + $agg = new IpRange("ip", "address"); + $agg->addRange("192.168.1.101"); + $agg->addRange(null, "192.168.1.200"); + + $cidrRange = "192.168.1.0/24"; + $agg->addMaskRange($cidrRange); + + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregation("ip"); + + foreach ($results['buckets'] as $bucket) { + if (array_key_exists('key', $bucket) && $bucket['key'] == $cidrRange) { + // the CIDR mask + $this->assertEquals(3, $bucket['doc_count']); + } else { + // the normal ip ranges + $this->assertEquals(2, $bucket['doc_count']); + } + } + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/MaxTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/MaxTest.php new file mode 100644 index 00000000..0f5475b3 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/MaxTest.php @@ -0,0 +1,72 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Aggregation\Max; +use Elastica\Document; +use Elastica\Query; +use Elastica\Script; + +class MaxTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex('max'); + $docs = array( + new Document('1', array('price' => 5)), + new Document('2', array('price' => 8)), + new Document('3', array('price' => 1)), + new Document('4', array('price' => 3)), + ); + $this->_index->getType('test')->addDocuments($docs); + $this->_index->refresh(); + } + + public function testToArray() + { + $expected = array( + "max" => array( + "field" => "price", + "script" => "_value * conversion_rate", + "params" => array( + "conversion_rate" => 1.2 + ) + ), + "aggs" => array( + "subagg" => array("max" => array("field" => "foo")) + ) + ); + + $agg = new Max("min_price_in_euros"); + $agg->setField("price"); + $agg->setScript(new Script("_value * conversion_rate", array('conversion_rate' => 1.2))); + $max = new Max("subagg"); + $max->setField("foo"); + $agg->addAggregation($max); + + $this->assertEquals($expected, $agg->toArray()); + } + + public function testMaxAggregation() + { + $agg = new Max("min_price"); + $agg->setField("price"); + + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregation("min_price"); + + $this->assertEquals(8, $results['value']); + + // test using a script + $agg->setScript(new Script("_value * conversion_rate", array("conversion_rate" => 1.2))); + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregation("min_price"); + + $this->assertEquals(8 * 1.2, $results['value']); + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/MinTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/MinTest.php new file mode 100644 index 00000000..44b52fb4 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/MinTest.php @@ -0,0 +1,38 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Aggregation\Min; +use Elastica\Document; +use Elastica\Query; + +class MinTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex('min'); + $docs = array( + new Document('1', array('price' => 5)), + new Document('2', array('price' => 8)), + new Document('3', array('price' => 1)), + new Document('4', array('price' => 3)), + ); + $this->_index->getType('test')->addDocuments($docs); + $this->_index->refresh(); + } + + public function testMinAggregation() + { + $agg = new Min("min_price"); + $agg->setField("price"); + + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregation("min_price"); + + $this->assertEquals(1, $results['value']); + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/MissingTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/MissingTest.php new file mode 100644 index 00000000..2a852ed0 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/MissingTest.php @@ -0,0 +1,37 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Aggregation\Missing; +use Elastica\Document; +use Elastica\Query; + +class MissingTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex('missing'); + $docs = array( + new Document('1', array('price' => 5, "color" => "blue")), + new Document('2', array('price' => 8, "color" => "blue")), + new Document('3', array('price' => 1)), + new Document('4', array('price' => 3, "color" => "green")), + ); + $this->_index->getType('test')->addDocuments($docs); + $this->_index->refresh(); + } + + public function testMissingAggregation() + { + $agg = new Missing("missing", "color"); + + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregation("missing"); + + $this->assertEquals(1, $results['doc_count']); + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/NestedTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/NestedTest.php new file mode 100644 index 00000000..ed6de99e --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/NestedTest.php @@ -0,0 +1,62 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Aggregation\Min; +use Elastica\Aggregation\Nested; +use Elastica\Document; +use Elastica\Query; +use Elastica\Type\Mapping; + +class NestedTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex("nested"); + $mapping = new Mapping(); + $mapping->setProperties(array( + "resellers" => array( + "type" => "nested", + "properties" => array( + "name" => array("type" => "string"), + "price" => array("type" => "double") + ) + ) + )); + $type = $this->_index->getType("test"); + $type->setMapping($mapping); + $docs = array( + new Document("1", array( + "resellers" => array( + "name" => "spacely sprockets", + "price" => 5.55 + ) + )), + new Document("1", array( + "resellers" => array( + "name" => "cogswell cogs", + "price" => 4.98 + ) + )) + ); + $type->addDocuments($docs); + $this->_index->refresh(); + } + + public function testNestedAggregation() + { + $agg = new Nested("resellers", "resellers"); + $min = new Min("min_price"); + $min->setField("price"); + $agg->addAggregation($min); + + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregation("resellers"); + + $this->assertEquals(4.98, $results['min_price']['value']); + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/RangeTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/RangeTest.php new file mode 100644 index 00000000..fb5ca2fe --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/RangeTest.php @@ -0,0 +1,41 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Aggregation\Range; +use Elastica\Document; +use Elastica\Query; + +class RangeTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex('range'); + $docs = array( + new Document('1', array('price' => 5)), + new Document('2', array('price' => 8)), + new Document('3', array('price' => 1)), + new Document('4', array('price' => 3)), + new Document('5', array('price' => 1.5)), + new Document('6', array('price' => 2)), + ); + $this->_index->getType('test')->addDocuments($docs); + $this->_index->refresh(); + } + + public function testRangeAggregation() + { + $agg = new Range("range"); + $agg->setField("price"); + $agg->addRange(1.5, 5); + + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregation("range"); + + $this->assertEquals(2, $results['buckets'][0]['doc_count']); + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/ReverseNestedTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/ReverseNestedTest.php new file mode 100644 index 00000000..215dac63 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/ReverseNestedTest.php @@ -0,0 +1,124 @@ +<?php + +namespace Elastica\Test\Aggregation; + +use Elastica\Aggregation\Terms; +use Elastica\Aggregation\Nested; +use Elastica\Aggregation\ReverseNested; +use Elastica\Document; +use Elastica\Query; +use Elastica\Type\Mapping; + +class ReverseNestedTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex("nested"); + $mapping = new Mapping(); + $mapping->setProperties(array( + "comments" => array( + "type" => "nested", + "properties" => array( + "name" => array("type" => "string"), + "body" => array("type" => "string") + ) + ) + )); + $type = $this->_index->getType("test"); + $type->setMapping($mapping); + $docs = array( + new Document("1", array( + "comments" => array( + array( + "name" => "bob", + "body" => "this is bobs comment", + ), + array( + "name" => "john", + "body" => "this is johns comment", + ), + ), + "tags" => array("foo", "bar"), + )), + new Document("2", array( + "comments" => array( + array( + "name" => "bob", + "body" => "this is another comment from bob", + ), + array( + "name" => "susan", + "body" => "this is susans comment", + ), + ), + "tags" => array("foo", "baz"), + )) + ); + $type->addDocuments($docs); + $this->_index->refresh(); + } + + public function testPathNotSetIfNull() + { + $agg = new ReverseNested('nested'); + $this->assertFalse($agg->hasParam('path')); + } + + public function testPathSetIfNotNull() + { + $agg = new ReverseNested('nested', 'some_field'); + $this->assertEquals('some_field', $agg->getParam('path')); + } + + public function testReverseNestedAggregation() + { + $agg = new Nested("comments", "comments"); + $names = new Terms("name"); + $names->setField("comments.name"); + + $tags = new Terms("tags"); + $tags->setField("tags"); + + $reverseNested = new ReverseNested("main"); + $reverseNested->addAggregation($tags); + + $names->addAggregation($reverseNested); + + $agg->addAggregation($names); + + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregation("comments"); + + $this->assertArrayHasKey('name', $results); + $nameResults = $results['name']; + + $this->assertCount(3, $nameResults['buckets']); + + // bob + $this->assertEquals('bob', $nameResults['buckets'][0]['key']); + $tags = array( + array('key' => 'foo', 'doc_count' => 2), + array('key' => 'bar', 'doc_count' => 1), + array('key' => 'baz', 'doc_count' => 1), + ); + $this->assertEquals($tags, $nameResults['buckets'][0]['main']['tags']['buckets']); + + // john + $this->assertEquals('john', $nameResults['buckets'][1]['key']); + $tags = array( + array('key' => 'bar', 'doc_count' => 1), + array('key' => 'foo', 'doc_count' => 1), + ); + $this->assertEquals($tags, $nameResults['buckets'][1]['main']['tags']['buckets']); + + // susan + $this->assertEquals('susan', $nameResults['buckets'][2]['key']); + $tags = array( + array('key' => 'baz', 'doc_count' => 1), + array('key' => 'foo', 'doc_count' => 1), + ); + $this->assertEquals($tags, $nameResults['buckets'][2]['main']['tags']['buckets']); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/StatsTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/StatsTest.php new file mode 100644 index 00000000..2d315abf --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/StatsTest.php @@ -0,0 +1,42 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Aggregation\Stats; +use Elastica\Document; +use Elastica\Query; + +class StatsTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex('stats'); + $docs = array( + new Document('1', array('price' => 5)), + new Document('2', array('price' => 8)), + new Document('3', array('price' => 1)), + new Document('4', array('price' => 3)), + ); + $this->_index->getType('test')->addDocuments($docs); + $this->_index->refresh(); + } + + public function testStatsAggregation() + { + $agg = new Stats("stats"); + $agg->setField("price"); + + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregation("stats"); + + $this->assertEquals(4, $results['count']); + $this->assertEquals(1, $results['min']); + $this->assertEquals(8, $results['max']); + $this->assertEquals((5 + 8 + 1 + 3) / 4.0, $results['avg']); + $this->assertEquals((5 + 8 + 1 + 3), $results['sum']); + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/SumTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/SumTest.php new file mode 100644 index 00000000..3b3c56a2 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/SumTest.php @@ -0,0 +1,38 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Aggregation\Sum; +use Elastica\Document; +use Elastica\Query; + +class SumTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex('sum'); + $docs = array( + new Document('1', array('price' => 5)), + new Document('2', array('price' => 8)), + new Document('3', array('price' => 1)), + new Document('4', array('price' => 3)), + ); + $this->_index->getType('test')->addDocuments($docs); + $this->_index->refresh(); + } + + public function testSumAggregation() + { + $agg = new Sum("sum"); + $agg->setField("price"); + + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregation("sum"); + + $this->assertEquals(5 + 8 + 1 + 3, $results['value']); + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/TermsTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/TermsTest.php new file mode 100644 index 00000000..d9f37a20 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/TermsTest.php @@ -0,0 +1,39 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Aggregation\Terms; +use Elastica\Document; +use Elastica\Query; + +class TermsTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex("terms"); + $docs = array( + new Document("1", array("color" => "blue")), + new Document("2", array("color" => "blue")), + new Document("3", array("color" => "red")), + new Document("4", array("color" => "green")), + ); + $this->_index->getType("test")->addDocuments($docs); + $this->_index->refresh(); + } + + public function testTermsAggregation() + { + $agg = new Terms("terms"); + $agg->setField("color"); + + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregation("terms"); + + $this->assertEquals(2, $results['buckets'][0]['doc_count']); + $this->assertEquals("blue", $results['buckets'][0]['key']); + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/ValueCountTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/ValueCountTest.php new file mode 100644 index 00000000..5eba9ea4 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/ValueCountTest.php @@ -0,0 +1,38 @@ +<?php + +namespace Elastica\Test\Aggregation; + + +use Elastica\Aggregation\ValueCount; +use Elastica\Document; +use Elastica\Query; + +class ValueCountTest extends BaseAggregationTest +{ + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex('value_count'); + $docs = array( + new Document('1', array('price' => 5)), + new Document('2', array('price' => 8)), + new Document('3', array('price' => 1)), + new Document('4', array('price' => 3)), + new Document('5', array('price' => 3)), + ); + $this->_index->getType('test')->addDocuments($docs); + $this->_index->refresh(); + } + + public function testValueCountAggregation() + { + $agg = new ValueCount("count", "price"); + + $query = new Query(); + $query->addAggregation($agg); + $results = $this->_index->search($query)->getAggregation("count"); + + $this->assertEquals(5, $results['value']); + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Base.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Base.php new file mode 100644 index 00000000..55cd8873 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Base.php @@ -0,0 +1,31 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Client; + +class Base extends \PHPUnit_Framework_TestCase +{ + protected function _getClient() + { + return new Client(array( + 'host' => getenv('ES_HOST') ?: 'localhost', + 'port' => getenv('ES_PORT') ?: 9200, + )); + } + + /** + * @param string $name Index name + * @param bool $delete Delete index if it exists + * @param int $shards Number of shards to create + * @return \Elastica\Index + */ + protected function _createIndex($name = 'test', $delete = true, $shards = 1) + { + $client = $this->_getClient(); + $index = $client->getIndex('elastica_' . $name); + $index->create(array('index' => array('number_of_shards' => $shards, 'number_of_replicas' => 0)), $delete); + + return $index; + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Bulk/ActionTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Bulk/ActionTest.php new file mode 100644 index 00000000..178883a8 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Bulk/ActionTest.php @@ -0,0 +1,69 @@ +<?php + +namespace Elastica\Test\Bulk; + +use Elastica\Bulk\Action; +use Elastica\Bulk; +use Elastica\Client; +use Elastica\Exception\Bulk\ResponseException; +use Elastica\Index; +use Elastica\Test\Base as BaseTest; +use Elastica\Bulk\ResponseSet; +use Elastica\Response; +use Elastica\Type; + +class ActionTest extends BaseTest +{ + public function testAction() + { + $action = new Action(); + $this->assertEquals('index', $action->getOpType()); + $this->assertFalse($action->hasSource()); + + $expected = '{"index":{}}' . "\n"; + $this->assertEquals($expected, $action->toString()); + + $action->setIndex('index'); + + $expected = '{"index":{"_index":"index"}}' . "\n"; + $this->assertEquals($expected, $action->toString()); + + $action->setType('type'); + + $expected = '{"index":{"_index":"index","_type":"type"}}' . "\n"; + $this->assertEquals($expected, $action->toString()); + + $action->setId(1); + $expected = '{"index":{"_index":"index","_type":"type","_id":1}}' . "\n"; + $this->assertEquals($expected, $action->toString()); + + $action->setRouting(1); + $expected = '{"index":{"_index":"index","_type":"type","_id":1,"_routing":1}}' . "\n"; + $this->assertEquals($expected, $action->toString()); + + $client = new Client(); + $index = new Index($client, 'index2'); + $type = new Type($index, 'type2'); + + $action->setIndex($index); + + $expected = '{"index":{"_index":"index2","_type":"type","_id":1,"_routing":1}}' . "\n"; + $this->assertEquals($expected, $action->toString()); + + $action->setType($type); + + $expected = '{"index":{"_index":"index2","_type":"type2","_id":1,"_routing":1}}' . "\n"; + $this->assertEquals($expected, $action->toString()); + + $action->setSource(array('user' => 'name')); + + $expected = '{"index":{"_index":"index2","_type":"type2","_id":1,"_routing":1}}' . "\n"; + $expected.= '{"user":"name"}' . "\n"; + + $this->assertEquals($expected, $action->toString()); + $this->assertTrue($action->hasSource()); + + $this->assertFalse(Action::isValidOpType('foo')); + $this->assertTrue(Action::isValidOpType('delete')); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Bulk/ResponseSetTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Bulk/ResponseSetTest.php new file mode 100644 index 00000000..d1495fce --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Bulk/ResponseSetTest.php @@ -0,0 +1,188 @@ +<?php + +namespace Elastica\Test\Bulk; + +use Elastica\Bulk\Action; +use Elastica\Bulk; +use Elastica\Exception\Bulk\ResponseException; +use Elastica\Test\Base as BaseTest; +use Elastica\Bulk\ResponseSet; +use Elastica\Response; + +class ResponseSetTest extends BaseTest +{ + /** + * @dataProvider isOkDataProvider + */ + public function testIsOk($responseData, $actions, $expected) + { + $responseSet = $this->_createResponseSet($responseData, $actions); + $this->assertEquals($expected, $responseSet->isOk()); + } + + public function testGetError() + { + list($responseData, $actions) = $this->_getFixture(); + $responseData['items'][1]['index']['ok'] = false; + $responseData['items'][1]['index']['error'] = 'SomeExceptionMessage'; + $responseData['items'][2]['index']['ok'] = false; + $responseData['items'][2]['index']['error'] = 'AnotherExceptionMessage'; + + try { + $this->_createResponseSet($responseData, $actions); + $this->fail('Bulk request should fail'); + } catch (ResponseException $e) { + $responseSet = $e->getResponseSet(); + + $this->assertInstanceOf('Elastica\\Bulk\\ResponseSet', $responseSet); + + $this->assertTrue($responseSet->hasError()); + $this->assertNotEquals('AnotherExceptionMessage', $responseSet->getError()); + $this->assertEquals('SomeExceptionMessage', $responseSet->getError()); + + $actionExceptions = $e->getActionExceptions(); + $this->assertEquals(2, count($actionExceptions)); + + $this->assertInstanceOf('Elastica\Exception\Bulk\Response\ActionException', $actionExceptions[0]); + $this->assertSame($actions[1], $actionExceptions[0]->getAction()); + $this->assertContains('SomeExceptionMessage', $actionExceptions[0]->getMessage()); + $this->assertTrue($actionExceptions[0]->getResponse()->hasError()); + + $this->assertInstanceOf('Elastica\Exception\Bulk\Response\ActionException', $actionExceptions[1]); + $this->assertSame($actions[2], $actionExceptions[1]->getAction()); + $this->assertContains('AnotherExceptionMessage', $actionExceptions[1]->getMessage()); + $this->assertTrue($actionExceptions[1]->getResponse()->hasError()); + } + } + + public function testGetBulkResponses() + { + list($responseData, $actions) = $this->_getFixture(); + + $responseSet = $this->_createResponseSet($responseData, $actions); + + $bulkResponses = $responseSet->getBulkResponses(); + $this->assertInternalType('array', $bulkResponses); + $this->assertEquals(3, count($bulkResponses)); + + foreach ($bulkResponses as $i => $bulkResponse) { + $this->assertInstanceOf('Elastica\\Bulk\\Response', $bulkResponse); + $bulkResponseData = $bulkResponse->getData(); + $this->assertInternalType('array', $bulkResponseData); + $this->assertArrayHasKey('_id', $bulkResponseData); + $this->assertEquals($responseData['items'][$i]['index']['_id'], $bulkResponseData['_id']); + $this->assertSame($actions[$i], $bulkResponse->getAction()); + $this->assertEquals('index', $bulkResponse->getOpType()); + } + } + + public function testIterator() + { + list($responseData, $actions) = $this->_getFixture(); + + $responseSet = $this->_createResponseSet($responseData, $actions); + + $this->assertEquals(3, count($responseSet)); + + foreach ($responseSet as $i => $bulkResponse) { + $this->assertInstanceOf('Elastica\Bulk\Response', $bulkResponse); + $bulkResponseData = $bulkResponse->getData(); + $this->assertInternalType('array', $bulkResponseData); + $this->assertArrayHasKey('_id', $bulkResponseData); + $this->assertEquals($responseData['items'][$i]['index']['_id'], $bulkResponseData['_id']); + $this->assertSame($actions[$i], $bulkResponse->getAction()); + $this->assertEquals('index', $bulkResponse->getOpType()); + } + + $this->assertFalse($responseSet->valid()); + $this->assertNotInstanceOf('Elastica\Bulk\Response', $responseSet->current()); + $this->assertFalse($responseSet->current()); + + $responseSet->next(); + + $this->assertFalse($responseSet->valid()); + $this->assertNotInstanceOf('Elastica\Bulk\Response', $responseSet->current()); + $this->assertFalse($responseSet->current()); + + $responseSet->rewind(); + + $this->assertEquals(0, $responseSet->key()); + $this->assertTrue($responseSet->valid()); + $this->assertInstanceOf('Elastica\Bulk\Response', $responseSet->current()); + } + + public function isOkDataProvider() + { + list($responseData, $actions) = $this->_getFixture(); + + $return = array(); + $return[] = array($responseData, $actions, true); + $responseData['items'][2]['index']['ok'] = false; + $return[] = array($responseData, $actions, false); + return $return; + } + + /** + * @param array $responseData + * @param array $actions + * @return \Elastica\Bulk\ResponseSet + */ + protected function _createResponseSet(array $responseData, array $actions) + { + $client = $this->getMock('Elastica\\Client', array('request')); + + $client->expects($this->once()) + ->method('request') + ->withAnyParameters() + ->will($this->returnValue(new Response($responseData))); + + $bulk = new Bulk($client); + $bulk->addActions($actions); + return $bulk->send(); + } + + /** + * @return array + */ + protected function _getFixture() + { + $responseData = array( + 'took' => 5, + 'items' => array( + array( + 'index' => array( + '_index' => 'index', + '_type' => 'type', + '_id' => '1', + '_version' => 1, + 'ok' => true, + ) + ), + array( + 'index' => array( + '_index' => 'index', + '_type' => 'type', + '_id' => '2', + '_version' => 1, + 'ok' => true, + ) + ), + array( + 'index' => array( + '_index' => 'index', + '_type' => 'type', + '_id' => '3', + '_version' => 1, + 'ok' => true, + ) + ) + ) + ); + $bulkResponses = array( + new Action(), + new Action(), + new Action(), + ); + return array($responseData, $bulkResponses); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/BulkTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/BulkTest.php new file mode 100644 index 00000000..3396fe86 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/BulkTest.php @@ -0,0 +1,711 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Bulk; +use Elastica\Bulk\Action; +use Elastica\Client; +use Elastica\Document; +use Elastica\Exception\Bulk\ResponseException; +use Elastica\Exception\InvalidException; +use Elastica\Exception\NotFoundException; +use Elastica\Test\Base as BaseTest; +use Elastica\Bulk\Action\AbstractDocument; +use Elastica\Filter\Script; + +class BulkTest extends BaseTest +{ + + public function testSend() + { + $index = $this->_createIndex(); + $type = $index->getType('bulk_test'); + $type2 = $index->getType('bulk_test2'); + $client = $index->getClient(); + + $newDocument1 = $type->createDocument(1, array('name' => 'Mister Fantastic')); + $newDocument2 = new Document(2, array('name' => 'Invisible Woman')); + $newDocument3 = $type->createDocument(3, array('name' => 'The Human Torch')); + $newDocument4 = $type->createDocument(null, array('name' => 'The Thing')); + + $newDocument1->setPercolate('*'); + $newDocument3->setOpType(Document::OP_TYPE_CREATE); + + $documents = array( + $newDocument1, + $newDocument2, + $newDocument3, + $newDocument4 + ); + + $bulk = new Bulk($client); + $bulk->setType($type2); + $bulk->addDocuments($documents); + + $actions = $bulk->getActions(); + + $this->assertInstanceOf('Elastica\Bulk\Action\IndexDocument', $actions[0]); + $this->assertEquals('index', $actions[0]->getOpType()); + $this->assertSame($newDocument1, $actions[0]->getDocument()); + + $this->assertInstanceOf('Elastica\Bulk\Action\IndexDocument', $actions[1]); + $this->assertEquals('index', $actions[1]->getOpType()); + $this->assertSame($newDocument2, $actions[1]->getDocument()); + + $this->assertInstanceOf('Elastica\Bulk\Action\CreateDocument', $actions[2]); + $this->assertEquals('create', $actions[2]->getOpType()); + $this->assertSame($newDocument3, $actions[2]->getDocument()); + + $this->assertInstanceOf('Elastica\Bulk\Action\IndexDocument', $actions[3]); + $this->assertEquals('index', $actions[3]->getOpType()); + $this->assertSame($newDocument4, $actions[3]->getDocument()); + + $data = $bulk->toArray(); + + $expected = array( + array('index' => array('_index' => 'elastica_test', '_type' => 'bulk_test', '_id' => 1, '_percolate' => '*')), + array('name' => 'Mister Fantastic'), + array('index' => array('_id' => 2)), + array('name' => 'Invisible Woman'), + array('create' => array('_index' => 'elastica_test', '_type' => 'bulk_test', '_id' => 3)), + array('name' => 'The Human Torch'), + array('index' => array('_index' => 'elastica_test', '_type' => 'bulk_test')), + array('name' => 'The Thing'), + ); + $this->assertEquals($expected, $data); + + $expected = '{"index":{"_index":"elastica_test","_type":"bulk_test","_id":1,"_percolate":"*"}} +{"name":"Mister Fantastic"} +{"index":{"_id":2}} +{"name":"Invisible Woman"} +{"create":{"_index":"elastica_test","_type":"bulk_test","_id":3}} +{"name":"The Human Torch"} +{"index":{"_index":"elastica_test","_type":"bulk_test"}} +{"name":"The Thing"} +'; + + $expected = str_replace(PHP_EOL, "\n", $expected); + $this->assertEquals($expected, (string)str_replace(PHP_EOL, "\n", (string)$bulk)); + + $response = $bulk->send(); + + $this->assertInstanceOf('Elastica\Bulk\ResponseSet', $response); + + $this->assertTrue($response->isOk()); + $this->assertFalse($response->hasError()); + + foreach ($response as $i => $bulkResponse) { + $this->assertInstanceOf('Elastica\Bulk\Response', $bulkResponse); + $this->assertTrue($bulkResponse->isOk()); + $this->assertFalse($bulkResponse->hasError()); + $this->assertSame($actions[$i], $bulkResponse->getAction()); + } + + $type->getIndex()->refresh(); + $type2->getIndex()->refresh(); + + $this->assertEquals(3, $type->count()); + $this->assertEquals(1, $type2->count()); + + + $bulk = new Bulk($client); + $bulk->addDocument($newDocument3, Action::OP_TYPE_DELETE); + + $data = $bulk->toArray(); + + $expected = array( + array('delete' => array('_index' => 'elastica_test', '_type' => 'bulk_test', '_id' => 3)), + ); + $this->assertEquals($expected, $data); + + $bulk->send(); + + $type->getIndex()->refresh(); + + $this->assertEquals(2, $type->count()); + + try { + $type->getDocument(3); + $this->fail('Document #3 should be deleted'); + } catch (NotFoundException $e) { + $this->assertTrue(true); + } + } + + public function testUnicodeBulkSend() + { + $index = $this->_createIndex(); + $type = $index->getType('bulk_test'); + $type2 = $index->getType('bulk_test2'); + $client = $index->getClient(); + + $newDocument1 = $type->createDocument(1, array('name' => 'Сегодня, я вижу, особенно грустен твой взгляд,')); + $newDocument2 = new Document(2, array('name' => 'И руки особенно тонки, колени обняв.')); + $newDocument3 = $type->createDocument(3, array('name' => 'Послушай: далеко, далеко, на озере Чад / Изысканный бродит жираф.')); + + $documents = array( + $newDocument1, + $newDocument2, + $newDocument3 + ); + + $bulk = new Bulk($client); + $bulk->setType($type2); + $bulk->addDocuments($documents); + + $actions = $bulk->getActions(); + + $this->assertSame($newDocument1, $actions[0]->getDocument()); + $this->assertSame($newDocument2, $actions[1]->getDocument()); + $this->assertSame($newDocument3, $actions[2]->getDocument()); + } + + public function testSetIndexType() + { + $client = new Client(); + $index = $client->getIndex('index'); + $type = $index->getType('type'); + + $index2 = $client->getIndex('index2'); + $type2 = $index2->getType('type2'); + + $bulk = new Bulk($client); + + $this->assertFalse($bulk->hasIndex()); + $this->assertFalse($bulk->hasType()); + + $bulk->setIndex($index); + $this->assertTrue($bulk->hasIndex()); + $this->assertFalse($bulk->hasType()); + $this->assertEquals('index', $bulk->getIndex()); + + $bulk->setType($type2); + $this->assertTrue($bulk->hasIndex()); + $this->assertTrue($bulk->hasType()); + $this->assertEquals('index2', $bulk->getIndex()); + $this->assertEquals('type2', $bulk->getType()); + + $bulk->setType($type); + $this->assertTrue($bulk->hasIndex()); + $this->assertTrue($bulk->hasType()); + $this->assertEquals('index', $bulk->getIndex()); + $this->assertEquals('type', $bulk->getType()); + + $bulk->setIndex($index2); + $this->assertTrue($bulk->hasIndex()); + $this->assertTrue($bulk->hasType()); + $this->assertEquals('index2', $bulk->getIndex()); + $this->assertEquals('type', $bulk->getType()); + } + + public function testAddActions() + { + $client = new Client(); + $bulk = new Bulk($client); + + $action1 = new Action(Action::OP_TYPE_DELETE); + $action1->setIndex('index'); + $action1->setType('type'); + $action1->setId(1); + + $action2 = new Action(Action::OP_TYPE_INDEX); + $action2->setIndex('index'); + $action2->setType('type'); + $action2->setId(1); + $action2->setSource(array('name' => 'Batman')); + + $actions = array( + $action1, + $action2 + ); + + $bulk->addActions($actions); + + $getActions = $bulk->getActions(); + + $this->assertSame($action1, $getActions[0]); + $this->assertSame($action2, $getActions[1]); + } + + public function testAddRawData() + { + $bulk = new Bulk($this->_getClient()); + + $rawData = array( + array('index' => array('_index' => 'test', '_type' => 'user', '_id' => '1')), + array('user' => array('name' => 'hans')), + array('delete' => array('_index' => 'test', '_type' => 'user', '_id' => '2')), + array('delete' => array('_index' => 'test', '_type' => 'user', '_id' => '3')), + array('create' => array('_index' => 'test', '_type' => 'user', '_id' => '4')), + array('user' => array('name' => 'mans')), + array('delete' => array('_index' => 'test', '_type' => 'user', '_id' => '5')), + ); + + $bulk->addRawData($rawData); + + $actions = $bulk->getActions(); + + $this->assertInternalType('array', $actions); + $this->assertEquals(5, count($actions)); + + $this->assertInstanceOf('Elastica\Bulk\Action', $actions[0]); + $this->assertEquals('index', $actions[0]->getOpType()); + $this->assertEquals($rawData[0]['index'], $actions[0]->getMetadata()); + $this->assertTrue($actions[0]->hasSource()); + $this->assertEquals($rawData[1], $actions[0]->getSource()); + + $this->assertInstanceOf('Elastica\Bulk\Action', $actions[1]); + $this->assertEquals('delete', $actions[1]->getOpType()); + $this->assertEquals($rawData[2]['delete'], $actions[1]->getMetadata()); + $this->assertFalse($actions[1]->hasSource()); + + $this->assertInstanceOf('Elastica\Bulk\Action', $actions[2]); + $this->assertEquals('delete', $actions[2]->getOpType()); + $this->assertEquals($rawData[3]['delete'], $actions[2]->getMetadata()); + $this->assertFalse($actions[2]->hasSource()); + + $this->assertInstanceOf('Elastica\Bulk\Action', $actions[3]); + $this->assertEquals('create', $actions[3]->getOpType()); + $this->assertEquals($rawData[4]['create'], $actions[3]->getMetadata()); + $this->assertTrue($actions[3]->hasSource()); + $this->assertEquals($rawData[5], $actions[3]->getSource()); + + $this->assertInstanceOf('Elastica\Bulk\Action', $actions[4]); + $this->assertEquals('delete', $actions[4]->getOpType()); + $this->assertEquals($rawData[6]['delete'], $actions[4]->getMetadata()); + $this->assertFalse($actions[4]->hasSource()); + } + + /** + * @dataProvider invalidRawDataProvider + * @expectedException \Elastica\Exception\InvalidException + */ + public function testInvalidRawData($rawData, $failMessage) + { + $bulk = new Bulk($this->_getClient()); + + $bulk->addRawData($rawData); + + $this->fail($failMessage); + } + + public function invalidRawDataProvider() + { + return array( + array( + array( + array('index' => array('_index' => 'test', '_type' => 'user', '_id' => '1')), + array('user' => array('name' => 'hans')), + array('user' => array('name' => 'mans')), + ), + 'Two sources for one action' + ), + array( + array( + array('index' => array('_index' => 'test', '_type' => 'user', '_id' => '1')), + array('user' => array('name' => 'hans')), + array('upsert' => array('_index' => 'test', '_type' => 'user', '_id' => '2')), + ), + 'Invalid optype for action' + ), + array( + array( + array('user' => array('name' => 'mans')), + ), + 'Source without action' + ), + array( + array( + array(), + ), + 'Empty array' + ), + array( + array( + 'dummy', + ), + 'String as data' + ) + ); + } + + public function testCreateAbstractDocumentWithInvalidData() + { + //Wrong class type + try { + $badDocument = new \stdClass(); + AbstractDocument::create($badDocument); + $this->fail('Tried to create an abstract document with an object that is not a Document or Script, but no exception was thrown'); + } catch (\Exception $e) { + //Excepted exception was thrown. + } + + //Try to create document with a script + try { + $script = new Script(); + AbstractDocument::create($script, AbstractDocument::OP_TYPE_CREATE); + $this->fail('Tried to create an abstract document with a Script, but no exception was thrown'); + } catch (\Exception $e) { + //Excepted exception was thrown. + } + } + + public function testErrorRequest() + { + $index = $this->_createIndex(); + $type = $index->getType('bulk_test'); + $client = $index->getClient(); + + $documents = array( + $type->createDocument(1, array('name' => 'Mister Fantastic')), + $type->createDocument(2, array('name' => 'Invisible Woman')), + $type->createDocument(2, array('name' => 'The Human Torch')), + ); + + $documents[2]->setOpType(Document::OP_TYPE_CREATE); + + $bulk = new Bulk($client); + $bulk->addDocuments($documents); + + try { + $bulk->send(); + $bulk->fail('3rd document create should produce error'); + } catch (ResponseException $e) { + $this->assertContains('DocumentAlreadyExists', $e->getMessage()); + $failures = $e->getFailures(); + $this->assertInternalType('array', $failures); + $this->assertArrayHasKey(0, $failures); + $this->assertContains('DocumentAlreadyExists', $failures[0]); + } + } + + public function testRawDocumentDataRequest() + { + $index = $this->_createIndex(); + $type = $index->getType('bulk_test'); + $client = $index->getClient(); + + $documents = array( + new Document(null, '{"name":"Mister Fantastic"}'), + new Document(null, '{"name":"Invisible Woman"}'), + new Document(null, '{"name":"The Human Torch"}'), + ); + + $bulk = new Bulk($client); + $bulk->addDocuments($documents); + $bulk->setType($type); + + $expectedJson = '{"index":{}} +{"name":"Mister Fantastic"} +{"index":{}} +{"name":"Invisible Woman"} +{"index":{}} +{"name":"The Human Torch"} +'; + $expectedJson = str_replace(PHP_EOL, "\n", $expectedJson); + $this->assertEquals($expectedJson, $bulk->toString()); + + $response = $bulk->send(); + $this->assertTrue($response->isOk()); + + $type->getIndex()->refresh(); + + $response = $type->search(); + $this->assertEquals(3, $response->count()); + + foreach (array("Mister", "Invisible", "Torch") as $name) { + $result = $type->search($name); + $this->assertEquals(1, count($result->getResults())); + } + } + + /** + * @dataProvider udpDataProvider + */ + public function testUdp($clientConfig, $host, $port, $shouldFail = false) + { + if (!function_exists('socket_create')) { + $this->markTestSkipped('Function socket_create() does not exist.'); + } + $client = new Client($clientConfig); + $index = $client->getIndex('elastica_test'); + $index->create(array('index' => array('number_of_shards' => 1, 'number_of_replicas' => 0)), true); + $type = $index->getType('udp_test'); + $client = $index->getClient(); + + $type->setMapping(array('name' => array('type' => 'string'))); + + $docs = array( + $type->createDocument(1, array('name' => 'Mister Fantastic')), + $type->createDocument(2, array('name' => 'Invisible Woman')), + $type->createDocument(3, array('name' => 'The Human Torch')), + $type->createDocument(4, array('name' => 'The Thing')), + $type->createDocument(5, array('name' => 'Mole Man')), + $type->createDocument(6, array('name' => 'The Skrulls')), + ); + + $bulk = new Bulk($client); + $bulk->addDocuments($docs); + + $bulk->sendUdp($host, $port); + + $i = 0; + $limit = 20; + do { + usleep(200000); + } while ($type->count() < 6 && ++$i < $limit); + + if ($shouldFail) { + $this->assertEquals($limit, $i, 'Invalid udp connection data. Test should fail'); + } else { + $this->assertLessThan($limit, $i, 'It took too much time waiting for UDP request result'); + + foreach ($docs as $doc) { + $getDoc = $type->getDocument($doc->getId()); + $this->assertEquals($doc->getData(), $getDoc->getData()); + } + } + } + + public function testUpdate() + { + $index = $this->_createIndex(); + $type = $index->getType('bulk_test'); + $client = $index->getClient(); + + $doc1 = $type->createDocument(1, array('name' => 'John')); + $doc2 = $type->createDocument(2, array('name' => 'Paul')); + $doc3 = $type->createDocument(3, array('name' => 'George')); + $doc4 = $type->createDocument(4, array('name' => 'Ringo')); + $documents = array($doc1, $doc2, $doc3, $doc4); + + //index some documents + $bulk = new Bulk($client); + $bulk->setType($type); + $bulk->addDocuments($documents); + $response = $bulk->send(); + + $this->assertTrue($response->isOk()); + $this->assertFalse($response->hasError()); + + $index->refresh(); + + //test updating via document + $doc2 = $type->createDocument(2, array('name' => 'The Walrus')); + $bulk = new Bulk($client); + $bulk->setType($type); + $updateAction = new \Elastica\Bulk\Action\UpdateDocument($doc2); + $bulk->addAction($updateAction); + $response = $bulk->send(); + + $this->assertTrue($response->isOk()); + $this->assertFalse($response->hasError()); + + $index->refresh(); + + $doc = $type->getDocument(2); + $docData = $doc->getData(); + $this->assertEquals('The Walrus', $docData['name']); + + //test updating via script + $script = new \Elastica\Script('ctx._source.name += param1;', array('param1' => ' was Paul'), null, 2); + $doc2 = new Document(); + $script->setUpsert($doc2); + $updateAction = Action\AbstractDocument::create($script, Action::OP_TYPE_UPDATE); + $bulk = new Bulk($client); + $bulk->setType($type); + $bulk->addAction($updateAction); + $response = $bulk->send(); + + $this->assertTrue($response->isOk()); + $this->assertFalse($response->hasError()); + + $index->refresh(); + + $doc2 = $type->getDocument(2); + $this->assertEquals('The Walrus was Paul', $doc2->name); + + //test upsert + $script = new \Elastica\Script('ctx._scource.counter += count', array('count' => 1), null, 5); + $doc = new Document('', array('counter' => 1)); + $script->setUpsert($doc); + $updateAction = Action\AbstractDocument::create($script, Action::OP_TYPE_UPDATE); + $bulk = new Bulk($client); + $bulk->setType($type); + $bulk->addAction($updateAction); + $response = $bulk->send(); + + $this->assertTrue($response->isOk()); + $this->assertFalse($response->hasError()); + + $index->refresh(); + $doc = $type->getDocument(5); + $this->assertEquals(1, $doc->counter); + + //test doc_as_upsert + $doc = new \Elastica\Document(6, array('test' => 'test')); + $doc->setDocAsUpsert(true); + $updateAction = Action\AbstractDocument::create($doc, Action::OP_TYPE_UPDATE); + $bulk = new Bulk($client); + $bulk->setType($type); + $bulk->addAction($updateAction); + $response = $bulk->send(); + + $this->assertTrue($response->isOk()); + $this->assertFalse($response->hasError()); + + $index->refresh(); + $doc = $type->getDocument(6); + $this->assertEquals('test', $doc->test); + + //test doc_as_upsert with set of documents (use of addDocuments) + $doc1 = new \Elastica\Document(7, array('test' => 'test1')); + $doc1->setDocAsUpsert(true); + $doc2 = new \Elastica\Document(8, array('test' => 'test2')); + $doc2->setDocAsUpsert(true); + $docs = array($doc1, $doc2); + $bulk = new Bulk($client); + $bulk->setType($type); + $bulk->addDocuments($docs, \Elastica\Bulk\Action::OP_TYPE_UPDATE); + $response = $bulk->send(); + + $this->assertTrue($response->isOk()); + $this->assertFalse($response->hasError()); + + $index->refresh(); + $doc = $type->getDocument(7); + $this->assertEquals('test1', $doc->test); + $doc = $type->getDocument(8); + $this->assertEquals('test2', $doc->test); + + //test updating via document with json string as data + $doc3 = $type->createDocument(2); + $bulk = new Bulk($client); + $bulk->setType($type); + $doc3->setData('{"name" : "Paul it is"}'); + $updateAction = new \Elastica\Bulk\Action\UpdateDocument($doc3); + $bulk->addAction($updateAction); + $response = $bulk->send(); + + $this->assertTrue($response->isOk()); + $this->assertFalse($response->hasError()); + + $index->refresh(); + + $doc = $type->getDocument(2); + $docData = $doc->getData(); + $this->assertEquals('Paul it is', $docData['name']); + + $index->delete(); + } + + public function testGetPath() + { + $client = $this->_getClient(); + $bulk = new Bulk($client); + + $this->assertEquals('_bulk', $bulk->getPath()); + + $indexName = 'testIndex'; + + $bulk->setIndex($indexName); + $this->assertEquals($indexName . '/_bulk', $bulk->getPath()); + + $typeName = 'testType'; + $bulk->setType($typeName); + $this->assertEquals($indexName . '/' . $typeName . '/_bulk', $bulk->getPath()); + } + + public function testRetry() + { + $index = $this->_createIndex(); + $type = $index->getType('bulk_test'); + $client = $index->getClient(); + + $doc1 = $type->createDocument(1, array('name' => 'Mister Fantastic')); + $doc1->setOpType(Action::OP_TYPE_UPDATE); + $doc1->setRetryOnConflict(5); + + $bulk = new Bulk($client); + $bulk->addDocument($doc1); + + $actions = $bulk->getActions(); + + $metadata = $actions[0]->getMetadata(); + $this->assertEquals(5, $metadata[ '_retry_on_conflict' ]); + + $script = new \Elastica\Script( '' ); + $script->setRetryOnConflict(5); + + $bulk = new Bulk($client); + $bulk->addScript($script); + + $actions = $bulk->getActions(); + + $metadata = $actions[0]->getMetadata(); + $this->assertEquals(5, $metadata[ '_retry_on_conflict' ]); + } + + public function udpDataProvider() + { + return array( + array( + array(), + null, + null + ), + array( + array(), + 'localhost', + null + ), + array( + array(), + null, + 9700 + ), + array( + array(), + 'localhost', + 9700 + ), + array( + array( + 'udp' => array( + 'host' => 'localhost', + 'port' => 9700, + ) + ), + null, + null + ), + array( + array( + 'udp' => array( + 'host' => 'localhost', + 'port' => 9800, + ) + ), + 'localhost', + 9700 + ), + array( + array( + 'udp' => array( + 'host' => 'localhost', + 'port' => 9800, + ) + ), + null, + null, + true + ), + array( + array(), + 'localhost', + 9800, + true + ), + ); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/ClientTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/ClientTest.php new file mode 100644 index 00000000..94ee2ead --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/ClientTest.php @@ -0,0 +1,1008 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Client; +use Elastica\Connection; +use Elastica\Document; +use Elastica\Exception\ClientException; +use Elastica\Exception\Connection\HttpException; +use Elastica\Script; +use Elastica\Index; +use Elastica\Request; +use Elastica\Test\Base as BaseTest; +use Elastica\Type; + +class ClientTest extends BaseTest +{ + + public function testConstruct() + { + $client = $this->_getClient(); + $this->assertCount(1, $client->getConnections()); + } + + public function testConnectionsArray() + { + // Creates a new index 'xodoa' and a type 'user' inside this index + $client = new Client(array('connections' => array(array('host' => 'localhost', 'port' => 9200)))); + $index = $client->getIndex('elastica_test1'); + $index->create(array(), true); + + $type = $index->getType('user'); + + // Adds 1 document to the index + $doc1 = new Document(1, + array('username' => 'hans', 'test' => array('2', '3', '5')) + ); + $type->addDocument($doc1); + + // Adds a list of documents with _bulk upload to the index + $docs = array(); + $docs[] = new Document(2, + array('username' => 'john', 'test' => array('1', '3', '6')) + ); + $docs[] = new Document(3, + array('username' => 'rolf', 'test' => array('2', '3', '7')) + ); + $type->addDocuments($docs); + + // Refresh index + $index->refresh(); + + $resultSet = $type->search('rolf'); + } + + public function testTwoServersSame() + { + // Creates a new index 'xodoa' and a type 'user' inside this index + $client = new Client(array('connections' => array( + array('host' => 'localhost', 'port' => 9200), + array('host' => 'localhost', 'port' => 9200), + ))); + $index = $client->getIndex('elastica_test1'); + $index->create(array(), true); + + $type = $index->getType('user'); + + // Adds 1 document to the index + $doc1 = new Document(1, + array('username' => 'hans', 'test' => array('2', '3', '5')) + ); + $type->addDocument($doc1); + + // Adds a list of documents with _bulk upload to the index + $docs = array(); + $docs[] = new Document(2, + array('username' => 'john', 'test' => array('1', '3', '6')) + ); + $docs[] = new Document(3, + array('username' => 'rolf', 'test' => array('2', '3', '7')) + ); + $type->addDocuments($docs); + + // Refresh index + $index->refresh(); + + $resultSet = $type->search('rolf'); + } + + public function testConnectionParamsArePreparedForConnectionsOption() + { + $client = new Client(array('connections' => array(array('url' => 'https://localhost:9200')))); + $connection = $client->getConnection(); + + $this->assertEquals('https://localhost:9200', $connection->getConfig('url')); + } + + public function testConnectionParamsArePreparedForServersOption() + { + $client = new Client(array('servers' => array(array('url' => 'https://localhost:9200')))); + $connection = $client->getConnection(); + + $this->assertEquals('https://localhost:9200', $connection->getConfig('url')); + } + + public function testConnectionParamsArePreparedForDefaultOptions() + { + $client = new Client(array('url' => 'https://localhost:9200')); + $connection = $client->getConnection(); + + $this->assertEquals('https://localhost:9200', $connection->getConfig('url')); + } + + public function testBulk() + { + $client = $this->_getClient(); + + $params = array( + array('index' => array('_index' => 'test', '_type' => 'user', '_id' => '1')), + array('user' => array('name' => 'hans')), + array('index' => array('_index' => 'test', '_type' => 'user', '_id' => '2')), + array('user' => array('name' => 'peter')), + ); + + $client->bulk($params); + } + + public function testOptimizeAll() + { + $client = $this->_getClient(); + $response = $client->optimizeAll(); + + $this->assertFalse($response->hasError()); + } + + /** + * @expectedException \Elastica\Exception\InvalidException + */ + public function testAddDocumentsEmpty() + { + $client = $this->_getClient(); + $client->addDocuments(array()); + } + + /** + * Test bulk operations on Index + */ + public function testBulkIndex() + { + $index = $this->_getClient()->getIndex('cryptocurrencies'); + + $anonCoin = new Document(1, array('name' => 'anoncoin'), 'altcoin'); + $ixCoin = new Document(2, array('name' => 'ixcoin'), 'altcoin'); + + $index->addDocuments(array($anonCoin, $ixCoin)); + + $this->assertEquals('anoncoin', $index->getType('altcoin')->getDocument(1)->get('name')); + $this->assertEquals('ixcoin', $index->getType('altcoin')->getDocument(2)->get('name')); + + $index->updateDocuments(array( + new Document(1, array('name' => 'AnonCoin'), 'altcoin'), + new Document(2, array('name' => 'iXcoin'), 'altcoin') + )); + + $this->assertEquals('AnonCoin', $index->getType('altcoin')->getDocument(1)->get('name')); + $this->assertEquals('iXcoin', $index->getType('altcoin')->getDocument(2)->get('name')); + + $ixCoin->setIndex(null); // Make sure the index gets set properly if missing + $index->deleteDocuments(array($anonCoin, $ixCoin)); + + $this->setExpectedException('Elastica\Exception\NotFoundException'); + $index->getType('altcoin')->getDocument(1); + $index->getType('altcoin')->getDocument(2); + } + + /** + * Test bulk operations on Type + */ + public function testBulkType() + { + $type = $this->_getClient()->getIndex('cryptocurrencies')->getType('altcoin'); + + $liteCoin = new Document(1, array('name' => 'litecoin')); + $nameCoin = new Document(2, array('name' => 'namecoin')); + + $type->addDocuments(array($liteCoin, $nameCoin)); + + $this->assertEquals('litecoin', $type->getDocument(1)->get('name')); + $this->assertEquals('namecoin', $type->getDocument(2)->get('name')); + + $type->updateDocuments(array( + new Document(1, array('name' => 'LiteCoin')), + new Document(2, array('name' => 'NameCoin')) + )); + + $this->assertEquals('LiteCoin', $type->getDocument(1)->get('name')); + $this->assertEquals('NameCoin', $type->getDocument(2)->get('name')); + + $nameCoin->setType(null); // Make sure the type gets set properly if missing + $type->deleteDocuments(array($liteCoin, $nameCoin)); + + $this->setExpectedException('Elastica\Exception\NotFoundException'); + $type->getDocument(1); + $type->getDocument(2); + } + + public function testUpdateDocuments() + { + $indexName = 'test'; + $typeName = 'people'; + + $client = $this->_getClient(); + $type = $client->getIndex($indexName)->getType($typeName); + + $initialValue = 28; + $modifiedValue = 27; + + $doc1 = new Document( + 1, + array('name' => 'hans', 'age' => $initialValue), + $typeName, + $indexName + ); + $doc2 = new Document( + 2, + array('name' => 'anna', 'age' => $initialValue), + $typeName, + $indexName + ); + $data = array($doc1, $doc2); + $client->addDocuments($data); + + foreach ($data as $i => $doc) { + $data[$i]->age = $modifiedValue; + } + $client->updateDocuments($data); + + $docData1 = $type->getDocument(1)->getData(); + $docData2 = $type->getDocument(2)->getData(); + + $this->assertEquals($modifiedValue, $docData1['age']); + $this->assertEquals($modifiedValue, $docData2['age']); + } + + /** + * Test deleteIds method using string parameters + * + * This test ensures that the deleteIds method of + * the \Elastica\Client can properly accept and use + * an $index parameter and $type parameter that are + * strings + * + * This test is a bit more verbose than just sending the + * values to deleteIds and checking for exceptions or + * warnings. + * + * It will add a document, search for it, then delete it + * using the parameter types we are interested in, and then + * re-search to verify that they have been deleted + */ + public function testDeleteIdsIdxStringTypeString() + { + $data = array('username' => 'hans'); + $userSearch = 'username:hans'; + + $index = $this->_createIndex('test', true, 2); + + // Create the index, deleting it first if it already exists + $index->create(array(), true); + $type = $index->getType('user'); + + // Adds 1 document to the index + $doc = new Document(null, $data); + $doc->setRouting(1); + $result = $type->addDocument($doc); + + // Refresh index + $index->refresh(); + + $resultData = $result->getData(); + $ids = array($resultData['_id']); + + // Check to make sure the document is in the index + $resultSet = $type->search($userSearch); + $totalHits = $resultSet->getTotalHits(); + $this->assertEquals(1, $totalHits); + + // And verify that the variables we are doing to send to + // deleteIds are the type we are testing for + $idxString = $index->getName(); + $typeString = $type->getName(); + $this->assertEquals(true, is_string($idxString)); + $this->assertEquals(true, is_string($typeString)); + + // Try to delete doc with a routing value which hashes to + // a different shard then the id. + $resp = $index->getClient()->deleteIds($ids, $index, $type, 2); + + // Refresh the index + $index->refresh(); + + // Research the index to verify that the items are still there + $resultSet = $type->search($userSearch); + $totalHits = $resultSet->getTotalHits(); + $this->assertEquals(1, $totalHits); + + // Using the existing $index and $type variables which + // are \Elastica\Index and \Elastica\Type objects respectively + $resp = $index->getClient()->deleteIds($ids, $index, $type, 1); + + // Refresh the index to clear out deleted ID information + $index->refresh(); + + // Research the index to verify that the items have been deleted + $resultSet = $type->search($userSearch); + $totalHits = $resultSet->getTotalHits(); + $this->assertEquals(0, $totalHits); + } + + /** + * Test deleteIds method using string parameter for $index + * and object parameter for $type + * + * This test ensures that the deleteIds method of + * the \Elastica\Client can properly accept and use + * an $index parameter that is a string and a $type + * parameter that is of type \Elastica\Type + * + * This test is a bit more verbose than just sending the + * values to deleteIds and checking for exceptions or + * warnings. + * + * It will add a document, search for it, then delete it + * using the parameter types we are interested in, and then + * re-search to verify that they have been deleted + */ + public function testDeleteIdsIdxStringTypeObject() + { + $data = array('username' => 'hans'); + $userSearch = 'username:hans'; + + $index = $this->_createIndex(); + + // Create the index, deleting it first if it already exists + $index->create(array(), true); + $type = $index->getType('user'); + + // Adds 1 document to the index + $doc = new Document(null, $data); + $result = $type->addDocument($doc); + + // Refresh index + $index->refresh(); + + $resultData = $result->getData(); + $ids = array($resultData['_id']); + + // Check to make sure the document is in the index + $resultSet = $type->search($userSearch); + $totalHits = $resultSet->getTotalHits(); + $this->assertEquals(1, $totalHits); + + // And verify that the variables we are doing to send to + // deleteIds are the type we are testing for + $idxString = $index->getName(); + $this->assertEquals(true, is_string($idxString)); + $this->assertEquals(true, ($type instanceof Type)); + + // Using the existing $index and $type variables which + // are \Elastica\Index and \Elastica\Type objects respectively + $resp = $index->getClient()->deleteIds($ids, $index, $type); + + // Refresh the index to clear out deleted ID information + $index->refresh(); + + // Research the index to verify that the items have been deleted + $resultSet = $type->search($userSearch); + $totalHits = $resultSet->getTotalHits(); + $this->assertEquals(0, $totalHits); + } + + /** + * Test deleteIds method using object parameter for $index + * and string parameter for $type + * + * This test ensures that the deleteIds method of + * the \Elastica\Client can properly accept and use + * an $index parameter that is of type Elasitca_Index + * and a $type parameter that is a string + * + * This test is a bit more verbose than just sending the + * values to deleteIds and checking for exceptions or + * warnings. + * + * It will add a document, search for it, then delete it + * using the parameter types we are interested in, and then + * re-search to verify that they have been deleted + */ + public function testDeleteIdsIdxObjectTypeString() + { + $data = array('username' => 'hans'); + $userSearch = 'username:hans'; + + $index = $this->_createIndex(); + + // Create the index, deleting it first if it already exists + $index->create(array(), true); + $type = $index->getType('user'); + + // Adds 1 document to the index + $doc = new Document(null, $data); + $result = $type->addDocument($doc); + + // Refresh index + $index->refresh(); + + $resultData = $result->getData(); + $ids = array($resultData['_id']); + + // Check to make sure the document is in the index + $resultSet = $type->search($userSearch); + $totalHits = $resultSet->getTotalHits(); + $this->assertEquals(1, $totalHits); + + // And verify that the variables we are doing to send to + // deleteIds are the type we are testing for + $typeString = $type->getName(); + $this->assertEquals(true, ($index instanceof Index)); + $this->assertEquals(true, is_string($typeString)); + + // Using the existing $index and $type variables which + // are \Elastica\Index and \Elastica\Type objects respectively + $resp = $index->getClient()->deleteIds($ids, $index, $type); + + // Refresh the index to clear out deleted ID information + $index->refresh(); + + // Research the index to verify that the items have been deleted + $resultSet = $type->search($userSearch); + $totalHits = $resultSet->getTotalHits(); + $this->assertEquals(0, $totalHits); + } + + /** + * Test deleteIds method using object parameter for $index + * and object parameter for $type + * + * This test ensures that the deleteIds method of + * the \Elastica\Client can properly accept and use + * an $index parameter that is an object and a $type + * parameter that is of type \Elastica\Type + * + * This test is a bit more verbose than just sending the + * values to deleteIds and checking for exceptions or + * warnings. + * + * It will add a document, search for it, then delete it + * using the parameter types we are interested in, and then + * re-search to verify that they have been deleted + */ + public function testDeleteIdsIdxObjectTypeObject() + { + $data = array('username' => 'hans'); + $userSearch = 'username:hans'; + + $index = $this->_createIndex(); + + // Create the index, deleting it first if it already exists + $index->create(array(), true); + $type = $index->getType('user'); + + // Adds 1 document to the index + $doc = new Document(null, $data); + $result = $type->addDocument($doc); + + // Refresh index + $index->refresh(); + + $resultData = $result->getData(); + $ids = array($resultData['_id']); + + // Check to make sure the document is in the index + $resultSet = $type->search($userSearch); + $totalHits = $resultSet->getTotalHits(); + $this->assertEquals(1, $totalHits); + + // And verify that the variables we are doing to send to + // deleteIds are the type we are testing for + $this->assertEquals(true, ($index instanceof Index)); + $this->assertEquals(true, ($type instanceof Type)); + + // Using the existing $index and $type variables which + // are \Elastica\Index and \Elastica\Type objects respectively + $resp = $index->getClient()->deleteIds($ids, $index, $type); + + // Refresh the index to clear out deleted ID information + $index->refresh(); + + // Research the index to verify that the items have been deleted + $resultSet = $type->search($userSearch); + $totalHits = $resultSet->getTotalHits(); + $this->assertEquals(0, $totalHits); + } + + public function testOneInvalidConnection() + { + $client = $this->_getClient(); + + // First connection work, second should not work + $connection1 = new Connection(array('port' => '9100', 'timeout' => 2)); + $connection2 = new Connection(array('port' => '9200', 'timeout' => 2)); + + $client->setConnections(array($connection1, $connection2)); + + $client->request('_status', Request::GET); + + $connections = $client->getConnections(); + + // two connections are setup + $this->assertEquals(2, count($connections)); + + // One connection has to be disabled + $this->assertTrue($connections[0]->isEnabled() == false || $connections[1]->isEnabled() == false); + } + + public function testTwoInvalidConnection() + { + $client = $this->_getClient(); + + // First connection work, second should not work + $connection1 = new Connection(array('port' => '9101', 'timeout' => 2)); + $connection2 = new Connection(array('port' => '9102', 'timeout' => 2)); + + $client->setConnections(array($connection1, $connection2)); + + try { + $client->request('_status', Request::GET); + $this->fail('Should throw exception as no connection valid'); + } catch (HttpException $e) { + $this->assertTrue(true); + } + + $connections = $client->getConnections(); + + // two connections are setup + $this->assertEquals(2, count($connections)); + + // One connection has to be disabled + $this->assertTrue($connections[0]->isEnabled() == false || $connections[1]->isEnabled() == false); + } + + /** + * Tests if the callback works in case a connection is down + */ + public function testCallback() + { + $count = 0; + $object = $this; + + // Callback function which verifies that disabled connection objects are returned + $callback = function($connection, $exception, $client) use (&$object, &$count) { + $object->assertInstanceOf('Elastica\Connection', $connection); + $object->assertInstanceOf('Elastica\Exception\ConnectionException', $exception); + $object->assertInstanceOf('Elastica\Client', $client); + $object->assertFalse($connection->isEnabled()); + $count++; + }; + + $client = new Client(array(), $callback); + + // First connection work, second should not work + $connection1 = new Connection(array('port' => '9101', 'timeout' => 2)); + $connection2 = new Connection(array('port' => '9102', 'timeout' => 2)); + + $client->setConnections(array($connection1, $connection2)); + + $this->assertEquals(0, $count); + + try { + $client->request('_status', Request::GET); + $this->fail('Should throw exception as no connection valid'); + } catch (HttpException $e) { + $this->assertTrue(true); + } + + // Two disabled connections (from closure call) + $this->assertEquals(2, $count); + } + + public function testUrlConstructor() + { + $url = 'http://localhost:9200/'; + + // Url should overwrite invalid host + $client = new Client(array('url' => $url, 'port' => '9101', 'timeout' => 2)); + + $response = $client->request('_status'); + $this->assertInstanceOf('Elastica\Response', $response); + } + + public function testUpdateDocumentByDocument() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + $client = $index->getClient(); + + $newDocument = new Document(1, array('field1' => 'value1', 'field2' => 'value2')); + $type->addDocument($newDocument); + + $updateDocument = new Document(1, array('field2' => 'value2changed', 'field3' => 'value3added')); + $client->updateDocument(1, $updateDocument, $index->getName(), $type->getName()); + + $document = $type->getDocument(1); + + $this->assertInstanceOf('Elastica\Document', $document); + $data = $document->getData(); + $this->assertArrayHasKey('field1', $data); + $this->assertEquals('value1', $data['field1']); + $this->assertArrayHasKey('field2', $data); + $this->assertEquals('value2changed', $data['field2']); + $this->assertArrayHasKey('field3', $data); + $this->assertEquals('value3added', $data['field3']); + } + + public function testUpdateDocumentByScript() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + $client = $index->getClient(); + + $newDocument = new Document(1, array('field1' => 'value1', 'field2' => 10, 'field3' => 'should be removed', 'field4' => 'should be changed')); + $type->addDocument($newDocument); + + $script = new Script('ctx._source.field2 += 5; ctx._source.remove("field3"); ctx._source.field4 = "changed"'); + $client->updateDocument(1, $script, $index->getName(), $type->getName()); + + $document = $type->getDocument(1); + + $this->assertInstanceOf('Elastica\Document', $document); + $data = $document->getData(); + $this->assertArrayHasKey('field1', $data); + $this->assertEquals('value1', $data['field1']); + $this->assertArrayHasKey('field2', $data); + $this->assertEquals(15, $data['field2']); + $this->assertArrayHasKey('field2', $data); + $this->assertEquals('changed', $data['field4']); + $this->assertArrayNotHasKey('field3', $data); + } + + public function testUpdateDocumentByScriptWithUpsert() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + $client = $index->getClient(); + + $script = new Script('ctx._source.field2 += count; ctx._source.remove("field3"); ctx._source.field4 = "changed"'); + $script->setParam('count', 5); + $script->setUpsert(array('field1' => 'value1', 'field2' => 10, 'field3' => 'should be removed', 'field4' => 'value4')); + + // should use document fields because document does not exist, script is avoided + $client->updateDocument(1, $script, $index->getName(), $type->getName(), array('fields' => '_source')); + + $document = $type->getDocument(1); + + $this->assertInstanceOf('Elastica\Document', $document); + $data = $document->getData(); + $this->assertArrayHasKey('field1', $data); + $this->assertEquals('value1', $data['field1']); + $this->assertArrayHasKey('field2', $data); + $this->assertEquals(10, $data['field2']); + $this->assertArrayHasKey('field3', $data); + $this->assertEquals('should be removed', $data['field3']); + $this->assertArrayHasKey('field4', $data); + $this->assertEquals('value4', $data['field4']); + + // should use script because document exists, document values are ignored + $client->updateDocument(1, $script, $index->getName(), $type->getName(), array('fields' => '_source')); + + $document = $type->getDocument(1); + + $this->assertInstanceOf('Elastica\Document', $document); + $data = $document->getData(); + $this->assertArrayHasKey('field1', $data); + $this->assertEquals('value1', $data['field1']); + $this->assertArrayHasKey('field2', $data); + $this->assertEquals(15, $data['field2']); + $this->assertArrayHasKey('field4', $data); + $this->assertEquals('changed', $data['field4']); + $this->assertArrayNotHasKey('field3', $data); + } + + public function testUpdateDocumentByRawData() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + $client = $index->getClient(); + + $newDocument = new Document(1, array('field1' => 'value1')); + $type->addDocument($newDocument); + + $rawData = array( + 'doc' => array( + 'field2' => 'value2', + ) + ); + + $response = $client->updateDocument(1, $rawData, $index->getName(), $type->getName(), array('retry_on_conflict' => 1)); + $this->assertTrue($response->isOk()); + + $document = $type->getDocument(1); + + $this->assertInstanceOf('Elastica\Document', $document); + $data = $document->getData(); + $this->assertArrayHasKey('field1', $data); + $this->assertEquals('value1', $data['field1']); + $this->assertArrayHasKey('field2', $data); + $this->assertEquals('value2', $data['field2']); + } + + public function testUpdateDocumentByDocumentWithUpsert() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + $client = $index->getClient(); + + $newDocument = new Document(1, array('field1' => 'value1updated', 'field2' => 'value2updated')); + $upsert = new Document(1, array('field1' => 'value1', 'field2' => 'value2')); + $newDocument->setUpsert($upsert); + $client->updateDocument(1, $newDocument, $index->getName(), $type->getName(), array('fields' => '_source')); + + $document = $type->getDocument(1); + $this->assertInstanceOf('Elastica\Document', $document); + $data = $document->getData(); + $this->assertArrayHasKey('field1', $data); + $this->assertEquals('value1', $data['field1']); + $this->assertArrayHasKey('field2', $data); + $this->assertEquals('value2', $data['field2']); + + // should use update document because document exists, upsert document values are ignored + $client->updateDocument(1, $newDocument, $index->getName(), $type->getName(), array('fields' => '_source')); + + $document = $type->getDocument(1); + $this->assertInstanceOf('Elastica\Document', $document); + $data = $document->getData(); + $this->assertArrayHasKey('field1', $data); + $this->assertEquals('value1updated', $data['field1']); + $this->assertArrayHasKey('field2', $data); + $this->assertEquals('value2updated', $data['field2']); + } + + public function testDocAsUpsert() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + $client = $index->getClient(); + + //Confirm document one does not exist + try { + $document = $type->getDocument(1); + $this->fail('Exception was not thrown. Maybe the document exists?'); + } catch (\Exception $e) { + //Ignore the exception because we expect the document to not exist. + } + + $newDocument = new Document(1, array('field1' => 'value1', 'field2' => 'value2')); + $newDocument->setDocAsUpsert(true); + $client->updateDocument(1, $newDocument, $index->getName(), $type->getName(), array('fields' => '_source')); + + $document = $type->getDocument(1); + $this->assertInstanceOf('Elastica\Document', $document); + $data = $document->getData(); + $this->assertArrayHasKey('field1', $data); + $this->assertEquals('value1', $data['field1']); + $this->assertArrayHasKey('field2', $data); + $this->assertEquals('value2', $data['field2']); + } + + public function testUpdateWithInvalidType() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + $client = $index->getClient(); + + //Try to update using a stdClass object + $badDocument = new \stdClass(); + + try { + $client->updateDocument(1, $badDocument, $index->getName(), $type->getName()); + $this->fail('Tried to update using an object that is not a Document or a Script but no exception was thrown'); + } catch (\Exception $e) { + //Good. An exception was thrown. + } + } + + public function testDeleteDocuments() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + $client = $index->getClient(); + + $docs = array( + new Document(1, array('field' => 'value1'), $type, $index), + new Document(2, array('field' => 'value2'), $type, $index), + new Document(3, array('field' => 'value3'), $type, $index), + ); + + $response = $client->addDocuments($docs); + + $this->assertInstanceOf('Elastica\Bulk\ResponseSet', $response); + $this->assertEquals(3, count($response)); + $this->assertTrue($response->isOk()); + $this->assertFalse($response->hasError()); + $this->assertEquals('', $response->getError()); + + $index->refresh(); + + $this->assertEquals(3, $type->count()); + + $deleteDocs = array( + $docs[0], + $docs[2], + ); + + $response = $client->deleteDocuments($deleteDocs); + + $this->assertInstanceOf('Elastica\Bulk\ResponseSet', $response); + $this->assertEquals(2, count($response)); + $this->assertTrue($response->isOk()); + $this->assertFalse($response->hasError()); + $this->assertEquals('', $response->getError()); + + $index->refresh(); + + $this->assertEquals(1, $type->count()); + } + + public function testLastRequestResponse() + { + $client = new Client(); + $response = $client->request('_status'); + + $this->assertInstanceOf('Elastica\Response', $response); + + $lastRequest = $client->getLastRequest(); + + $this->assertInstanceOf('Elastica\Request', $lastRequest); + $this->assertEquals('_status', $lastRequest->getPath()); + + $lastResponse = $client->getLastResponse(); + $this->assertInstanceOf('Elastica\Response', $lastResponse); + $this->assertSame($response, $lastResponse); + } + + public function testUpdateDocumentPopulateFields() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + $client = $index->getClient(); + + $newDocument = new Document(1, array('field1' => 'value1', 'field2' => 10, 'field3' => 'should be removed', 'field4' => 'value4')); + $newDocument->setAutoPopulate(); + $type->addDocument($newDocument); + + $script = new Script('ctx._source.field2 += count; ctx._source.remove("field3"); ctx._source.field4 = "changed"'); + $script->setParam('count', 5); + $script->setUpsert($newDocument); + + $client->updateDocument( + 1, + $script, + $index->getName(), + $type->getName(), + array('fields' => '_source') + ); + + $data = $type->getDocument(1)->getData(); + $this->assertArrayHasKey('field1', $data); + $this->assertEquals('value1', $data['field1']); + $this->assertArrayHasKey('field2', $data); + $this->assertEquals(15, $data['field2']); + $this->assertArrayHasKey('field4', $data); + $this->assertEquals('changed', $data['field4']); + $this->assertArrayNotHasKey('field3', $data); + + $script = new Script('ctx._source.field2 += count; ctx._source.remove("field4"); ctx._source.field1 = field1;'); + $script->setParam('count', 5); + $script->setParam('field1', 'updated'); + $script->setUpsert($newDocument); + + $client->updateDocument( + 1, + $script, + $index->getName(), + $type->getName(), + array('fields' => 'field2,field4') + ); + + $document = $type->getDocument(1); + + $data = $document->getData(); + + $this->assertArrayHasKey('field1', $data); + $this->assertEquals('updated', $data['field1']); + $this->assertArrayHasKey('field2', $data); + $this->assertEquals(20, $data['field2']); + $this->assertArrayNotHasKey('field3', $data); + $this->assertArrayNotHasKey('field4', $data); + } + + public function testAddDocumentsWithoutIds() + { + $docs = array(); + for ($i = 0; $i < 10; $i++) { + $docs[] = new Document(null, array('pos' => $i)); + } + + foreach ($docs as $doc) { + $this->assertFalse($doc->hasId()); + } + + $index = $this->_createIndex(); + + $client = $index->getClient(); + $client->setConfigValue('document', array('autoPopulate' => true)); + + $type = $index->getType('pos'); + $type->addDocuments($docs); + + foreach ($docs as $doc) { + $this->assertTrue($doc->hasId()); + $this->assertTrue($doc->hasVersion()); + $this->assertEquals(1, $doc->getVersion()); + } + } + + public function testConfigValue() + { + $config = array( + 'level1' => array( + 'level2' => array( + 'level3' => 'value3', + ), + 'level21' => 'value21' + ), + 'level11' => 'value11' + ); + $client = new Client($config); + + $this->assertNull($client->getConfigValue('level12')); + $this->assertFalse($client->getConfigValue('level12', false)); + $this->assertEquals(10, $client->getConfigValue('level12', 10)); + + $this->assertEquals('value11', $client->getConfigValue('level11')); + $this->assertNotNull($client->getConfigValue('level11')); + $this->assertNotEquals(false, $client->getConfigValue('level11', false)); + $this->assertNotEquals(10, $client->getConfigValue('level11', 10)); + + $this->assertEquals('value3', $client->getConfigValue(array('level1', 'level2', 'level3'))); + $this->assertInternalType('array', $client->getConfigValue(array('level1', 'level2'))); + } + + + public function testArrayQuery() + { + $client = new Client(); + + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('test'); + $type->addDocument(new Document(1, array('username' => 'ruflin'))); + $index->refresh(); + + $query = array( + 'query' => array( + 'query_string' => array( + 'query' => 'ruflin', + ) + ) + ); + + $path = $index->getName() . '/' . $type->getName() . '/_search'; + + $response = $client->request($path, Request::GET, $query); + $responseArray = $response->getData(); + + $this->assertEquals(1, $responseArray['hits']['total']); + } + + public function testJSONQuery() + { + $client = new Client(); + + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('test'); + $type->addDocument(new Document(1, array('username' => 'ruflin'))); + $index->refresh(); + + $query = '{"query":{"query_string":{"query":"ruflin"}}}'; + + $path = $index->getName() . '/' . $type->getName() . '/_search'; + + $response = $client->request($path, Request::GET, $query); + $responseArray = $response->getData(); + + $this->assertEquals(1, $responseArray['hits']['total']); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Cluster/Health/IndexTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Cluster/Health/IndexTest.php new file mode 100644 index 00000000..085ac13a --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Cluster/Health/IndexTest.php @@ -0,0 +1,113 @@ +<?php + +namespace Elastica\Test\Cluster\Health; + +use Elastica\Cluster\Health\Index as HealthIndex; +use Elastica\Test\Base as BaseTest; + +class IndexTest extends BaseTest +{ + /** + * @var \Elastica\Cluster\Health\Index + */ + protected $_index; + + public function setUp() + { + $data = array( + "status" => "yellow", + "number_of_shards" => 1, + "number_of_replicas" => 2, + "active_primary_shards" => 3, + "active_shards" => 4, + "relocating_shards" => 5, + "initializing_shards" => 6, + "unassigned_shards" => 7, + "shards" => array( + "0" => array( + "status" => "yellow", + "primary_active" => false, + "active_shards" => 0, + "relocating_shards" => 1, + "initializing_shards" => 0, + "unassigned_shards" => 1 + ), + "1" => array( + "status" => "yellow", + "primary_active" => true, + "active_shards" => 1, + "relocating_shards" => 0, + "initializing_shards" => 0, + "unassigned_shards" => 1 + ), + "2" => array( + "status" => "green", + "primary_active" => true, + "active_shards" => 1, + "relocating_shards" => 0, + "initializing_shards" => 0, + "unassigned_shards" => 0, + ), + ) + ); + + $this->_index = new HealthIndex('test', $data); + } + + public function testGetName() + { + $this->assertEquals('test', $this->_index->getName()); + } + + public function testGetStatus() + { + $this->assertEquals('yellow', $this->_index->getStatus()); + } + + public function testGetNumberOfShards() + { + $this->assertEquals(1, $this->_index->getNumberOfShards()); + } + + public function testGetNumberOfReplicas() + { + $this->assertEquals(2, $this->_index->getNumberOfReplicas()); + } + + public function testGetActivePrimaryShards() + { + $this->assertEquals(3, $this->_index->getActivePrimaryShards()); + } + + public function testGetActiveShards() + { + $this->assertEquals(4, $this->_index->getActiveShards()); + } + + public function testGetRelocatingShards() + { + $this->assertEquals(5, $this->_index->getRelocatingShards()); + } + + public function testGetInitializingShards() + { + $this->assertEquals(6, $this->_index->getInitializingShards()); + } + + public function testGetUnassignedShards() + { + $this->assertEquals(7, $this->_index->getUnassignedShards()); + } + + public function testGetShards() + { + $shards = $this->_index->getShards(); + + $this->assertInternalType('array', $shards); + $this->assertEquals(3, count($shards)); + + foreach ($shards as $shard) { + $this->assertInstanceOf('Elastica\Cluster\Health\Shard', $shard); + } + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Cluster/Health/ShardTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Cluster/Health/ShardTest.php new file mode 100644 index 00000000..b63195a0 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Cluster/Health/ShardTest.php @@ -0,0 +1,63 @@ +<?php + +namespace Elastica\Test\Cluster\Health; + +use Elastica\Cluster\Health\Shard as HealthShard; +use Elastica\Test\Base as BaseTest; + +class ShardTest extends BaseTest +{ + /** + * @var \Elastica\Cluster\Health\Shard + */ + protected $_shard; + + public function setUp() + { + $shardData = array( + 'status' => 'red', + 'primary_active' => true, + 'active_shards' => 1, + 'relocating_shards' => 0, + 'initializing_shards' => 0, + 'unassigned_shards' => 1, + ); + + $this->_shard = new HealthShard(2, $shardData); + } + + public function testGetShardNumber() + { + $this->assertEquals(2, $this->_shard->getShardNumber()); + } + + public function testGetStatus() + { + $this->assertEquals('red', $this->_shard->getStatus()); + } + + public function testisPrimaryActive() + { + $this->assertTrue($this->_shard->isPrimaryActive()); + } + + public function testIsActive() + { + $this->assertTrue($this->_shard->isActive()); + } + + public function testIsRelocating() + { + $this->assertFalse($this->_shard->isRelocating()); + } + + public function testIsInitialized() + { + $this->assertFalse($this->_shard->isInitialized()); + } + + public function testIsUnassigned() + { + $this->assertTrue($this->_shard->isUnassigned()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Cluster/HealthTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Cluster/HealthTest.php new file mode 100644 index 00000000..054af3f7 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Cluster/HealthTest.php @@ -0,0 +1,113 @@ +<?php + +namespace Elastica\Test\Cluster; + +use Elastica\Test\Base as BaseTest; + +class HealthTest extends BaseTest +{ + /** + * @var \Elastica\Cluster\Health + */ + protected $_health; + + public function setUp() + { + $data = array( + 'cluster_name' => 'test_cluster', + 'status' => 'green', + 'timed_out' => false, + 'number_of_nodes' => 10, + 'number_of_data_nodes' => 8, + 'active_primary_shards' => 3, + 'active_shards' => 4, + 'relocating_shards' => 2, + 'initializing_shards' => 7, + 'unassigned_shards' => 5, + 'indices' => array( + 'index_one' => array( + ), + 'index_two' => array( + ), + ), + ); + + $health = $this + ->getMockBuilder('Elastica\Cluster\Health') + ->setConstructorArgs(array($this->_getClient())) + ->setMethods(array('_retrieveHealthData')) + ->getMock(); + + $health + ->expects($this->any()) + ->method('_retrieveHealthData') + ->will($this->returnValue($data)); + + // need to explicitly refresh because the mocking won't refresh the data in the constructor + $health->refresh(); + + $this->_health = $health; + } + + public function testGetClusterName() + { + $this->assertEquals('test_cluster', $this->_health->getClusterName()); + } + + public function testGetStatus() + { + $this->assertEquals('green', $this->_health->getStatus()); + } + + public function testGetTimedOut() + { + $this->assertFalse($this->_health->getTimedOut()); + } + + public function testGetNumberOfNodes() + { + $this->assertEquals(10, $this->_health->getNumberOfNodes()); + } + + public function testGetNumberOfDataNodes() + { + $this->assertEquals(8, $this->_health->getNumberOfDataNodes()); + } + + public function testGetActivePrimaryShards() + { + $this->assertEquals(3, $this->_health->getActivePrimaryShards()); + } + + public function testGetActiveShards() + { + $this->assertEquals(4, $this->_health->getActiveShards()); + } + + public function testGetRelocatingShards() + { + $this->assertEquals(2, $this->_health->getRelocatingShards()); + } + + public function testGetInitializingShards() + { + $this->assertEquals(7, $this->_health->getInitializingShards()); + } + + public function testGetUnassignedShards() + { + $this->assertEquals(5, $this->_health->getUnassignedShards()); + } + + public function testGetIndices() + { + $indices = $this->_health->getIndices(); + + $this->assertInternalType('array', $indices); + $this->assertEquals(2, count($indices)); + + foreach ($indices as $index) { + $this->assertInstanceOf('Elastica\Cluster\Health\Index', $index); + } + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Cluster/SettingsTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Cluster/SettingsTest.php new file mode 100644 index 00000000..a093feef --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Cluster/SettingsTest.php @@ -0,0 +1,110 @@ +<?php + +namespace Elastica\Test\Cluster; + +use Elastica\Document; +use Elastica\Exception\ResponseException; +use Elastica\Test\Base as BaseTest; +use Elastica\Cluster\Settings; + +class SettingsTest extends BaseTest +{ + public function testSetTransient() + { + $index = $this->_createIndex(); + + if (count($index->getClient()->getCluster()->getNodes()) < 2) { + $this->markTestSkipped('At least two master nodes have to be running for this test'); + } + + $settings = new Settings($index->getClient()); + + $settings->setTransient('discovery.zen.minimum_master_nodes', 2); + $data = $settings->get(); + $this->assertEquals(2, $data['transient']['discovery.zen.minimum_master_nodes']); + + $settings->setTransient('discovery.zen.minimum_master_nodes', 1); + $data = $settings->get(); + $this->assertEquals(1, $data['transient']['discovery.zen.minimum_master_nodes']); + } + + public function testSetPersistent() + { + $index = $this->_createIndex(); + + if (count($index->getClient()->getCluster()->getNodes()) < 2) { + $this->markTestSkipped('At least two master nodes have to be running for this test'); + } + + $settings = new Settings($index->getClient()); + + $settings->setPersistent('discovery.zen.minimum_master_nodes', 2); + $data = $settings->get(); + $this->assertEquals(2, $data['persistent']['discovery.zen.minimum_master_nodes']); + + $settings->setPersistent('discovery.zen.minimum_master_nodes', 1); + $data = $settings->get(); + $this->assertEquals(1, $data['persistent']['discovery.zen.minimum_master_nodes']); + } + + public function testSetReadOnly() + { + // Create two indices to check that the complete cluster is read only + $settings = new Settings($this->_getClient()); + $settings->setReadOnly(false); + $index1 = $this->_createIndex('test1'); + $index2 = $this->_createIndex('test2'); + + + $doc1 = new Document(null, array('hello' => 'world')); + $doc2 = new Document(null, array('hello' => 'world')); + $doc3 = new Document(null, array('hello' => 'world')); + $doc4 = new Document(null, array('hello' => 'world')); + $doc5 = new Document(null, array('hello' => 'world')); + $doc6 = new Document(null, array('hello' => 'world')); + + // Check that adding documents work + $index1->getType('test')->addDocument($doc1); + $index2->getType('test')->addDocument($doc2); + + $response = $settings->setReadOnly(true); + $this->assertFalse($response->hasError()); + $setting = $settings->getTransient('cluster.blocks.read_only'); + $this->assertEquals('true', $setting); + + // Make sure both index are read only + try { + $index1->getType('test')->addDocument($doc3); + $this->fail('should throw read only exception'); + } catch (ResponseException $e) { + $message = $e->getMessage(); + $this->assertContains('ClusterBlockException', $message); + $this->assertContains('cluster read-only', $message); + } + + try { + $index2->getType('test')->addDocument($doc4); + $this->fail('should throw read only exception'); + } catch (ResponseException $e) { + $message = $e->getMessage(); + $this->assertContains('ClusterBlockException', $message); + $this->assertContains('cluster read-only', $message); + } + + $response = $settings->setReadOnly(false); + $this->assertFalse($response->hasError()); + $setting = $settings->getTransient('cluster.blocks.read_only'); + $this->assertEquals('false', $setting); + + // Check that adding documents works again + $index1->getType('test')->addDocument($doc5); + $index2->getType('test')->addDocument($doc6); + + $index1->refresh(); + $index2->refresh(); + + // 2 docs should be in each index + $this->assertEquals(2, $index1->count()); + $this->assertEquals(2, $index2->count()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/ClusterTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/ClusterTest.php new file mode 100644 index 00000000..ae5fb980 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/ClusterTest.php @@ -0,0 +1,89 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Client; +use Elastica\Cluster; +use Elastica\Test\Base as BaseTest; + +class ClusterTest extends BaseTest +{ + + public function testGetNodeNames() + { + $client = $this->_getClient(); + + $cluster = new Cluster($client); + + $names = $cluster->getNodeNames(); + + $this->assertInternalType('array', $names); + $this->assertGreaterThan(0, count($names)); + } + + public function testGetNodes() + { + $client = $this->_getClient(); + $cluster = $client->getCluster(); + + $nodes = $cluster->getNodes(); + + foreach ($nodes as $node) { + $this->assertInstanceOf('Elastica\Node', $node); + } + + $this->assertGreaterThan(0, count($nodes)); + } + + public function testGetState() + { + $client = $this->_getClient(); + $cluster = $client->getCluster(); + $state = $cluster->getState(); + $this->assertInternalType('array', $state); + } + + /** + * @expectedException \Elastica\Exception\ConnectionException + */ + public function testShutdown() + { + $this->markTestSkipped('This test shuts down the cluster which means the following tests would not work'); + $client = $this->_getClient(); + $cluster = $client->getCluster(); + + $cluster->shutdown('2s'); + + sleep(5); + + $client->getStatus(); + } + + public function testGetIndexNames() + { + $client = $this->_getClient(); + $cluster = $client->getCluster(); + + $indexName = 'elastica_test999'; + $index = $this->_createIndex($indexName); + $index->delete(); + $cluster->refresh(); + + // Checks that index does not exist + $indexNames = $cluster->getIndexNames(); + $this->assertNotContains($index->getName(), $indexNames); + + $index = $this->_createIndex($indexName); + $cluster->refresh(); + + // Now index should exist + $indexNames = $cluster->getIndexNames(); + $this->assertContains($index->getname(), $indexNames); + } + + public function testGetHealth() + { + $client = $this->_getClient(); + $this->assertInstanceOf('Elastica\Cluster\Health', $client->getCluster()->getHealth()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/ConnectionTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/ConnectionTest.php new file mode 100644 index 00000000..80cab9f0 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/ConnectionTest.php @@ -0,0 +1,103 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Connection; +use Elastica\Request; +use Elastica\Test\Base as BaseTest; + +class ConnectionTest extends BaseTest +{ + + public function testEmptyConstructor() + { + $connection = new Connection(); + $this->assertEquals(Connection::DEFAULT_HOST, $connection->getHost()); + $this->assertEquals(Connection::DEFAULT_PORT, $connection->getPort()); + $this->assertEquals(Connection::DEFAULT_TRANSPORT, $connection->getTransport()); + $this->assertInstanceOf('Elastica\Transport\AbstractTransport', $connection->getTransportObject()); + $this->assertEquals(Connection::TIMEOUT, $connection->getTimeout()); + $this->assertEquals(array(), $connection->getConfig()); + $this->assertTrue($connection->isEnabled()); + } + + public function testEnabledDisable() + { + $connection = new Connection(); + $this->assertTrue($connection->isEnabled()); + $connection->setEnabled(false); + $this->assertFalse($connection->isEnabled()); + $connection->setEnabled(true); + $this->assertTrue($connection->isEnabled()); + } + + /** + * @expectedException \Elastica\Exception\ConnectionException + */ + public function testInvalidConnection() + { + $connection = new Connection(array('port' => 9999)); + + $request = new Request('_status', Request::GET); + $request->setConnection($connection); + + // Throws exception because no valid connection + $request->send(); + } + + public function testCreate() + { + $connection = Connection::create(); + $this->assertInstanceOf('Elastica\Connection', $connection); + + $connection = Connection::create(array()); + $this->assertInstanceOf('Elastica\Connection', $connection); + + $port = 9999; + $connection = Connection::create(array('port' => $port)); + $this->assertInstanceOf('Elastica\Connection', $connection); + $this->assertEquals($port, $connection->getPort()); + } + + /** + * @expectedException \Elastica\Exception\InvalidException + * @expectedException \Elastica\Exception\InvalidException + */ + public function testCreateInvalid() + { + Connection::create('test'); + } + + public function testGetConfig() + { + $url = 'test'; + $connection = new Connection(array('config' => array('url' => $url))); + $this->assertTrue($connection->hasConfig('url')); + $this->assertEquals($url, $connection->getConfig('url')); + } + + public function testGetConfigWithArrayUsedForTransport() + { + $connection = new Connection(array('transport' => array('type' => 'Http'))); + $this->assertInstanceOf('Elastica\Transport\Http', $connection->getTransportObject()); + } + + /** + * @expectedException Elastica\Exception\InvalidException + * @expectedExceptionMessage Invalid transport + */ + public function testGetInvalidConfigWithArrayUsedForTransport() + { + $connection = new Connection(array('transport' => array('type' => 'invalidtransport'))); + $connection->getTransportObject(); + } + + /** + * @expectedException \Elastica\Exception\InvalidException + */ + public function testGetConfigInvalidValue() + { + $connection = new Connection(); + $connection->getConfig('url'); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/DocumentTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/DocumentTest.php new file mode 100644 index 00000000..27fc5184 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/DocumentTest.php @@ -0,0 +1,309 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Document; +use Elastica\Exception\InvalidException; +use Elastica\Script; +use Elastica\Index; +use Elastica\Type; +use Elastica\Test\Base as BaseTest; + +class DocumentTest extends BaseTest +{ + public function testAddFile() + { + $fileName = '/dev/null'; + if(!file_exists($fileName)){ + $this->markTestSkipped("File {$fileName} does not exist."); + } + $doc = new Document(); + $returnValue = $doc->addFile('key', $fileName); + $this->assertInstanceOf('Elastica\Document', $returnValue); + } + + public function testAddGeoPoint() + { + $doc = new Document(); + $returnValue = $doc->addGeoPoint('point', 38.89859, -77.035971); + $this->assertInstanceOf('Elastica\Document', $returnValue); + } + + public function testSetData() + { + $doc = new Document(); + $returnValue = $doc->setData(array('data')); + $this->assertInstanceOf('Elastica\Document', $returnValue); + } + + public function testToArray() + { + $id = 17; + $data = array('hello' => 'world'); + $type = 'testtype'; + $index = 'textindex'; + + $doc = new Document($id, $data, $type, $index); + + $result = array('_index' => $index, '_type' => $type, '_id' => $id, '_source' => $data); + $this->assertEquals($result, $doc->toArray()); + } + + public function testSetType() + { + $document = new Document(); + $document->setType('type'); + + $this->assertEquals('type', $document->getType()); + + $index = new Index($this->_getClient(), 'index'); + $type = $index->getType('type'); + + $document->setIndex('index2'); + $this->assertEquals('index2', $document->getIndex()); + + $document->setType($type); + + $this->assertEquals('index', $document->getIndex()); + $this->assertEquals('type', $document->getType()); + } + + public function testSetIndex() + { + $document = new Document(); + $document->setIndex('index2'); + $document->setType('type2'); + + $this->assertEquals('index2', $document->getIndex()); + $this->assertEquals('type2', $document->getType()); + + $index = new Index($this->_getClient(), 'index'); + + $document->setIndex($index); + + $this->assertEquals('index', $document->getIndex()); + $this->assertEquals('type2', $document->getType()); + } + + public function testHasId() + { + $document = new Document(); + $this->assertFalse($document->hasId()); + $document->setId(''); + $this->assertFalse($document->hasId()); + $document->setId(0); + $this->assertTrue($document->hasId()); + $document->setId('hello'); + $this->assertTrue($document->hasId()); + } + + public function testGetOptions() + { + $document = new Document(); + $document->setIndex('index'); + $document->setOpType('create'); + $document->setParent('2'); + $document->setId(1); + + $options = $document->getOptions(array('index', 'type', 'id', 'parent')); + + $this->assertInternalType('array', $options); + $this->assertEquals(3, count($options)); + $this->assertArrayHasKey('index', $options); + $this->assertArrayHasKey('id', $options); + $this->assertArrayHasKey('parent', $options); + $this->assertEquals('index', $options['index']); + $this->assertEquals(1, $options['id']); + $this->assertEquals('2', $options['parent']); + $this->assertArrayNotHasKey('type', $options); + $this->assertArrayNotHasKey('op_type', $options); + $this->assertArrayNotHasKey('_index', $options); + $this->assertArrayNotHasKey('_id', $options); + $this->assertArrayNotHasKey('_parent', $options); + + $options = $document->getOptions(array('parent', 'op_type', 'percolate'), true); + + $this->assertInternalType('array', $options); + $this->assertEquals(2, count($options)); + $this->assertArrayHasKey('_parent', $options); + $this->assertArrayHasKey('_op_type', $options); + $this->assertEquals('2', $options['_parent']); + $this->assertEquals('create', $options['_op_type']); + $this->assertArrayNotHasKey('percolate', $options); + $this->assertArrayNotHasKey('op_type', $options); + $this->assertArrayNotHasKey('parent', $options); + } + + public function testGetSetHasRemove() + { + $document = new Document(1, array('field1' => 'value1', 'field2' => 'value2', 'field3' => 'value3', 'field4' => null)); + + $this->assertEquals('value1', $document->get('field1')); + $this->assertEquals('value2', $document->get('field2')); + $this->assertEquals('value3', $document->get('field3')); + $this->assertNull($document->get('field4')); + try { + $document->get('field5'); + $this->fail('Undefined field get should throw exception'); + } catch (InvalidException $e) { + $this->assertTrue(true); + } + + $this->assertTrue($document->has('field1')); + $this->assertTrue($document->has('field2')); + $this->assertTrue($document->has('field3')); + $this->assertTrue($document->has('field4')); + $this->assertFalse($document->has('field5'), 'Field5 should not be isset, because it is not set'); + + $data = $document->getData(); + + $this->assertArrayHasKey('field1', $data); + $this->assertEquals('value1', $data['field1']); + $this->assertArrayHasKey('field2', $data); + $this->assertEquals('value2', $data['field2']); + $this->assertArrayHasKey('field3', $data); + $this->assertEquals('value3', $data['field3']); + $this->assertArrayHasKey('field4', $data); + $this->assertNull($data['field4']); + + $returnValue = $document->set('field1', 'changed1'); + $this->assertInstanceOf('Elastica\Document', $returnValue); + $returnValue = $document->remove('field3'); + $this->assertInstanceOf('Elastica\Document', $returnValue); + try { + $document->remove('field5'); + $this->fail('Undefined field unset should throw exception'); + } catch (InvalidException $e) { + $this->assertTrue(true); + } + + $this->assertEquals('changed1', $document->get('field1')); + $this->assertFalse($document->has('field3')); + + $newData = $document->getData(); + + $this->assertNotEquals($data, $newData); + } + + public function testDataPropertiesOverloading() + { + $document = new Document(1, array('field1' => 'value1', 'field2' => 'value2', 'field3' => 'value3', 'field4' => null)); + + $this->assertEquals('value1', $document->field1); + $this->assertEquals('value2', $document->field2); + $this->assertEquals('value3', $document->field3); + $this->assertNull($document->field4); + try { + $document->field5; + $this->fail('Undefined field get should throw exception'); + } catch (InvalidException $e) { + $this->assertTrue(true); + } + + $this->assertTrue(isset($document->field1)); + $this->assertTrue(isset($document->field2)); + $this->assertTrue(isset($document->field3)); + $this->assertFalse(isset($document->field4), 'Field4 should not be isset, because it is null'); + $this->assertFalse(isset($document->field5), 'Field5 should not be isset, because it is not set'); + + $data = $document->getData(); + + $this->assertArrayHasKey('field1', $data); + $this->assertEquals('value1', $data['field1']); + $this->assertArrayHasKey('field2', $data); + $this->assertEquals('value2', $data['field2']); + $this->assertArrayHasKey('field3', $data); + $this->assertEquals('value3', $data['field3']); + $this->assertArrayHasKey('field4', $data); + $this->assertNull($data['field4']); + + $document->field1 = 'changed1'; + unset($document->field3); + try { + unset($document->field5); + $this->fail('Undefined field unset should throw exception'); + } catch (InvalidException $e) { + $this->assertTrue(true); + } + + $this->assertEquals('changed1', $document->field1); + $this->assertFalse(isset($document->field3)); + + $newData = $document->getData(); + + $this->assertNotEquals($data, $newData); + } + + public function testSetTtl() + { + $document = new Document(); + + $this->assertFalse($document->hasTtl()); + $options = $document->getOptions(); + $this->assertArrayNotHasKey('ttl', $options); + + $document->setTtl('1d'); + + $newOptions = $document->getOptions(); + + $this->assertArrayHasKey('ttl', $newOptions); + $this->assertEquals('1d', $newOptions['ttl']); + $this->assertNotEquals($options, $newOptions); + + $this->assertTrue($document->hasTtl()); + $this->assertEquals('1d', $document->getTtl()); + } + + public function testSerializedData() + { + $data = '{"user":"rolf"}'; + $document = new Document(1, $data); + + $this->assertFalse($document->has('user')); + + try { + $document->get('user'); + $this->fail('User field should not be available'); + } catch (InvalidException $e) { + $this->assertTrue(true); + } + + try { + $document->remove('user'); + $this->fail('User field should not be available for removal'); + } catch (InvalidException $e) { + $this->assertTrue(true); + } + + try { + $document->set('name', 'shawn'); + $this->fail('Document should not allow to set new data'); + } catch (InvalidException $e) { + $this->assertTrue(true); + } + } + + public function testUpsert() + { + $document = new Document(); + + $upsert = new Document(); + $upsert->setData(array('someproperty' => 'somevalue')); + + $this->assertFalse($document->hasUpsert()); + + $document->setUpsert($upsert); + + $this->assertTrue($document->hasUpsert()); + $this->assertSame($upsert, $document->getUpsert()); + } + + public function testDocAsUpsert() + { + $document = new Document(); + + $this->assertFalse($document->getDocAsUpsert()); + $this->assertSame($document, $document->setDocAsUpsert(true)); + $this->assertTrue($document->getDocAsUpsert()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/ExampleTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/ExampleTest.php new file mode 100644 index 00000000..0331e389 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/ExampleTest.php @@ -0,0 +1,58 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Client; +use Elastica\Document; +use Elastica\Test\Base as BaseTest; + +/** + * Tests the example code + */ +class ExampleTest extends BaseTest +{ + public function testBasicGettingStarted() { + + $client = new \Elastica\Client(); + $index = $client->getIndex('ruflin'); + $type = $index->getType('users'); + + $id = 2; + $data = array('firstname' => 'Nicolas', 'lastname' => 'Ruflin'); + $doc = new \Elastica\Document($id, $data); + + $type->addDocument($doc); + + } + + public function testExample() + { + // Creates a new index 'xodoa' and a type 'user' inside this index + $client = $this->_getClient(); + $index = $client->getIndex('elastica_test'); + $index->create(array(), true); + + $type = $index->getType('user'); + + // Adds 1 document to the index + $doc1 = new Document(1, + array('username' => 'hans', 'test' => array('2', '3', '5')) + ); + $type->addDocument($doc1); + + // Adds a list of documents with _bulk upload to the index + $docs = array(); + $docs[] = new Document(2, + array('username' => 'john', 'test' => array('1', '3', '6')) + ); + $docs[] = new Document(3, + array('username' => 'rolf', 'test' => array('2', '3', '7')) + ); + $type->addDocuments($docs); + + // Refresh index + $index->refresh(); + + $resultSet = $type->search('rolf'); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Exception/NotImplementedTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Exception/NotImplementedTest.php new file mode 100644 index 00000000..ff704638 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Exception/NotImplementedTest.php @@ -0,0 +1,23 @@ +<?php + +namespace Elastica\Test\Exception; + +use Elastica\Exception\NotImplementedException; +use Elastica\Test\Base as BaseTest; + +class NotImplementedTest extends BaseTest +{ + public function testInstance() + { + $code = 4; + $message = 'Hello world'; + $exception = new NotImplementedException($message, $code); + + $this->assertInstanceOf('Elastica\Exception\NotImplementedException', $exception); + $this->assertInstanceOf('Elastica\Exception\ExceptionInterface', $exception); + $this->assertInstanceOf('Exception', $exception); + + $this->assertEquals($message, $exception->getMessage()); + $this->assertEquals($code, $exception->getCode()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Exception/PartialShardFailureExceptionTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Exception/PartialShardFailureExceptionTest.php new file mode 100644 index 00000000..31698e26 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Exception/PartialShardFailureExceptionTest.php @@ -0,0 +1,55 @@ +<?php + +namespace Elastica\Test\Exception; + +use Elastica\Document; +use Elastica\Exception\PartialShardFailureException; +use Elastica\Query; +use Elastica\ResultSet; +use Elastica\Test\Base as BaseTest; + +class PartialShardFailureExceptionTest extends BaseTest +{ + + public function testPartialFailure() + { + $client = $this->_getClient(); + $index = $client->getIndex('elastica_partial_failure'); + $index->create(array( + 'index' => array( + 'number_of_shards' => 5, + 'number_of_replicas' => 0 + ) + ), true); + + $type = $index->getType('folks'); + + $type->addDocument(new Document('', array('name' => 'ruflin'))); + $type->addDocument(new Document('', array('name' => 'bobrik'))); + $type->addDocument(new Document('', array('name' => 'kimchy'))); + + $index->refresh(); + + $query = Query::create(array( + 'query' => array( + 'filtered' => array( + 'filter' => array( + 'script' => array( + 'script' => 'doc["undefined"] > 8', // compiles, but doesn't work + ), + ), + ), + ), + )); + + try { + $index->search($query); + + $this->fail('PartialShardFailureException should have been thrown'); + } catch (PartialShardFailureException $e) { + $resultSet = new ResultSet($e->getResponse(), $query); + $this->assertEquals(0, count($resultSet->getResults())); + } + } + +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Exception/ResponseExceptionTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Exception/ResponseExceptionTest.php new file mode 100644 index 00000000..06b5462b --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Exception/ResponseExceptionTest.php @@ -0,0 +1,60 @@ +<?php + +namespace Elastica\Test\Exception; + +use Elastica\Document; +use Elastica\Exception\ResponseException; +use Elastica\Test\Base as BaseTest; + +class ResponseExceptionTest extends BaseTest +{ + + public function testCreateExistingIndex() + { + $this->_createIndex('woo', true); + + try { + $this->_createIndex('woo', false); + $this->fail('Index created when it should fail'); + } catch (ResponseException $ex) { + $this->assertEquals('IndexAlreadyExistsException', $ex->getElasticsearchException()->getExceptionName()); + $this->assertEquals(400, $ex->getElasticsearchException()->getCode()); + } + } + + public function testBadType() + { + $index = $this->_createIndex('woo'); + $type = $index->getType('test'); + + $type->setMapping(array( + 'num' => array( + 'type' => 'long' + ) + )); + + try { + $type->addDocument(new Document('', array( + 'num' => 'not number at all', + ))); + $this->fail('Indexing with wrong type should fail'); + } catch (ResponseException $ex) { + $this->assertEquals('MapperParsingException', $ex->getElasticsearchException()->getExceptionName()); + $this->assertEquals(400, $ex->getElasticsearchException()->getCode()); + } + } + + public function testWhatever() + { + $index = $this->_createIndex('woo'); + $index->delete(); + + try { + $index->search(); + } catch (ResponseException $ex) { + $this->assertEquals('IndexMissingException', $ex->getElasticsearchException()->getExceptionName()); + $this->assertEquals(404, $ex->getElasticsearchException()->getCode()); + } + } + +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/DateHistogramTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/DateHistogramTest.php new file mode 100644 index 00000000..46dcdbf9 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/DateHistogramTest.php @@ -0,0 +1,59 @@ +<?php + +namespace Elastica\Test\Facet; + +use Elastica\Document; +use Elastica\Facet\DateHistogram; +use Elastica\Query; +use Elastica\Query\MatchAll; +use Elastica\Test\Base as BaseTest; +use Elastica\Type\Mapping; + +class DateHistogramTest extends BaseTest +{ + public function testClassHierarchy() + { + $facet = new DateHistogram('dateHist1'); + $this->assertInstanceOf('Elastica\Facet\Histogram', $facet); + $this->assertInstanceOf('Elastica\Facet\AbstractFacet', $facet); + unset($facet); + } + + public function testTest() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('helloworld'); + + $mapping = new Mapping($type, array( + 'name' => array('type' => 'string', 'store' => 'no'), + 'dtmPosted' => array('type' => 'date', 'store' => 'no', 'format' => 'yyyy-MM-dd HH:mm:ss') + )); + $type->setMapping($mapping); + + $doc = new Document(1, array('name' => 'nicolas ruflin', 'dtmPosted' => "2011-06-23 21:53:00")); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'raul martinez jr', 'dtmPosted' => "2011-06-23 09:53:00")); + $type->addDocument($doc); + $doc = new Document(3, array('name' => 'rachelle clemente', 'dtmPosted' => "2011-07-08 08:53:00")); + $type->addDocument($doc); + $doc = new Document(4, array('name' => 'elastica search', 'dtmPosted' => "2011-07-08 01:53:00")); + $type->addDocument($doc); + + $facet = new DateHistogram('dateHist1'); + $facet->setInterval("day"); + $facet->setField("dtmPosted"); + + $query = new Query(); + $query->addFacet($facet); + $query->setQuery(new MatchAll()); + $index->refresh(); + + $response = $type->search($query); + $facets = $response->getFacets(); + + $this->assertEquals(4, $response->getTotalHits()); + $this->assertEquals(2, count($facets['dateHist1']['entries'])); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/FilterTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/FilterTest.php new file mode 100644 index 00000000..ca6f5ba3 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/FilterTest.php @@ -0,0 +1,40 @@ +<?php + +namespace Elastica\Test\Facet; + +use Elastica\Document; +use Elastica\Filter\Term; +use Elastica\Facet\Filter; +use Elastica\Query; +use Elastica\Test\Base as BaseTest; + +class FilterTest extends BaseTest +{ + public function testFilter() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('helloworld'); + + $type->addDocument(new Document(1, array('color' => 'red'))); + $type->addDocument(new Document(2, array('color' => 'green'))); + $type->addDocument(new Document(3, array('color' => 'blue'))); + + $index->refresh(); + + $filter = new Term(array('color' => 'red')); + + $facet = new Filter('test'); + $facet->setFilter($filter); + + $query = new Query(); + $query->addFacet($facet); + + $resultSet = $type->search($query); + + $facets = $resultSet->getFacets(); + + $this->assertEquals(1, $facets['test']['count']); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/GeoClusterTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/GeoClusterTest.php new file mode 100644 index 00000000..d06b58f9 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/GeoClusterTest.php @@ -0,0 +1,49 @@ +<?php + +namespace Elastica\Test\Facet; + +use Elastica\Test\Base as BaseTest; + +class GeoClusterTest extends BaseTest{ + public function testQuery() { + $client = $this->_getClient(); + $nodes = $client->getCluster()->getNodes(); + if(!$nodes[0]->getInfo()->hasPlugin('geocluster-facet')){ + $this->markTestSkipped('geocluster-facet plugin not installed'); + } + + $index = $this->_createIndex('geocluster_test'); + $type = $index->getType('testQuery'); + $geoField = 'location'; + + $type->setMapping(new \Elastica\Type\Mapping($type, array( + $geoField => array( 'type' => 'geo_point', 'lat_lon' => true ) + ))); + + $doc = new \Elastica\Document(1, array('name' => 'item1', 'location' => array(20,20))); + $type->addDocument($doc); + + $doc = new \Elastica\Document(2, array('name' => 'item2', 'location' => array(20,20))); + $type->addDocument($doc); + + $doc = new \Elastica\Document(3, array('name' => 'item3', 'location' => array(20,20))); + $type->addDocument($doc); + + $index->refresh(); + + $facet = new \Elastica\Facet\GeoCluster('clusters'); + $facet + ->setField($geoField) + ->setFactor(1) + ->setShowIds(false); + $query = new \Elastica\Query(); + $query->setFacets(array($facet)); + + $response = $type->search($query); + $facets = $response->getFacets(); + + $this->assertEquals(1, count($facets['clusters']['clusters'])); + + $index->delete(); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/QueryTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/QueryTest.php new file mode 100644 index 00000000..ef5d7ccd --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/QueryTest.php @@ -0,0 +1,40 @@ +<?php + +namespace Elastica\Test\Facet; + +use Elastica\Document; +use Elastica\Facet\Query as FacetQuery; +use Elastica\Query; +use Elastica\Query\Term; +use Elastica\Test\Base as BaseTest; + +class QueryTest extends BaseTest +{ + public function testFilter() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('helloworld'); + + $type->addDocument(new Document(1, array('color' => 'red'))); + $type->addDocument(new Document(2, array('color' => 'green'))); + $type->addDocument(new Document(3, array('color' => 'blue'))); + + $index->refresh(); + + $termQuery = new Term(array('color' => 'red')); + + $facet = new FacetQuery('test'); + $facet->setQuery($termQuery); + + $query = new Query(); + $query->addFacet($facet); + + $resultSet = $type->search($query); + + $facets = $resultSet->getFacets(); + + $this->assertEquals(1, $facets['test']['count']); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/StatisticalTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/StatisticalTest.php new file mode 100644 index 00000000..0b528a79 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/StatisticalTest.php @@ -0,0 +1,82 @@ +<?php + +namespace Elastica\Test\Facet; + +use Elastica\Document; +use Elastica\Facet\Statistical; +use Elastica\Query; +use Elastica\Query\MatchAll; +use Elastica\Test\Base as BaseTest; + +class StatisticalTest extends BaseTest +{ + public function testStatisticalWithSetField() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('helloworld'); + + $doc = new Document(1, array('price' => 10)); + $type->addDocument($doc); + $doc = new Document(2, array('price' => 35)); + $type->addDocument($doc); + $doc = new Document(2, array('price' => 45)); + $type->addDocument($doc); + + $facet = new Statistical('stats'); + $facet->setField('price'); + + $query = new Query(); + $query->addFacet($facet); + $query->setQuery(new MatchAll()); + + $index->refresh(); + + $response = $type->search($query); + $facets = $response->getFacets(); + + $this->assertEquals(55, $facets['stats']['total']); + $this->assertEquals(10, $facets['stats']['min']); + $this->assertEquals(45, $facets['stats']['max']); + } + + public function testStatisticalWithSetFields() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('helloworld'); + + $doc = new Document(1, array('price' => 10, 'price2' => 20)); + $type->addDocument($doc); + $doc = new Document(2, array('price' => 35, 'price2' => 70)); + $type->addDocument($doc); + $doc = new Document(2, array('price' => 45, 'price2' => 90)); + $type->addDocument($doc); + + $facet = new Statistical('stats'); + $facet->setFields(array('price','price2')); + + $query = new Query(); + $query->addFacet($facet); + $query->setQuery(new MatchAll()); + + $index->refresh(); + + $response = $type->search($query); + $facets = $response->getFacets(); + + $this->assertEquals(165, $facets['stats']['total']); + $this->assertEquals(10, $facets['stats']['min']); + $this->assertEquals(90, $facets['stats']['max']); + } + + /** + * @todo + */ + public function testStatisticalWithSetScript() + { + $this->markTestIncomplete('Test for setting the script value'); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/TermsStatsTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/TermsStatsTest.php new file mode 100644 index 00000000..bea9b78d --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/TermsStatsTest.php @@ -0,0 +1,105 @@ +<?php + +namespace Elastica\Test\Facet; + +use Elastica\Document; +use Elastica\Facet\TermsStats; +use Elastica\Query; +use Elastica\Query\MatchAll; +use Elastica\Test\Base as BaseTest; + +class TermsStatsTest extends BaseTest +{ + public function testOrder() + { + $client = $this->_getClient(); + $index = $client->getIndex( 'test' ); + $index->create( array( ), true ); + $type = $index->getType( 'helloworld' ); + + $doc = new Document( 1, array( 'name' => 'tom', 'paid' => 7 ) ); + $type->addDocument( $doc ); + $doc = new Document( 2, array( 'name' => 'tom', 'paid' => 2 ) ); + $type->addDocument( $doc ); + $doc = new Document( 3, array( 'name' => 'tom', 'paid' => 5 ) ); + $type->addDocument( $doc ); + $doc = new Document( 4, array( 'name' => 'mike', 'paid' => 13 ) ); + $type->addDocument( $doc ); + $doc = new Document( 5, array( 'name' => 'mike', 'paid' => 1 ) ); + $type->addDocument( $doc ); + $doc = new Document( 6, array( 'name' => 'mike', 'paid' => 15 ) ); + $type->addDocument( $doc ); + + $facet = new TermsStats( 'test' ); + $facet->setKeyField( 'name' ); + $facet->setValueField( 'paid' ); + $facet->setOrder( 'reverse_total' ); + + $query = new Query(); + $query->addFacet( $facet ); + $query->setQuery( new MatchAll() ); + + $index->refresh(); + + $response = $type->search( $query ); + $facets = $response->getFacets(); + + $this->assertEquals(14, $facets[ 'test' ][ 'terms' ][0]['total'] ); + $this->assertEquals(29, $facets[ 'test' ][ 'terms' ][1]['total'] ); + } + + public function testQuery() + { + $client = $this->_getClient(); + $index = $client->getIndex( 'test' ); + $index->create( array( ), true ); + $type = $index->getType( 'helloworld' ); + + $doc = new Document( 1, array( 'name' => 'tom', 'paid' => 7 ) ); + $type->addDocument( $doc ); + $doc = new Document( 2, array( 'name' => 'tom', 'paid' => 2 ) ); + $type->addDocument( $doc ); + $doc = new Document( 3, array( 'name' => 'tom', 'paid' => 5 ) ); + $type->addDocument( $doc ); + $doc = new Document( 4, array( 'name' => 'mike', 'paid' => 13 ) ); + $type->addDocument( $doc ); + $doc = new Document( 5, array( 'name' => 'mike', 'paid' => 1 ) ); + $type->addDocument( $doc ); + $doc = new Document( 6, array( 'name' => 'mike', 'paid' => 15 ) ); + $type->addDocument( $doc ); + + $facet = new TermsStats( 'test' ); + $facet->setKeyField( 'name' ); + $facet->setValueField( 'paid' ); + + $query = new Query(); + $query->addFacet( $facet ); + $query->setQuery( new MatchAll() ); + + $index->refresh(); + + $response = $type->search( $query ); + $facets = $response->getFacets(); + + $this->assertEquals( 2, count( $facets[ 'test' ][ 'terms' ] ) ); + foreach ($facets[ 'test' ][ 'terms' ] as $facet) { + if ($facet[ 'term' ] === 'tom') { + $this->assertEquals( 14, $facet[ 'total' ] ); + } + if ($facet[ 'term' ] === 'mike') { + $this->assertEquals( 29, $facet[ 'total' ] ); + } + } + } + + public function testSetSize() + { + $facet = new TermsStats( 'test' ); + $facet->setSize(100); + + $data = $facet->toArray(); + + $this->assertArrayHasKey('size', $data['terms_stats']); + $this->assertEquals(100, $data['terms_stats']['size']); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/TermsTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/TermsTest.php new file mode 100644 index 00000000..e8521c5c --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/TermsTest.php @@ -0,0 +1,69 @@ +<?php + +namespace Elastica\Test\Facet; + +use Elastica\Document; +use Elastica\Facet\Terms; +use Elastica\Query; +use Elastica\Query\MatchAll; +use Elastica\Test\Base as BaseTest; + +class TermsTest extends BaseTest +{ + public function testQuery() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('helloworld'); + + $doc = new Document(1, array('name' => 'nicolas ruflin')); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'ruflin test')); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'nicolas helloworld')); + $type->addDocument($doc); + + $facet = new Terms('test'); + $facet->setField('name'); + + $query = new Query(); + $query->addFacet($facet); + $query->setQuery(new MatchAll()); + + $index->refresh(); + + $response = $type->search($query); + $facets = $response->getFacets(); + + $this->assertEquals(3, count($facets['test']['terms'])); + } + + public function testFacetScript() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('helloworld'); + + $doc = new Document(1, array('name' => 'rodolfo', 'last_name' => 'moraes')); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'jose', 'last_name' => 'honjoya')); + $type->addDocument($doc); + + $facet = new Terms('test'); + $facet->setField('name'); + $facet->setScript('term + " "+doc["last_name"].value'); + + $query = new Query(); + $query->addFacet($facet); + $query->setQuery(new MatchAll()); + + $index->refresh(); + + $response = $type->search($query); + $facets = $response->getFacets(); + + $this->assertEquals(2, count($facets['test']['terms'])); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/AbstractTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/AbstractTest.php new file mode 100644 index 00000000..1e47819f --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/AbstractTest.php @@ -0,0 +1,69 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Test\Base as BaseTest; + +class AbstractTest extends BaseTest +{ + public function testSetCached() + { + $stubFilter = $this->getStub(); + + $stubFilter->setCached(true); + $arrayFilter = current($stubFilter->toArray()); + $this->assertTrue($arrayFilter['_cache']); + + $stubFilter->setCached(false); + $arrayFilter = current($stubFilter->toArray()); + $this->assertFalse($arrayFilter['_cache']); + } + + public function testSetCachedDefaultValue() + { + $stubFilter = $this->getStub(); + + $stubFilter->setCached(); + $arrayFilter = current($stubFilter->toArray()); + $this->assertTrue($arrayFilter['_cache']); + } + + public function testSetCacheKey() + { + $stubFilter = $this->getStub(); + + $cacheKey = 'myCacheKey'; + + $stubFilter->setCacheKey($cacheKey); + $arrayFilter = current($stubFilter->toArray()); + $this->assertEquals($cacheKey, $arrayFilter['_cache_key']); + } + + /** + * @expectedException \Elastica\Exception\InvalidException + */ + public function testSetCacheKeyEmptyKey() + { + $stubFilter = $this->getStub(); + + $cacheKey = ''; + + $stubFilter->setCacheKey($cacheKey); + } + + public function testSetName() + { + $stubFilter = $this->getStub(); + + $name = 'myFilter'; + + $stubFilter->setName($name); + $arrayFilter = current($stubFilter->toArray()); + $this->assertEquals($name, $arrayFilter['_name']); + } + + private function getStub() + { + return $this->getMockForAbstractClass('Elastica\Filter\AbstractFilter'); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/BoolAndTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/BoolAndTest.php new file mode 100644 index 00000000..672c6c67 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/BoolAndTest.php @@ -0,0 +1,65 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Document; +use Elastica\Filter\BoolAnd; +use Elastica\Filter\Ids; +use Elastica\Test\Base as BaseTest; + +class BoolAndTest extends BaseTest +{ + public function testToArray() + { + $and = new BoolAnd(); + $this->assertEquals(array('and' => array()), $and->toArray()); + + $idsFilter = new Ids(); + $idsFilter->setIds(12); + + $and->addFilter($idsFilter); + $and->addFilter($idsFilter); + + $expectedArray = array( + 'and' => array( + $idsFilter->toArray(), + $idsFilter->toArray() + ) + ); + + $this->assertEquals($expectedArray, $and->toArray()); + } + + public function testSetCache() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('test'); + + $doc = new Document(1, array('name' => 'hello world')); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'nicolas ruflin')); + $type->addDocument($doc); + $doc = new Document(3, array('name' => 'ruflin')); + $type->addDocument($doc); + + $and = new BoolAnd(); + + $idsFilter1 = new Ids(); + $idsFilter1->setIds(1); + + $idsFilter2 = new Ids(); + $idsFilter2->setIds(1); + + $and->addFilter($idsFilter1); + $and->addFilter($idsFilter2); + + $index->refresh(); + $and->setCached(true); + + $resultSet = $type->search($and); + + $this->assertEquals(1, $resultSet->count()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/BoolNotTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/BoolNotTest.php new file mode 100644 index 00000000..adcebf45 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/BoolNotTest.php @@ -0,0 +1,25 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Filter\Ids; +use Elastica\Filter\BoolNot; +use Elastica\Test\Base as BaseTest; + +class BoolNotTest extends BaseTest +{ + public function testToArray() + { + $idsFilter = new Ids(); + $idsFilter->setIds(12); + $filter = new BoolNot($idsFilter); + + $expectedArray = array( + 'not' => array( + 'filter' => $idsFilter->toArray() + ) + ); + + $this->assertEquals($expectedArray, $filter->toArray()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/BoolOrTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/BoolOrTest.php new file mode 100644 index 00000000..25234a8c --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/BoolOrTest.php @@ -0,0 +1,42 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Filter\AbstractFilter; +use Elastica\Filter\BoolOr; +use Elastica\Filter\Ids; +use Elastica\Test\Base as BaseTest; + +class BoolOrTest extends BaseTest +{ + public function testAddFilter() + { + $filter = $this->getMockForAbstractClass('Elastica\Filter\AbstractFilter'); + $orFilter = new BoolOr(); + $returnValue = $orFilter->addFilter($filter); + $this->assertInstanceOf('Elastica\Filter\BoolOr', $returnValue); + } + + public function testToArray() + { + $orFilter = new BoolOr(); + + $filter1 = new Ids(); + $filter1->setIds('1'); + + $filter2 = new Ids(); + $filter2->setIds('2'); + + $orFilter->addFilter($filter1); + $orFilter->addFilter($filter2); + + $expectedArray = array( + 'or' => array( + $filter1->toArray(), + $filter2->toArray() + ) + ); + + $this->assertEquals($expectedArray, $orFilter->toArray()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/BoolTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/BoolTest.php new file mode 100644 index 00000000..60eb3a45 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/BoolTest.php @@ -0,0 +1,107 @@ +<?php + +namespace Elastica\Test\Filter; + +use \Elastica\Query; +use Elastica\Filter\Bool; +use Elastica\Filter\Term; +use Elastica\Filter\Ids; +use Elastica\Test\Base as BaseTest; + +class BoolTest extends BaseTest +{ + public function testToArray() + { + $mainBool = new Bool(); + + $idsFilter1 = new Ids(); + $idsFilter1->setIds(1); + $idsFilter2 = new Ids(); + $idsFilter2->setIds(2); + $idsFilter3 = new Ids(); + $idsFilter3->setIds(3); + + $childBool = new Bool(); + $childBool->addShould(array($idsFilter1, $idsFilter2)); + $mainBool->addShould(array($childBool, $idsFilter3)); + + $expectedArray = array( + 'bool' => array( + 'should' => array( + array( + array( + 'bool' => array( + 'should' => array( + array( + $idsFilter1->toArray(), + $idsFilter2->toArray() + ) + ) + ) + ), + $idsFilter3->toArray() + ) + ) + ) + ); + + $this->assertEquals($expectedArray, $mainBool->toArray()); + } + + public function testBoolFilter() + { + $index = $this->_createIndex('bool_filter_test'); + $type = $index->getType('book'); + + //index some test data + $type->addDocument(new \Elastica\Document(1, array('author' => 'Michael Shermer', 'title' => 'The Believing Brain', 'publisher' => 'Robinson'))); + $type->addDocument(new \Elastica\Document(2, array('author' => 'Jared Diamond', 'title' => 'Guns, Germs and Steel', 'publisher' => 'Vintage'))); + $type->addDocument(new \Elastica\Document(3, array('author' => 'Jared Diamond', 'title' => 'Collapse', 'publisher' => 'Penguin'))); + $type->addDocument(new \Elastica\Document(4, array('author' => 'Richard Dawkins', 'title' => 'The Selfish Gene', 'publisher' => 'OUP Oxford'))); + $type->addDocument(new \Elastica\Document(5, array('author' => 'Anthony Burges', 'title' => 'A Clockwork Orange', 'publisher' => 'Penguin'))); + + $index->refresh(); + + //use the terms lookup feature to query for some data + //build query + //must + // should + // author = jared + // author = richard + // must_not + // publisher = penguin + + //construct the query + $query = new Query(); + $mainBoolFilter = new Bool(); + $shouldFilter = new Bool(); + $authorFilter1 = new Term(); + $authorFilter1->setTerm('author', 'jared'); + $authorFilter2 = new Term(); + $authorFilter2->setTerm('author', 'richard'); + $shouldFilter->addShould(array($authorFilter1, $authorFilter2)); + + $mustNotFilter = new Bool(); + $publisherFilter = new Term(); + $publisherFilter->setTerm('publisher', 'penguin'); + $mustNotFilter->addMustNot($publisherFilter); + + $mainBoolFilter->addMust(array($shouldFilter, $mustNotFilter)); + $query->setFilter($mainBoolFilter); + //execute the query + $results = $index->search($query); + + //check the number of results + $this->assertEquals($results->count(), 2, 'Bool filter with child Bool filters: number of results check'); + + //count compare the id's + $ids = array(); + /** @var \Elastica\Result $result **/ + foreach($results as $result){ + $ids[] = $result->getId(); + } + $this->assertEquals($ids, array("2","4"), 'Bool filter with child Bool filters: result ID check'); + + $index->delete(); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/ExistsTests.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/ExistsTests.php new file mode 100644 index 00000000..9e4f5b67 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/ExistsTests.php @@ -0,0 +1,31 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Filter\Exists; +use Elastica\Test\Base as BaseTest; + +class ExistsTest extends BaseTest +{ + public function testToArray() + { + $field = 'test'; + $filter = new Exists($field); + + $expectedArray = array('exists' => array('field' => $field)); + $this->assertEquals($expectedArray, $filter->toArray()); + } + + public function testSetField() + { + $field = 'test'; + $filter = new Exists($field); + + $this->assertEquals($field, $filter->getParam('field')); + + $newField = 'hello world'; + $this->assertInstanceOf('Elastica\Filter\Exists', $filter->setField($newField)); + + $this->assertEquals($newField, $filter->getParam('field')); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoDistanceRangeTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoDistanceRangeTest.php new file mode 100644 index 00000000..4c4d2bcc --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoDistanceRangeTest.php @@ -0,0 +1,218 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Document; +use Elastica\Filter\GeoDistanceRange; +use Elastica\Query; +use Elastica\Query\MatchAll; +use Elastica\Test\Base as BaseTest; + +class GeoDistanceRangeTest extends BaseTest +{ + public function testGeoPoint() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + + $type = $index->getType('test'); + + // Set mapping + $type->setMapping(array('point' => array('type' => 'geo_point'))); + + // Add doc 1 + $doc1 = new Document(1, + array( + 'name' => 'ruflin', + ) + ); + + $doc1->addGeoPoint('point', 17, 19); + $type->addDocument($doc1); + + // Add doc 2 + $doc2 = new Document(2, + array( + 'name' => 'ruflin', + ) + ); + + $doc2->addGeoPoint('point', 30, 40); + $type->addDocument($doc2); + + $index->optimize(); + $index->refresh(); + + // Only one point should be in radius + $query = new Query(); + $geoFilter = new GeoDistanceRange( + 'point', + array('lat' => 30, 'lon' => 40), + array('from' => '0km', 'to' => '2km') + ); + + $query = new Query(new MatchAll()); + $query->setFilter($geoFilter); + $this->assertEquals(1, $type->search($query)->count()); + + // Both points should be inside + $query = new Query(); + $geoFilter = new GeoDistanceRange( + 'point', + array('lat' => 30, 'lon' => 40), + array('gte' => '0km', 'lte' => '40000km') + ); + $query = new Query(new MatchAll()); + $query->setFilter($geoFilter); + $index->refresh(); + + $this->assertEquals(2, $type->search($query)->count()); + } + + /** + * @expectedException \Elastica\Exception\InvalidException + */ + public function testInvalidRange() + { + $geoFilter = new GeoDistanceRange( + 'point', + array('lat' => 30, 'lon' => 40), + array('invalid' => '0km', 'lte' => '40000km') + ); + } + + /** + * @dataProvider invalidLocationDataProvider + * @expectedException \Elastica\Exception\InvalidException + */ + public function testInvalidLocation($location) + { + $geoFilter = new GeoDistanceRange( + 'point', + $location, + array('gt' => '0km', 'lte' => '40000km') + ); + } + + /** + * @dataProvider constructDataProvider + */ + public function testConstruct($key, $location, $ranges, $expected) + { + $filter = new GeoDistanceRange($key, $location, $ranges); + + $data = $filter->toArray(); + + $this->assertEquals($expected, $data); + } + + public function invalidLocationDataProvider() + { + return array( + array( + array('lat' => 1.0), + ), + array( + array('lon' => 1.0), + ), + array( + array(), + ), + array( + new \stdClass(), + ), + array( + null, + ), + array( + true, + ), + array( + false, + ) + ); + } + + public function constructDataProvider() + { + return array( + array( + 'location', + 'u09tvqx', + array( + 'from' => '10km', + 'to' => '20km', + ), + array( + 'geo_distance_range' => array( + 'from' => '10km', + 'to' => '20km', + 'location' => 'u09tvqx', + ) + ) + ), + array( + 'location', + 'u09tvqx', + array( + 'to' => '20km', + 'include_upper' => 0, + 'from' => '10km', + 'include_lower' => 1, + ), + array( + 'geo_distance_range' => array( + 'to' => '20km', + 'include_upper' => false, + 'from' => '10km', + 'include_lower' => true, + 'location' => 'u09tvqx', + ) + ) + ), + array( + 'location', + array( + 'lon' => 2.35, + 'lat' => 48.86, + ), + array( + 'lte' => '20km', + 'gt' => '10km', + ), + array( + 'geo_distance_range' => array( + 'lte' => '20km', + 'gt' => '10km', + 'location' => array( + 'lat' => 48.86, + 'lon' => 2.35, + ), + ) + ) + ), + array( + 'location', + array( + 'lat' => 48.86, + 'lon' => 2.35, + ), + array( + 'lt' => '20km', + 'gte' => '10km', + ), + array( + 'geo_distance_range' => array( + 'lt' => '20km', + 'gte' => '10km', + 'location' => array( + 'lat' => 48.86, + 'lon' => 2.35, + ), + ) + ) + ) + ); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoDistanceTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoDistanceTest.php new file mode 100644 index 00000000..a5049914 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoDistanceTest.php @@ -0,0 +1,129 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Document; +use Elastica\Filter\GeoDistance; +use Elastica\Query; +use Elastica\Query\MatchAll; +use Elastica\Test\Base as BaseTest; + +class GeoDistanceTest extends BaseTest +{ + public function testGeoPoint() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + + $type = $index->getType('test'); + + // Set mapping + $type->setMapping(array('point' => array('type' => 'geo_point'))); + + // Add doc 1 + $doc1 = new Document(1, + array( + 'name' => 'ruflin', + ) + ); + + $doc1->addGeoPoint('point', 17, 19); + $type->addDocument($doc1); + + // Add doc 2 + $doc2 = new Document(2, + array( + 'name' => 'ruflin', + ) + ); + + $doc2->addGeoPoint('point', 30, 40); + $type->addDocument($doc2); + + $index->optimize(); + $index->refresh(); + + // Only one point should be in radius + $query = new Query(); + $geoFilter = new GeoDistance('point', array('lat' => 30, 'lon' => 40), '1km'); + + $query = new Query(new MatchAll()); + $query->setFilter($geoFilter); + $this->assertEquals(1, $type->search($query)->count()); + + // Both points should be inside + $query = new Query(); + $geoFilter = new GeoDistance('point', array('lat' => 30, 'lon' => 40), '40000km'); + $query = new Query(new MatchAll()); + $query->setFilter($geoFilter); + $index->refresh(); + + $this->assertEquals(2, $type->search($query)->count()); + } + + public function testConstructLatlon() + { + $key = 'location'; + $location = array( + 'lat' => 48.86, + 'lon' => 2.35 + ); + $distance = '10km'; + + $filter = new GeoDistance($key, $location, $distance); + + $expected = array( + 'geo_distance' => array( + $key => $location, + 'distance' => $distance + ) + ); + + $data = $filter->toArray(); + + $this->assertEquals($expected, $data); + } + + public function testConstructGeohash() + { + $key = 'location'; + $location = 'u09tvqx'; + $distance = '10km'; + + $filter = new GeoDistance($key, $location, $distance); + + $expected = array( + 'geo_distance' => array( + $key => $location, + 'distance' => $distance + ) + ); + + $data = $filter->toArray(); + + $this->assertEquals($expected, $data); + } + + public function testSetDistanceType() + { + $filter = new GeoDistance('location', array('lat' => 48.86, 'lon' => 2.35), '10km'); + $distanceType = GeoDistance::DISTANCE_TYPE_ARC; + $filter->setDistanceType($distanceType); + + $data = $filter->toArray(); + + $this->assertEquals($distanceType, $data['geo_distance']['distance_type']); + } + + public function testSetOptimizeBbox() + { + $filter = new GeoDistance('location', array('lat' => 48.86, 'lon' => 2.35), '10km'); + $optimizeBbox = GeoDistance::OPTIMIZE_BBOX_MEMORY; + $filter->setOptimizeBbox($optimizeBbox); + + $data = $filter->toArray(); + + $this->assertEquals($optimizeBbox, $data['geo_distance']['optimize_bbox']); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoPolygonTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoPolygonTest.php new file mode 100644 index 00000000..7ebd738c --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoPolygonTest.php @@ -0,0 +1,65 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Document; +use Elastica\Filter\GeoPolygon; +use Elastica\Query; +use Elastica\Query\MatchAll; +use Elastica\Test\Base as BaseTest; + +class GeoPolygonTest extends BaseTest +{ + public function testGeoPoint() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + + $type = $index->getType('test'); + + // Set mapping + $type->setMapping(array('location' => array('type' => 'geo_point'))); + + // Add doc 1 + $doc1 = new Document(1, + array( + 'name' => 'ruflin', + ) + ); + + $doc1->addGeoPoint('location', 17, 19); + $type->addDocument($doc1); + + // Add doc 2 + $doc2 = new Document(2, + array( + 'name' => 'ruflin', + ) + ); + + $doc2->addGeoPoint('location', 30, 40); + $type->addDocument($doc2); + + $index->refresh(); + + // Only one point should be in polygon + $query = new Query(); + $points = array(array(16, 16), array(16, 20), array(20, 20), array(20, 16), array(16, 16)); + $geoFilter = new GeoPolygon('location', $points); + + $query = new Query(new MatchAll()); + $query->setFilter($geoFilter); + $this->assertEquals(1, $type->search($query)->count()); + + // Both points should be inside + $query = new Query(); + $points = array(array(16, 16), array(16, 40), array(40, 40), array(40, 16), array(16, 16)); + $geoFilter = new GeoPolygon('location', $points); + + $query = new Query(new MatchAll()); + $query->setFilter($geoFilter); + + $this->assertEquals(2, $type->search($query)->count()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoShapePreIndexedTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoShapePreIndexedTest.php new file mode 100644 index 00000000..21afec1a --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoShapePreIndexedTest.php @@ -0,0 +1,90 @@ +<?php + + +namespace Elastica\Test\Filter; + +use Elastica\Filter\AbstractGeoShape; +use Elastica\Filter\GeoShapePreIndexed; +use Elastica\Query\MatchAll; +use Elastica\Query\Filtered; +use Elastica\Test\Base as BaseTest; + +class GeoShapePreIndexedTest extends BaseTest +{ + public function testGeoProvided() + { + $indexName = 'geo_shape_filter_test'; + $index = $this->_createIndex($indexName); + $type = $index->getType('type'); + $otherType = $index->getType('other_type'); + + // create mapping + $mapping = new \Elastica\Type\Mapping($type, array( + 'location' => array( + 'type' => 'geo_shape' + ) + )); + $type->setMapping($mapping); + + // create other type mapping + $otherMapping = new \Elastica\Type\Mapping($type, array( + 'location' => array( + 'type' => 'geo_shape' + ) + )); + $otherType->setMapping($otherMapping); + + // add type docs + $type->addDocument(new \Elastica\Document('1', array( + 'location' => array( + "type" => "envelope", + "coordinates" => array( + array(0.0, 50.0), + array(50.0, 0.0) + ) + ) + ))); + + // add other type docs + $otherType->addDocument(new \Elastica\Document('2', array( + 'location' => array( + "type" => "envelope", + "coordinates" => array( + array(25.0, 75.0), + array(75.0, 25.0) + ) + ) + ))); + + $index->optimize(); + $index->refresh(); + + $gsp = new GeoShapePreIndexed( + 'location', '1', 'type', 'elastica_'.$indexName, 'location' + ); + $gsp->setRelation(AbstractGeoShape::RELATION_INTERSECT); + + $expected = array( + 'geo_shape' => array( + 'location' => array( + 'indexed_shape' => array( + 'id' => '1', + 'type' => 'type', + 'index' => 'elastica_'.$indexName, + 'path' => 'location' + ), + 'relation' => $gsp->getRelation() + ) + ) + ); + + $this->assertEquals($expected, $gsp->toArray()); + + $query = new Filtered(new MatchAll(), $gsp); + $results = $index->getType('type')->search($query); + + $this->assertEquals(1, $results->count()); + + $index->delete(); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoShapeProvidedTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoShapeProvidedTest.php new file mode 100644 index 00000000..146150a3 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoShapeProvidedTest.php @@ -0,0 +1,88 @@ +<?php + + +namespace Elastica\Test\Filter; + +use Elastica\Filter\AbstractGeoShape; +use Elastica\Filter\GeoShapeProvided; +use Elastica\Query\Filtered; +use Elastica\Query\MatchAll; +use Elastica\Test\Base as BaseTest; + +class GeoShapeProvidedTest extends BaseTest +{ + public function testConstructEnvelope() + { + $index = $this->_createIndex('geo_shape_filter_test'); + $type = $index->getType('test'); + + // create mapping + $mapping = new \Elastica\Type\Mapping($type, array( + 'location' => array( + 'type' => 'geo_shape' + ) + )); + $type->setMapping($mapping); + + // add docs + $type->addDocument(new \Elastica\Document(1, array( + 'location' => array( + "type" => "envelope", + "coordinates" => array( + array(-50.0, 50.0), + array(50.0, -50.0) + ) + ) + ))); + + $index->optimize(); + $index->refresh(); + + $envelope = array( + array(25.0, 75.0), + array(75.0, 25.0) + ); + $gsp = new GeoShapeProvided('location', $envelope); + + $expected = array( + 'geo_shape' => array( + 'location' => array( + 'shape' => array( + 'type' => GeoShapeProvided::TYPE_ENVELOPE, + 'coordinates' => $envelope + ), + 'relation' => AbstractGeoShape::RELATION_INTERSECT + ), + ) + ); + + $this->assertEquals($expected, $gsp->toArray()); + + $query = new Filtered(new MatchAll(), $gsp); + $results = $type->search($query); + + $this->assertEquals(1, $results->count()); + + $index->delete(); + } + + public function testConstructPolygon() + { + $polygon = array(array(102.0, 2.0), array(103.0, 2.0), array(103.0, 3.0), array(103.0, 3.0), array(102.0, 2.0)); + $gsp = new GeoShapeProvided('location', $polygon, GeoShapeProvided::TYPE_POLYGON); + + $expected = array( + 'geo_shape' => array( + 'location' => array( + 'shape' => array( + 'type' => GeoShapeProvided::TYPE_POLYGON, + 'coordinates' => $polygon + ), + 'relation' => $gsp->getRelation() + ), + ) + ); + + $this->assertEquals($expected, $gsp->toArray()); + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeohashCellTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeohashCellTest.php new file mode 100644 index 00000000..7cb8aef6 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeohashCellTest.php @@ -0,0 +1,60 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Test\Base as BaseTest; +use Elastica\Filter\GeohashCell; + +class GeohashCellTest extends BaseTest +{ + public function testToArray() + { + $filter = new GeohashCell('pin', array('lat' => 37.789018, 'lon' => -122.391506), '50m'); + $expected = array( + 'geohash_cell' => array( + 'pin' => array( + 'lat' => 37.789018, + 'lon' => -122.391506 + ), + 'precision' => '50m', + 'neighbors' => false + ) + ); + $this->assertEquals($expected, $filter->toArray()); + } + + public function testFilter() + { + $index = $this->_createIndex('geohash_filter_test'); + $type = $index->getType('test'); + $mapping = new \Elastica\Type\Mapping($type, array( + 'pin' => array( + 'type' => 'geo_point', + 'geohash' => true, + 'geohash_prefix' => true + ) + )); + $type->setMapping($mapping); + + $type->addDocument(new \Elastica\Document(1, array('pin' => '9q8yyzm0zpw8'))); + $type->addDocument(new \Elastica\Document(2, array('pin' => '9mudgb0yued0'))); + $index->refresh(); + + $filter = new GeohashCell('pin', array('lat' => 32.828326, 'lon' => -117.255854)); + $query = new \Elastica\Query(); + $query->setFilter($filter); + $results = $type->search($query); + + $this->assertEquals(1, $results->count()); + + //test precision parameter + $filter = new GeohashCell('pin', '9', 1); + $query = new \Elastica\Query(); + $query->setFilter($filter); + $results = $type->search($query); + + $this->assertEquals(2, $results->count()); + + $index->delete(); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/HasChildTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/HasChildTest.php new file mode 100644 index 00000000..8bba8173 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/HasChildTest.php @@ -0,0 +1,166 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Document; +use Elastica\Filter\HasChild; +use Elastica\Query\MatchAll; +use Elastica\Test\Base as BaseTest; + +class HasChildTest extends BaseTest +{ + public function testToArray() + { + $q = new MatchAll(); + + $type = 'test'; + + $filter = new HasChild($q, $type); + + $expectedArray = array( + 'has_child' => array( + 'query' => $q->toArray(), + 'type' => $type + ) + ); + + $this->assertEquals($expectedArray, $filter->toArray()); + } + + public function testSetScope() + { + $q = new MatchAll(); + + $type = 'test'; + + $scope = 'foo'; + + $filter = new HasChild($q, $type); + $filter->setScope($scope); + + $expectedArray = array( + 'has_child' => array( + 'query' => $q->toArray(), + 'type' => $type, + '_scope' => $scope + ) + ); + + $this->assertEquals($expectedArray, $filter->toArray()); + } + + public function testFilterInsideHasChild() + { + $f = new \Elastica\Filter\MatchAll(); + + $type = 'test'; + + $filter = new HasChild($f, $type); + + $expectedArray = array( + 'has_child' => array( + 'filter' => $f->toArray(), + 'type' => $type + ) + ); + + $this->assertEquals($expectedArray, $filter->toArray()); + + } + + public function testFilterInsideHasChildSearch() + { + $index = $this->prepareSearchData(); + + $f = new \Elastica\Filter\Term(); + $f->setTerm('user', 'child1'); + $filter = new HasChild($f, 'child'); + + $searchQuery = new \Elastica\Query(); + $searchQuery->setFilter($filter); + $searchResults = $index->search($searchQuery); + + $this->assertEquals(1, $searchResults->count()); + + $result = $searchResults->current()->getData(); + $expected = array('id' => 'parent1', 'user' => 'parent1', 'email' => 'parent1@test.com'); + + $this->assertEquals($expected, $result); + } + + public function testQueryInsideHasChildSearch() + { + $index = $this->prepareSearchData(); + + $f = new \Elastica\Query\Term(); + $f->setTerm('user', 'child1'); + $filter = new HasChild($f, 'child'); + + $searchQuery = new \Elastica\Query(); + $searchQuery->setFilter($filter); + $searchResults = $index->search($searchQuery); + + $this->assertEquals(1, $searchResults->count()); + + $result = $searchResults->current()->getData(); + $expected = array('id' => 'parent1', 'user' => 'parent1', 'email' => 'parent1@test.com'); + + $this->assertEquals($expected, $result); + } + + public function testTypeInsideHasChildSearch() + { + $index = $this->prepareSearchData(); + + $f = new \Elastica\Query\Match(); + $f->setField('alt.name', 'testname'); + $filter = new HasChild($f, 'child'); + + $searchQuery = new \Elastica\Query(); + $searchQuery->setFilter($filter); + $searchResults = $index->search($searchQuery); + + $this->assertEquals(1, $searchResults->count()); + + $result = $searchResults->current()->getData(); + $expected = array('id' => 'parent2', 'user' => 'parent2', 'email' => 'parent2@test.com'); + + $this->assertEquals($expected, $result); + } + + private function prepareSearchData() + { + $client = $this->_getClient(); + $index = $client->getIndex('has_child_test'); + $index->create(array(), true); + + $parentType = $index->getType('parent'); + + $childType = $index->getType('child'); + $childMapping = new \Elastica\Type\Mapping($childType); + $childMapping->setParent('parent'); + $childMapping->send(); + + $altType = $index->getType('alt'); + $altDoc = new Document('alt1', array('name' => 'altname')); + $altType->addDocument($altDoc); + + $parent1 = new Document('parent1', array('id' => 'parent1', 'user' => 'parent1', 'email' => 'parent1@test.com')); + $parentType->addDocument($parent1); + $parent2 = new Document('parent2', array('id' => 'parent2', 'user' => 'parent2', 'email' => 'parent2@test.com')); + $parentType->addDocument($parent2); + + $child1 = new Document('child1', array('id' => 'child1', 'user' => 'child1', 'email' => 'child1@test.com')); + $child1->setParent('parent1'); + $childType->addDocument($child1); + $child2 = new Document('child2', array('id' => 'child2', 'user' => 'child2', 'email' => 'child2@test.com')); + $child2->setParent('parent2'); + $childType->addDocument($child2); + $child3 = new Document('child3', array('id' => 'child3', 'user' => 'child3', 'email' => 'child3@test.com', 'alt' => array(array('name' => 'testname')))); + $child3->setParent('parent2'); + $childType->addDocument($child3); + + $index->refresh(); + return $index; + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/HasParentTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/HasParentTest.php new file mode 100644 index 00000000..7998372b --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/HasParentTest.php @@ -0,0 +1,139 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Document; +use Elastica\Filter\HasParent; +use Elastica\Query\MatchAll; +use Elastica\Test\Base as BaseTest; + +class HasParentTest extends BaseTest +{ + public function testToArray() + { + $q = new MatchAll(); + + $type = 'test'; + + $filter = new HasParent($q, $type); + + $expectedArray = array( + 'has_parent' => array( + 'query' => $q->toArray(), + 'type' => $type + ) + ); + + $this->assertEquals($expectedArray, $filter->toArray()); + } + + public function testSetScope() + { + $q = new MatchAll(); + + $type = 'test'; + + $scope = 'foo'; + + $filter = new HasParent($q, $type); + $filter->setScope($scope); + + $expectedArray = array( + 'has_parent' => array( + 'query' => $q->toArray(), + 'type' => $type, + '_scope' => $scope + ) + ); + + $this->assertEquals($expectedArray, $filter->toArray()); + } + + public function testFilterInsideHasParent() + { + $f = new \Elastica\Filter\MatchAll(); + + $type = 'test'; + + $filter = new HasParent($f, $type); + + $expectedArray = array( + 'has_parent' => array( + 'filter' => $f->toArray(), + 'type' => $type + ) + ); + + $this->assertEquals($expectedArray, $filter->toArray()); + + } + + public function testFilterInsideHasParentSearch() + { + $index = $this->prepareSearchData(); + + $f = new \Elastica\Filter\Term(); + $f->setTerm('user', 'parent1'); + $filter = new HasParent($f, 'parent'); + + $searchQuery = new \Elastica\Query(); + $searchQuery->setFilter($filter); + $searchResults = $index->search($searchQuery); + + $this->assertEquals(1, $searchResults->count()); + + $result = $searchResults->current()->getData(); + $expected = array('id' => 'child1', 'user' => 'child1', 'email' => 'child1@test.com'); + + $this->assertEquals($expected, $result); + } + + public function testQueryInsideHasParentSearch() + { + $index = $this->prepareSearchData(); + + $f = new \Elastica\Query\Term(); + $f->setTerm('user', 'parent1'); + $filter = new HasParent($f, 'parent'); + + $searchQuery = new \Elastica\Query(); + $searchQuery->setFilter($filter); + $searchResults = $index->search($searchQuery); + + $this->assertEquals(1, $searchResults->count()); + + $result = $searchResults->current()->getData(); + $expected = array('id' => 'child1', 'user' => 'child1', 'email' => 'child1@test.com'); + + $this->assertEquals($expected, $result); + } + + private function prepareSearchData() + { + $client = $this->_getClient(); + $index = $client->getIndex('has_parent_test'); + $index->create(array(), true); + + $parentType = $index->getType('parent'); + + $childType = $index->getType('child'); + $childMapping = new \Elastica\Type\Mapping($childType); + $childMapping->setParent('parent'); + $childMapping->send(); + + $parent1 = new Document('parent1', array('id' => 'parent1', 'user' => 'parent1', 'email' => 'parent1@test.com')); + $parentType->addDocument($parent1); + $parent2 = new Document('parent2', array('id' => 'parent2', 'user' => 'parent2', 'email' => 'parent2@test.com')); + $parentType->addDocument($parent2); + + $child1 = new Document('child1', array('id' => 'child1', 'user' => 'child1', 'email' => 'child1@test.com')); + $child1->setParent('parent1'); + $childType->addDocument($child1); + $child2 = new Document('child2', array('id' => 'child2', 'user' => 'child2', 'email' => 'child2@test.com')); + $child2->setParent('parent2'); + $childType->addDocument($child2); + + $index->refresh(); + return $index; + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/IdsTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/IdsTest.php new file mode 100644 index 00000000..3d6af870 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/IdsTest.php @@ -0,0 +1,201 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Document; +use Elastica\Filter\Ids; +use Elastica\Filter\Type; +use Elastica\Query; +use Elastica\Test\Base as BaseTest; + +class IdsTest extends BaseTest +{ + protected $_index; + protected $_type; + + public function setUp() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + + $type1 = $index->getType('helloworld1'); + $type2 = $index->getType('helloworld2'); + + // Add documents to first type + for ($i = 1; $i < 100; $i++) { + $doc = new Document($i, array('name' => 'ruflin')); + $type1->addDocument($doc); + } + + // Add documents to second type + for ($i = 1; $i < 100; $i++) { + $doc = new Document($i, array('name' => 'ruflin')); + $type2->addDocument($doc); + } + + // This is a special id that will only be in the second type + $doc = new Document('101', array('name' => 'ruflin')); + $type2->addDocument($doc); + + $index->optimize(); + $index->refresh(); + + $this->_type = $type1; + $this->_index = $index; + } + + public function tearDown() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->delete(); + } + + public function testSetIdsSearchSingle() + { + $filter = new Ids(); + $filter->setIds('1'); + + $query = Query::create($filter); + $resultSet = $this->_type->search($query); + + $this->assertEquals(1, $resultSet->count()); + } + + public function testSetIdsSearchArray() + { + $filter = new Ids(); + $filter->setIds(array(1, 7, 13)); + + $query = Query::create($filter); + $resultSet = $this->_type->search($query); + + $this->assertEquals(3, $resultSet->count()); + } + + public function testAddIdsSearchSingle() + { + $filter = new Ids(); + $filter->addId('39'); + + $query = Query::create($filter); + $resultSet = $this->_type->search($query); + + $this->assertEquals(1, $resultSet->count()); + } + + public function testAddIdsSearchSingleNotInType() + { + $filter = new Ids(); + $filter->addId('39'); + + // Add an ID that is not in the index + $filter->addId(104); + + $query = Query::create($filter); + $resultSet = $this->_type->search($query); + + $this->assertEquals(1, $resultSet->count()); + } + + public function testComboIdsSearchArray() + { + $filter = new Ids(); + $filter->setIds(array(1, 7, 13)); + $filter->addId('39'); + + $query = Query::create($filter); + $resultSet = $this->_type->search($query); + + $this->assertEquals(4, $resultSet->count()); + } + + public function testSetTypeSingleSearchSingle() + { + $filter = new Ids(); + $filter->setIds('1'); + $filter->setType('helloworld1'); + + $query = Query::create($filter); + $resultSet = $this->_index->search($query); + + $this->assertEquals(1, $resultSet->count()); + } + + public function testSetTypeSingleSearchArray() + { + $filter = new Ids(); + $filter->setIds(array('1', '2')); + $filter->setType('helloworld1'); + + $query = Query::create($filter); + $resultSet = $this->_index->search($query); + + $this->assertEquals(2, $resultSet->count()); + } + + public function testSetTypeSingleSearchSingleDocInOtherType() + { + $filter = new Ids(); + + // Doc 4 is in the second type... + $filter->setIds('101'); + $filter->setType('helloworld1'); + + $query = Query::create($filter); + $resultSet = $this->_type->search($query); + + // ...therefore 0 results should be returned + $this->assertEquals(0, $resultSet->count()); + } + + public function testSetTypeSingleSearchArrayDocInOtherType() + { + $filter = new Ids(); + + // Doc 4 is in the second type... + $filter->setIds(array('1', '101')); + $filter->setType('helloworld1'); + + $query = Query::create($filter); + $resultSet = $this->_type->search($query); + + // ...therefore only 1 result should be returned + $this->assertEquals(1, $resultSet->count()); + } + + public function testSetTypeArraySearchArray() + { + $filter = new Ids(); + $filter->setIds(array('1', '4')); + $filter->setType(array('helloworld1', 'helloworld2')); + + $query = Query::create($filter); + $resultSet = $this->_index->search($query); + + $this->assertEquals(4, $resultSet->count()); + } + + public function testSetTypeArraySearchSingle() + { + $filter = new Ids(); + $filter->setIds('4'); + $filter->setType(array('helloworld1', 'helloworld2')); + + $query = Query::create($filter); + $resultSet = $this->_index->search($query); + + $this->assertEquals(2, $resultSet->count()); + } + + public function testFilterTypeAndTypeCollision() + { + // This test ensures that Elastica\Type and Elastica\Filter\Type + // do not collide when used together, which at one point + // happened because of a use statement in Elastica\Filter\Ids + // Test goal is to make sure a Fatal Error is not triggered + $filterType = new Type(); + $filter = new Ids(); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/IndicesTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/IndicesTest.php new file mode 100644 index 00000000..b682a5ce --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/IndicesTest.php @@ -0,0 +1,93 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Document; +use Elastica\Filter\BoolNot; +use Elastica\Filter\Indices; +use Elastica\Filter\Term; +use Elastica\Index; +use Elastica\Query; +use Elastica\Test\Base as BaseTest; + +class IndicesTest extends BaseTest +{ + /** + * @var Index + */ + protected $_index1; + + /** + * @var Index + */ + protected $_index2; + + protected function setUp() + { + parent::setUp(); + $this->_index1 = $this->_createIndex('indices_filter_1'); + $this->_index2 = $this->_createIndex('indices_filter_2'); + $this->_index1->addAlias("indices_filter"); + $this->_index2->addAlias("indices_filter"); + $docs = array( + new Document("1", array("color" => "blue")), + new Document("2", array("color" => "green")), + new Document("3", array("color" => "blue")), + new Document("4", array("color" => "yellow")), + ); + $this->_index1->getType("test")->addDocuments($docs); + $this->_index2->getType("test")->addDocuments($docs); + $this->_index1->refresh(); + $this->_index2->refresh(); + } + + protected function tearDown() + { + $this->_index1->delete(); + $this->_index2->delete(); + parent::tearDown(); + } + + public function testToArray() + { + $expected = array( + "indices" => array( + "indices" => array("index1", "index2"), + "filter" => array( + "term" => array("tag" => "wow") + ), + "no_match_filter" => array( + "term" => array("tag" => "such filter") + ) + ) + ); + $filter = new Indices(new Term(array("tag" => "wow")), array("index1", "index2")); + $filter->setNoMatchFilter(new Term(array("tag" => "such filter"))); + $this->assertEquals($expected, $filter->toArray()); + } + + public function testIndicesFilter() + { + $filter = new Indices(new BoolNot(new Term(array("color" => "blue"))), array($this->_index1->getName())); + $filter->setNoMatchFilter(new BoolNot(new Term(array("color" => "yellow")))); + $query = new Query(); + $query->setFilter($filter); + + // search over the alias + $index = $this->_getClient()->getIndex("indices_filter"); + $results = $index->search($query); + + // ensure that the proper docs have been filtered out for each index + $this->assertEquals(5, $results->count()); + foreach ($results->getResults() as $result) { + $data = $result->getData(); + $color = $data["color"]; + if ($result->getIndex() == $this->_index1->getName()) { + $this->assertNotEquals("blue", $color); + } else { + $this->assertNotEquals("yellow", $color); + } + } + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/MatchAllTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/MatchAllTest.php new file mode 100644 index 00000000..6696f11d --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/MatchAllTest.php @@ -0,0 +1,18 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Filter\MatchAll; +use Elastica\Test\Base as BaseTest; + +class MatchAllTest extends BaseTest +{ + public function testToArray() + { + $filter = new MatchAll(); + + $expectedArray = array('match_all' => new \stdClass()); + + $this->assertEquals($expectedArray, $filter->toArray()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/MultiTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/MultiTest.php new file mode 100644 index 00000000..f6513338 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/MultiTest.php @@ -0,0 +1,95 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Filter\AbstractMulti; +use Elastica\Filter\MatchAll; +use Elastica\Test\Base as BaseTest; + +class AbstractMultiTest extends BaseTest +{ + public function testConstruct() + { + $stub = $this->getStub(); + + $this->assertEmpty($stub->getFilters()); + } + + public function testAddFilter() + { + $stub = $this->getStub(); + + $filter = new MatchAll(); + $stub->addFilter($filter); + + $expected = array( + $filter->toArray() + ); + + $this->assertEquals($expected, $stub->getFilters()); + } + + public function testSetFilters() + { + $stub = $this->getStub(); + + $filter = new MatchAll(); + $stub->setFilters(array($filter)); + + $expected = array( + $filter->toArray() + ); + + $this->assertEquals($expected, $stub->getFilters()); + } + + public function testToArray() + { + $stub = $this->getStub(); + + $filter = new MatchAll(); + $stub->addFilter($filter); + + $expected = array( + $stub->getBaseName() => array( + $filter->toArray() + ) + ); + + $this->assertEquals($expected, $stub->toArray()); + } + + public function testToArrayWithParam() + { + $stub = $this->getStub(); + + $stub->setCached(true); + + $filter = new MatchAll(); + $stub->addFilter($filter); + + $expected = array( + $stub->getBaseName() => array( + '_cache' => true, + 'filters' => array( + $filter->toArray() + ) + ) + ); + + $this->assertEquals($expected, $stub->toArray()); + } + + private function getStub() + { + return $this->getMockForAbstractClass('Elastica\Test\Filter\AbstractMultiDebug'); + } +} + +class AbstractMultiDebug extends AbstractMulti +{ + public function getBaseName() + { + return parent::_getBaseName(); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/NestedFilterWithSetFilterTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/NestedFilterWithSetFilterTest.php new file mode 100644 index 00000000..12dbb598 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/NestedFilterWithSetFilterTest.php @@ -0,0 +1,121 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Document; +use Elastica\Filter\Nested; +use Elastica\Filter\Terms; +use Elastica\Search; +use Elastica\Type\Mapping; +use Elastica\Test\Base as BaseTest; + +class NestedFilterWithSetFilterTest extends BaseTest +{ + public function setUp() + { + $client = $this->_getClient(); + $index = $client->getIndex('elastica_test_filter_nested_abstract_filter'); + $index->create(array(), true); + $type = $index->getType('user'); + $mapping = new Mapping(); + $mapping->setProperties( + array( + 'firstname' => array('type' => 'string', 'store' => 'yes'), + // default is store => no expected + 'lastname' => array('type' => 'string'), + 'hobbies' => array( + 'type' => 'nested', + 'include_in_parent' => true, + 'properties' => array('hobby' => array('type' => 'string')) + ) + ) + ); + $type->setMapping($mapping); + + // Adds a list of documents with _bulk upload to the index + $docs = array(); + $docs[] = new Document(1, + array( + 'firstname' => 'Nicolas', + 'lastname' => 'Ruflin', + 'hobbies' => array( + array('hobby' => 'opensource') + ) + ) + ); + $docs[] = new Document(2, + array( + 'firstname' => 'Nicolas', + 'lastname' => 'Ippolito', + 'hobbies' => array( + array('hobby' => 'opensource'), + array('hobby' => 'guitar'), + ) + ) + ); + $response = $type->addDocuments($docs); + + // Refresh index + $index->refresh(); + } + + public function tearDown() + { + $client = $this->_getClient(); + $index = $client->getIndex('elastica_test_filter_nested_abstract_filter'); + $index->delete(); + } + + public function testToArray() + { + $f = new Nested(); + $this->assertEquals(array('nested' => array()), $f->toArray()); + $q = new Terms(); + $q->setTerms('hobby', array('guitar')); + $f->setPath('hobbies'); + $f->setFilter($q); + + $expectedArray = array( + 'nested' => array( + 'path' => 'hobbies', + 'filter' => array('terms' => array( + 'hobby' => array('guitar') + )) + ) + ); + + $this->assertEquals($expectedArray, $f->toArray()); + } + + public function testShouldReturnTheRightNumberOfResult() + { + $f = new Nested(); + $this->assertEquals(array('nested' => array()), $f->toArray()); + $q = new Terms(); + $q->setTerms('hobby', array('guitar')); + $f->setPath('hobbies'); + $f->setFilter($q); + + $c = $this->_getClient(); + $s = new Search($c); + $i = $c->getIndex('elastica_test_filter_nested_abstract_filter'); + $s->addIndex($i); + $r = $s->search($f); + + $this->assertEquals(1, $r->getTotalHits()); + + $f = new Nested(); + $this->assertEquals(array('nested' => array()), $f->toArray()); + $q = new Terms(); + $q->setTerms('hobby', array('opensource')); + $f->setPath('hobbies'); + $f->setFilter($q); + + $c = $this->_getClient(); + $s = new Search($c); + $i = $c->getIndex('elastica_test_filter_nested_abstract_filter'); + $s->addIndex($i); + $r = $s->search($f); + $this->assertEquals(2, $r->getTotalHits()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/NestedTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/NestedTest.php new file mode 100644 index 00000000..8d0d2004 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/NestedTest.php @@ -0,0 +1,121 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Document; +use Elastica\Filter\Nested; +use Elastica\Query\Terms; +use Elastica\Search; +use Elastica\Type\Mapping; +use Elastica\Test\Base as BaseTest; + +class NestedTest extends BaseTest +{ + public function setUp() + { + $client = $this->_getClient(); + $index = $client->getIndex('elastica_test_filter_nested'); + $index->create(array(), true); + $type = $index->getType('user'); + $mapping = new Mapping(); + $mapping->setProperties( + array( + 'firstname' => array('type' => 'string', 'store' => 'yes'), + // default is store => no expected + 'lastname' => array('type' => 'string'), + 'hobbies' => array( + 'type' => 'nested', + 'include_in_parent' => true, + 'properties' => array('hobby' => array('type' => 'string')) + ) + ) + ); + $type->setMapping($mapping); + + // Adds a list of documents with _bulk upload to the index + $docs = array(); + $docs[] = new Document(1, + array( + 'firstname' => 'Nicolas', + 'lastname' => 'Ruflin', + 'hobbies' => array( + array('hobby' => 'opensource') + ) + ) + ); + $docs[] = new Document(2, + array( + 'firstname' => 'Nicolas', + 'lastname' => 'Ippolito', + 'hobbies' => array( + array('hobby' => 'opensource'), + array('hobby' => 'guitar'), + ) + ) + ); + $response = $type->addDocuments($docs); + + // Refresh index + $index->refresh(); + } + + public function tearDown() + { + $client = $this->_getClient(); + $index = $client->getIndex('elastica_test_filter_nested'); + $index->delete(); + } + + public function testToArray() + { + $f = new Nested(); + $this->assertEquals(array('nested' => array()), $f->toArray()); + $q = new Terms(); + $q->setTerms('hobby', array('guitar')); + $f->setPath('hobbies'); + $f->setQuery($q); + + $expectedArray = array( + 'nested' => array( + 'path' => 'hobbies', + 'query' => array('terms' => array( + 'hobby' => array('guitar') + )) + ) + ); + + $this->assertEquals($expectedArray, $f->toArray()); + } + + public function testShouldReturnTheRightNumberOfResult() + { + $f = new Nested(); + $this->assertEquals(array('nested' => array()), $f->toArray()); + $q = new Terms(); + $q->setTerms('hobby', array('guitar')); + $f->setPath('hobbies'); + $f->setQuery($q); + + $c = $this->_getClient(); + $s = new Search($c); + $i = $c->getIndex('elastica_test_filter_nested'); + $s->addIndex($i); + $r = $s->search($f); + + $this->assertEquals(1, $r->getTotalHits()); + + $f = new Nested(); + $this->assertEquals(array('nested' => array()), $f->toArray()); + $q = new Terms(); + $q->setTerms('hobby', array('opensource')); + $f->setPath('hobbies'); + $f->setQuery($q); + + $c = $this->_getClient(); + $s = new Search($c); + $i = $c->getIndex('elastica_test_filter_nested'); + $s->addIndex($i); + $r = $s->search($f); + $this->assertEquals(2, $r->getTotalHits()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/NumericRangeTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/NumericRangeTest.php new file mode 100644 index 00000000..6cc2de06 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/NumericRangeTest.php @@ -0,0 +1,32 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Filter\NumericRange; +use Elastica\Test\Base as BaseTest; + +class NumericRangeTest extends BaseTest +{ + public function testAddField() + { + $rangeFilter = new NumericRange(); + $returnValue = $rangeFilter->addField('fieldName', array('to' => 'value')); + $this->assertInstanceOf('Elastica\Filter\NumericRange', $returnValue); + } + + public function testToArray() + { + $filter = new NumericRange(); + + $fromTo = array('from' => 'ra', 'to' => 'ru'); + $filter->addField('name', $fromTo); + + $expectedArray = array( + 'numeric_range' => array( + 'name' => $fromTo + ) + ); + + $this->assertEquals($expectedArray, $filter->toArray()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/PrefixTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/PrefixTest.php new file mode 100644 index 00000000..16362140 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/PrefixTest.php @@ -0,0 +1,149 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Document; +use Elastica\Filter\Prefix; +use Elastica\Type\Mapping; +use Elastica\Test\Base as BaseTest; + +class PrefixTest extends BaseTest +{ + public function testToArray() + { + $field = 'name'; + $prefix = 'ruf'; + + $filter = new Prefix($field, $prefix); + + $expectedArray = array( + 'prefix' => array( + $field => $prefix + ) + ); + + $this->assertequals($expectedArray, $filter->toArray()); + } + + public function testDifferentPrefixes() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + + /*$indexParams = array( + 'analysis' => array( + 'analyzer' => array( + 'lw' => array( + 'type' => 'custom', + 'tokenizer' => 'keyword', + 'filter' => array('lowercase') + ) + ), + ) + );*/ + + $index->create(array(), true); + $type = $index->getType('test'); + + $mapping = new Mapping($type, array( + 'name' => array('type' => 'string', 'store' => 'no', 'index' => 'not_analyzed'), + ) + ); + $type->setMapping($mapping); + + $doc = new Document(1, array('name' => 'Basel-Stadt')); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'New York')); + $type->addDocument($doc); + $doc = new Document(3, array('name' => 'Baden')); + $type->addDocument($doc); + $doc = new Document(4, array('name' => 'Baden Baden')); + $type->addDocument($doc); + $doc = new Document(5, array('name' => 'New Orleans')); + $type->addDocument($doc); + + $index->refresh(); + + $query = new Prefix('name', 'Ba'); + $resultSet = $index->search($query); + $this->assertEquals(3, $resultSet->count()); + + // Lower case should not return a result + $query = new Prefix('name', 'ba'); + $resultSet = $index->search($query); + $this->assertEquals(0, $resultSet->count()); + + $query = new Prefix('name', 'Baden'); + $resultSet = $index->search($query); + $this->assertEquals(2, $resultSet->count()); + + $query = new Prefix('name', 'Baden B'); + $resultSet = $index->search($query); + $this->assertEquals(1, $resultSet->count()); + + $query = new Prefix('name', 'Baden Bas'); + $resultSet = $index->search($query); + $this->assertEquals(0, $resultSet->count()); + } + + public function testDifferentPrefixesLowercase() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + + $indexParams = array( + 'analysis' => array( + 'analyzer' => array( + 'lw' => array( + 'type' => 'custom', + 'tokenizer' => 'keyword', + 'filter' => array('lowercase') + ) + ), + ) + ); + + $index->create($indexParams, true); + $type = $index->getType('test'); + + $mapping = new Mapping($type, array( + 'name' => array('type' => 'string', 'store' => 'no', 'analyzer' => 'lw'), + ) + ); + $type->setMapping($mapping); + + $doc = new Document(1, array('name' => 'Basel-Stadt')); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'New York')); + $type->addDocument($doc); + $doc = new Document(3, array('name' => 'Baden')); + $type->addDocument($doc); + $doc = new Document(4, array('name' => 'Baden Baden')); + $type->addDocument($doc); + $doc = new Document(5, array('name' => 'New Orleans')); + $type->addDocument($doc); + + $index->refresh(); + + $query = new Prefix('name', 'ba'); + $resultSet = $index->search($query); + $this->assertEquals(3, $resultSet->count()); + + // Upper case should not return a result + $query = new Prefix('name', 'Ba'); + $resultSet = $index->search($query); + $this->assertEquals(0, $resultSet->count()); + + $query = new Prefix('name', 'baden'); + $resultSet = $index->search($query); + $this->assertEquals(2, $resultSet->count()); + + $query = new Prefix('name', 'baden b'); + $resultSet = $index->search($query); + $this->assertEquals(1, $resultSet->count()); + + $query = new Prefix('name', 'baden bas'); + $resultSet = $index->search($query); + $this->assertEquals(0, $resultSet->count()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/QueryTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/QueryTest.php new file mode 100644 index 00000000..0a331098 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/QueryTest.php @@ -0,0 +1,46 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Query\QueryString; +use Elastica\Filter\Query; +use Elastica\Test\Base as BaseTest; + +class QueryTest extends BaseTest +{ + public function testSimple() + { + $query = new QueryString('foo bar'); + $filter = new Query($query); + + $expected = array( + 'query' => array( + 'query_string' => array( + 'query' => 'foo bar', + ) + ) + ); + + $this->assertEquals($expected, $filter->toArray()); + } + + public function testExtended() + { + $query = new QueryString('foo bar'); + $filter = new Query($query); + $filter->setCached(true); + + $expected = array( + 'fquery' => array( + 'query' => array( + 'query_string' => array( + 'query' => 'foo bar', + ), + ), + '_cache' => true + ) + ); + + $this->assertEquals($expected, $filter->toArray()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/RangeTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/RangeTest.php new file mode 100644 index 00000000..bf2cb260 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/RangeTest.php @@ -0,0 +1,32 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Filter\Range; +use Elastica\Test\Base as BaseTest; + +class RangeTest extends BaseTest +{ + public function testAddField() + { + $rangeFilter = new Range(); + $returnValue = $rangeFilter->addField('fieldName', array('to' => 'value')); + $this->assertInstanceOf('Elastica\Filter\Range', $returnValue); + } + + public function testToArray() + { + $filter = new Range(); + + $fromTo = array('from' => 'ra', 'to' => 'ru'); + $filter->addField('name', $fromTo); + + $expectedArray = array( + 'range' => array( + 'name' => $fromTo + ) + ); + + $this->assertEquals($expectedArray, $filter->toArray()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/RegexpTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/RegexpTest.php new file mode 100644 index 00000000..e06064dd --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/RegexpTest.php @@ -0,0 +1,137 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Document; +use Elastica\Filter\Regexp; +use Elastica\Type\Mapping; +use Elastica\Test\Base as BaseTest; + +class RegexpTest extends BaseTest +{ + public function testToArray() + { + $field = 'name'; + $regexp = 'ruf'; + + $filter = new Regexp($field, $regexp); + + $expectedArray = array( + 'regexp' => array( + $field => $regexp + ) + ); + + $this->assertequals($expectedArray, $filter->toArray()); + } + + public function testDifferentRegexp() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + + $index->create(array(), true); + $type = $index->getType('test'); + + $mapping = new Mapping($type, array( + 'name' => array('type' => 'string', 'store' => 'no', 'index' => 'not_analyzed'), + ) + ); + $type->setMapping($mapping); + + $doc = new Document(1, array('name' => 'Basel-Stadt')); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'New York')); + $type->addDocument($doc); + $doc = new Document(3, array('name' => 'Baden')); + $type->addDocument($doc); + $doc = new Document(4, array('name' => 'Baden Baden')); + $type->addDocument($doc); + $doc = new Document(5, array('name' => 'New Orleans')); + $type->addDocument($doc); + + $index->refresh(); + + $query = new Regexp('name', 'Ba.*'); + $resultSet = $index->search($query); + $this->assertEquals(3, $resultSet->count()); + + // Lower case should not return a result + $query = new Regexp('name', 'ba.*'); + $resultSet = $index->search($query); + $this->assertEquals(0, $resultSet->count()); + + $query = new Regexp('name', 'Baden.*'); + $resultSet = $index->search($query); + $this->assertEquals(2, $resultSet->count()); + + $query = new Regexp('name', 'Baden B.*'); + $resultSet = $index->search($query); + $this->assertEquals(1, $resultSet->count()); + + $query = new Regexp('name', 'Baden Bas.*'); + $resultSet = $index->search($query); + $this->assertEquals(0, $resultSet->count()); + } + + public function testDifferentRegexpLowercase() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + + $indexParams = array( + 'analysis' => array( + 'analyzer' => array( + 'lw' => array( + 'type' => 'custom', + 'tokenizer' => 'keyword', + 'filter' => array('lowercase') + ) + ), + ) + ); + + $index->create($indexParams, true); + $type = $index->getType('test'); + + $mapping = new Mapping($type, array( + 'name' => array('type' => 'string', 'store' => 'no', 'analyzer' => 'lw'), + ) + ); + $type->setMapping($mapping); + + $doc = new Document(1, array('name' => 'Basel-Stadt')); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'New York')); + $type->addDocument($doc); + $doc = new Document(3, array('name' => 'Baden')); + $type->addDocument($doc); + $doc = new Document(4, array('name' => 'Baden Baden')); + $type->addDocument($doc); + $doc = new Document(5, array('name' => 'New Orleans')); + $type->addDocument($doc); + + $index->refresh(); + + $query = new Regexp('name', 'ba.*'); + $resultSet = $index->search($query); + $this->assertEquals(3, $resultSet->count()); + + // Upper case should not return a result + $query = new Regexp('name', 'Ba.*'); + $resultSet = $index->search($query); + $this->assertEquals(0, $resultSet->count()); + + $query = new Regexp('name', 'baden.*'); + $resultSet = $index->search($query); + $this->assertEquals(2, $resultSet->count()); + + $query = new Regexp('name', 'baden b.*'); + $resultSet = $index->search($query); + $this->assertEquals(1, $resultSet->count()); + + $query = new Regexp('name', 'baden bas.*'); + $resultSet = $index->search($query); + $this->assertEquals(0, $resultSet->count()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/ScriptTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/ScriptTest.php new file mode 100644 index 00000000..65ea628e --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/ScriptTest.php @@ -0,0 +1,52 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Script; +use Elastica\Filter\Script as ScriptFilter; +use Elastica\Test\Base as BaseTest; + +class ScriptTest extends BaseTest +{ + public function testToArray() + { + $string = '_score * 2.0'; + + $filter = new ScriptFilter($string); + + $array = $filter->toArray(); + $this->assertInternalType('array', $array); + + $expected = array( + 'script' => array( + 'script' => $string, + ) + ); + $this->assertEquals($expected, $array); + } + + public function testSetScript() + { + $string = '_score * 2.0'; + $params = array( + 'param1' => 'one', + 'param2' => 1, + ); + $lang = 'mvel'; + $script = new Script($string, $params, $lang); + + $filter = new ScriptFilter(); + $filter->setScript($script); + + $array = $filter->toArray(); + + $expected = array( + 'script' => array( + 'script' => $string, + 'params' => $params, + 'lang' => $lang, + ) + ); + $this->assertEquals($expected, $array); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/TermTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/TermTest.php new file mode 100644 index 00000000..9a116851 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/TermTest.php @@ -0,0 +1,23 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Filter\Term; +use Elastica\Test\Base as BaseTest; + +class TermTest extends BaseTest +{ + + public function testToArray() + { + $query = new Term(); + $key = 'name'; + $value = 'ruflin'; + $query->setTerm($key, $value); + + $data = $query->toArray(); + + $this->assertInternalType('array', $data['term']); + $this->assertEquals(array($key => $value), $data['term']); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/TermsTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/TermsTest.php new file mode 100644 index 00000000..96994730 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/TermsTest.php @@ -0,0 +1,54 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Filter\Terms; +use Elastica\Test\Base as BaseTest; + +class TermsTest extends BaseTest +{ + + public function testLookup() + { + $index = $this->_createIndex('terms_filter_test'); + $type1 = $index->getType('musicians'); + $type2 = $index->getType('bands'); + + //index some test data + $type1->addDocument(new \Elastica\Document(1, array('name' => 'robert', 'lastName' => 'plant'))); + $type1->addDocument(new \Elastica\Document(2, array('name' => 'jimmy', 'lastName' => 'page'))); + $type1->addDocument(new \Elastica\Document(3, array('name' => 'john paul', 'lastName' => 'jones'))); + $type1->addDocument(new \Elastica\Document(4, array('name' => 'john', 'lastName' => 'bonham'))); + $type1->addDocument(new \Elastica\Document(5, array('name' => 'jimi', 'lastName' => 'hendrix'))); + + $type2->addDocument(new \Elastica\Document('led zeppelin', array('members' => array('plant', 'page', 'jones', 'bonham')))); + $index->refresh(); + + //use the terms lookup feature to query for some data + $termsFilter = new Terms(); + $termsFilter->setLookup('lastName', $type2, 'led zeppelin', 'members', NULL); + $query = new \Elastica\Query(); + $query->setFilter($termsFilter); + $results = $index->search($query); + $this->assertEquals($results->count(), 4, 'Terms lookup with null index'); + + $termsFilter->setLookup('lastName', $type2, 'led zeppelin', 'members', $index); + $query->setFilter($termsFilter); + $results = $index->search($query); + $this->assertEquals($results->count(), 4, 'Terms lookup with index as object'); + + //Query with index given as string + $termsFilter->setLookup('lastName', $type2, 'led zeppelin', 'members', $index->getName()); + $query->setFilter($termsFilter); + $results = $index->search($query); + $this->assertEquals($results->count(), 4, 'Terms lookup with index as string'); + + //Query with array of options + $termsFilter->setLookup('lastName', $type2, 'led zeppelin', 'members', array('index' => $index, 'cache' => false)); + $query->setFilter($termsFilter); + $results = $index->search($query); + $this->assertEquals($results->count(), 4, 'Terms lookup with options array'); + + $index->delete(); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/TypeTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/TypeTest.php new file mode 100644 index 00000000..fcada826 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/TypeTest.php @@ -0,0 +1,27 @@ +<?php + +namespace Elastica\Test\Filter; + +use Elastica\Filter\Type; +use Elastica\Test\Base as BaseTest; + +class TypeTest extends BaseTest +{ + public function testSetType() + { + $typeFilter = new Type(); + $returnValue = $typeFilter->setType('type_name'); + $this->assertInstanceOf('Elastica\Filter\Type', $returnValue); + } + + public function testToArray() + { + $typeFilter = new Type('type_name'); + + $expectedArray = array( + 'type' => array('value' => 'type_name') + ); + + $this->assertEquals($expectedArray, $typeFilter->toArray()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Index/SettingsTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Index/SettingsTest.php new file mode 100644 index 00000000..4f74d22b --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Index/SettingsTest.php @@ -0,0 +1,300 @@ +<?php + +namespace Elastica\Test\Index; + +use Elastica\Document; +use Elastica\Exception\ResponseException; +use Elastica\Index; +use Elastica\Index\Settings as IndexSettings; +use Elastica\Test\Base as BaseTest; + +class SettingsTest extends BaseTest +{ + public function testGet() + { + $indexName = 'elasticatest'; + + $client = $this->_getClient(); + $index = $client->getIndex($indexName); + $index->create(array(), true); + $index->refresh(); + $settings = $index->getSettings(); + + $this->assertInternalType('array', $settings->get()); + $this->assertNotNull($settings->get('number_of_replicas')); + $this->assertNotNull($settings->get('number_of_shards')); + $this->assertNull($settings->get('kjqwerjlqwer')); + + $index->delete(); + } + + public function testGetWithAlias() + { + $indexName = 'elasticatest'; + $aliasName = 'elasticatest_alias'; + + $client = $this->_getClient(); + $index = $client->getIndex($indexName); + $index->create(array(), true); + $index->refresh(); + + $index->addAlias($aliasName); + $index = $client->getIndex($aliasName); + $settings = $index->getSettings(); + + $this->assertInternalType('array', $settings->get()); + $this->assertNotNull($settings->get('number_of_replicas')); + $this->assertNotNull($settings->get('number_of_shards')); + $this->assertNull($settings->get('kjqwerjlqwer')); + + $index->delete(); + } + + public function testSetNumberOfReplicas() + { + $indexName = 'test'; + + $client = $this->_getClient(); + $index = $client->getIndex($indexName); + $index->create(array(), true); + $settings = $index->getSettings(); + + $settings->setNumberOfReplicas(2); + $index->refresh(); + $this->assertEquals(2, $settings->get('number_of_replicas')); + + $settings->setNumberOfReplicas(3); + $index->refresh(); + $this->assertEquals(3, $settings->get('number_of_replicas')); + + $index->delete(); + } + + public function testSetRefreshInterval() + { + $indexName = 'test'; + + $client = $this->_getClient(); + $index = $client->getIndex($indexName); + $index->create(array(), true); + + $settings = $index->getSettings(); + + $settings->setRefreshInterval('2s'); + $index->refresh(); + $this->assertEquals('2s', $settings->get('refresh_interval')); + + $settings->setRefreshInterval('5s'); + $index->refresh(); + $this->assertEquals('5s', $settings->get('refresh_interval')); + + $index->delete(); + } + + public function testGetRefreshInterval() + { + $indexName = 'test'; + + $client = $this->_getClient(); + $index = $client->getIndex($indexName); + $index->create(array(), true); + + $settings = $index->getSettings(); + + $this->assertEquals(IndexSettings::DEFAULT_REFRESH_INTERVAL, $settings->getRefreshInterval()); + + $interval = '2s'; + $settings->setRefreshInterval($interval); + $index->refresh(); + $this->assertEquals($interval, $settings->getRefreshInterval()); + $this->assertEquals($interval, $settings->get('refresh_interval')); + + $index->delete(); + } + + public function testSetMergePolicy() + { + $indexName = 'test'; + + $client = $this->_getClient(); + $index = $client->getIndex($indexName); + $index->create(array(), true); + //wait for the shards to be allocated + $this->_waitForAllocation($index); + + $settings = $index->getSettings(); + + $settings->setMergePolicy('expunge_deletes_allowed', 15); + $this->assertEquals(15, $settings->getMergePolicy('expunge_deletes_allowed')); + + $settings->setMergePolicy('expunge_deletes_allowed', 10); + $this->assertEquals(10, $settings->getMergePolicy('expunge_deletes_allowed')); + + $index->delete(); + } + + public function testSetMergeFactor() + { + $indexName = 'test'; + + $client = $this->_getClient(); + $index = $client->getIndex($indexName); + $index->create(array(), true); + + //wait for the shards to be allocated + $this->_waitForAllocation($index); + + $settings = $index->getSettings(); + + $response = $settings->setMergePolicy('merge_factor', 15); + $this->assertEquals(15, $settings->getMergePolicy('merge_factor')); + $this->assertInstanceOf('Elastica\Response', $response); + $this->assertTrue($response->isOk()); + + $settings->setMergePolicy('merge_factor', 10); + $this->assertEquals(10, $settings->getMergePolicy('merge_factor')); + + $index->delete(); + } + + public function testSetMergePolicyType() + { + $indexName = 'test'; + + $client = $this->_getClient(); + $index = $client->getIndex($indexName); + $index->create(array(), true); + + //wait for the shards to be allocated + $this->_waitForAllocation($index); + + $settings = $index->getSettings(); + + $settings->setMergePolicyType('log_byte_size'); + $this->assertEquals('log_byte_size', $settings->getMergePolicyType()); + + $response = $settings->setMergePolicy('merge_factor', 15); + $this->assertEquals(15, $settings->getMergePolicy('merge_factor')); + $this->assertInstanceOf('Elastica\Response', $response); + $this->assertTrue($response->isOk()); + + $index->delete(); + } + + public function testSetReadOnly() + { + $index = $this->_createIndex('test'); + //wait for the shards to be allocated + $this->_waitForAllocation($index); + $index->getSettings()->setReadOnly(false); + + + // Add document to normal index + $doc1 = new Document(null, array('hello' => 'world')); + $doc2 = new Document(null, array('hello' => 'world')); + $doc3 = new Document(null, array('hello' => 'world')); + + $type = $index->getType('test'); + $type->addDocument($doc1); + $this->assertEquals('false', $index->getSettings()->get('blocks.read_only')); //ES returns a string for this setting + + // Try to add doc to read only index + $index->getSettings()->setReadOnly(true); + $this->assertEquals('true', $index->getSettings()->get('blocks.read_only')); + + try { + $type->addDocument($doc2); + $this->fail('Should throw exception because of read only'); + } catch (ResponseException $e) { + $message = $e->getMessage(); + $this->assertContains('ClusterBlockException', $message); + $this->assertContains('index read-only', $message); + } + + // Remove read only, add document + $response = $index->getSettings()->setReadOnly(false); + $this->assertTrue($response->isOk()); + + $type->addDocument($doc3); + $index->refresh(); + + $this->assertEquals(2, $type->count()); + + $index->delete(); + } + + + public function testGetSetBlocksRead() + { + $index = $this->_createIndex('elastica-test'); + $index->refresh(); + $settings = $index->getSettings(); + + $this->assertFalse($settings->getBlocksRead()); + + $settings->setBlocksRead(true); + $this->assertTrue($settings->getBlocksRead()); + + $settings->setBlocksRead(false); + $this->assertFalse($settings->getBlocksRead()); + + $settings->setBlocksRead(); + $this->assertTrue($settings->getBlocksRead()); + + $index->delete(); + } + + public function testGetSetBlocksWrite() + { + $index = $this->_createIndex('elastica-test'); + $index->refresh(); + $settings = $index->getSettings(); + + $this->assertFalse($settings->getBlocksWrite()); + + $settings->setBlocksWrite(true); + $this->assertTrue($settings->getBlocksWrite()); + + $settings->setBlocksWrite(false); + $this->assertFalse($settings->getBlocksWrite()); + + $settings->setBlocksWrite(); + $this->assertTrue($settings->getBlocksWrite()); + + $index->delete(); + } + + public function testGetSetBlocksMetadata() + { + $index = $this->_createIndex('elastica-test'); + $index->refresh(); + $settings = $index->getSettings(); + + $this->assertFalse($settings->getBlocksMetadata()); + + $settings->setBlocksMetadata(true); + $this->assertTrue($settings->getBlocksMetadata()); + + $settings->setBlocksMetadata(false); + $this->assertFalse($settings->getBlocksMetadata()); + + $settings->setBlocksMetadata(); + $this->assertTrue($settings->getBlocksMetadata()); + + $settings->setBlocksMetadata(false); // Cannot delete index otherwise + $index->delete(); + } + + protected function _waitForAllocation(Index $index) + { + do { + $settings = $index->getStatus()->get(); + $allocated = true; + foreach ($settings['shards'] as $shard) { + if ($shard[0]['routing']['state'] != 'STARTED') { + $allocated = false; + } + } + } while (!$allocated); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Index/StatsTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Index/StatsTest.php new file mode 100644 index 00000000..5e8e8d57 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Index/StatsTest.php @@ -0,0 +1,23 @@ +<?php + +namespace Elastica\Test\Index; + +use Elastica\Test\Base as BaseTest; + +class StatsTest extends BaseTest +{ + + public function testGetSettings() + { + $indexName = 'test'; + + $client = $this->_getClient(); + $index = $client->getIndex($indexName); + $index->create(array(), true); + $stats = $index->getStats(); + $this->assertInstanceOf('Elastica\Index\Stats', $stats); + + $this->assertTrue($stats->getResponse()->isOk()); + $this->assertEquals(0, $stats->get('_all', 'indices', 'test', 'primaries', 'docs', 'count')); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Index/StatusTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Index/StatusTest.php new file mode 100644 index 00000000..8a056a53 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Index/StatusTest.php @@ -0,0 +1,66 @@ +<?php + +namespace Elastica\Test\Index; + +use Elastica\Index\Status as IndexStatus; +use Elastica\Test\Base as BaseTest; + +class StatusTest extends BaseTest +{ + public function testGetAliases() + { + $indexName = 'test'; + $aliasName = 'test-alias'; + + $client = $this->_getClient(); + $index = $client->getIndex($indexName); + $index->create(array(), true); + + $status = new IndexStatus($index); + + $aliases = $status->getAliases(); + + $this->assertTrue(empty($aliases)); + $this->assertInternalType('array', $aliases); + + $index->addAlias($aliasName); + $status->refresh(); + + $aliases = $status->getAliases(); + + $this->assertTrue(in_array($aliasName, $aliases)); + } + + public function testHasAlias() + { + $indexName = 'test'; + $aliasName = 'test-alias'; + + $client = $this->_getClient(); + $index = $client->getIndex($indexName); + $index->create(array(), true); + + $status = new IndexStatus($index); + + $this->assertFalse($status->hasAlias($aliasName)); + + $index->addAlias($aliasName); + $status->refresh(); + + $this->assertTrue($status->hasAlias($aliasName)); + } + + public function testGetSettings() + { + $indexName = 'test'; + + $client = $this->_getClient(); + $index = $client->getIndex($indexName); + $index->create(array(), true); + $status = $index->getStatus(); + + $settings = $status->getSettings(); + $this->assertInternalType('array', $settings); + $this->assertTrue(isset($settings['index']['number_of_shards'])); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/IndexTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/IndexTest.php new file mode 100644 index 00000000..8e4ac306 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/IndexTest.php @@ -0,0 +1,696 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Client; +use Elastica\Document; +use Elastica\Exception\ResponseException; +use Elastica\Index; +use Elastica\Query\QueryString; +use Elastica\Query\Term; +use Elastica\Status; +use Elastica\Type; +use Elastica\Type\Mapping; +use Elastica\Query\HasChild; +use Elastica\Test\Base as BaseTest; + +class IndexTest extends BaseTest +{ + public function testMapping() + { + $index = $this->_createIndex(); + $doc = new Document(1, array('id' => 1, 'email' => 'test@test.com', 'username' => 'hanswurst', 'test' => array('2', '3', '5'))); + + $type = $index->getType('test'); + + $mapping = array('id' => array('type' => 'integer', 'store' => true), 'email' => array('type' => 'string', 'store' => 'no'), + 'username' => array('type' => 'string', 'store' => 'no'), 'test' => array('type' => 'integer', 'store' => 'no'),); + $type->setMapping($mapping); + + $type->addDocument($doc); + $index->optimize(); + + $storedMapping = $index->getMapping(); + + $this->assertEquals($storedMapping['test']['properties']['id']['type'], 'integer'); + $this->assertEquals($storedMapping['test']['properties']['id']['store'], true); + $this->assertEquals($storedMapping['test']['properties']['email']['type'], 'string'); + $this->assertEquals($storedMapping['test']['properties']['username']['type'], 'string'); + $this->assertEquals($storedMapping['test']['properties']['test']['type'], 'integer'); + + $result = $type->search('hanswurst'); + } + + public function testGetMappingAlias() { + + $indexName = 'test-mapping'; + $aliasName = 'test-mapping-alias'; + + $index = $this->_createIndex($indexName); + $indexName = $index->getName(); + $index->addAlias($aliasName); + + $type = new Type($index, 'test'); + $mapping = new Mapping($type, array( + 'id' => array('type' => 'integer', 'store' => 'yes'), + )); + $type->setMapping($mapping); + + $client = $index->getClient(); + + // Index mapping + $mapping1 = $client->getIndex($indexName)->getMapping(); + + // Alias mapping + $mapping2 = $client->getIndex($aliasName)->getMapping(); + + // Make sure, a mapping is set + $this->assertNotEmpty($mapping1); + + // Alias and index mapping should be identical + $this->assertEquals($mapping1, $mapping2); + } + + public function testParent() + { + $index = $this->_createIndex(); + + $typeBlog = new Type($index, 'blog'); + + $typeComment = new Type($index, 'comment'); + + $mapping = new Mapping(); + $mapping->setParam('_parent', array('type' => 'blog')); + $typeComment->setMapping($mapping); + + $entry1 = new Document(1); + $entry1->set('title', 'Hello world'); + $typeBlog->addDocument($entry1); + + $entry2 = new Document(2); + $entry2->set('title', 'Foo bar'); + $typeBlog->addDocument($entry2); + + $entry3 = new Document(3); + $entry3->set('title', 'Till dawn'); + $typeBlog->addDocument($entry3); + + $comment = new Document(1); + $comment->set('author', 'Max'); + $comment->setParent(2); // Entry Foo bar + $typeComment->addDocument($comment); + + $index->optimize(); + + $query = new HasChild('Max', 'comment'); + $resultSet = $typeBlog->search($query); + $this->assertEquals(1, $resultSet->count()); + $this->assertEquals(array('title' => 'Foo bar'), $resultSet->current()->getData()); + } + + public function testAddPdfFile() + { + $this->_checkAttachmentsPlugin(); + $indexMapping = array('file' => array('type' => 'attachment', 'store' => 'no'), 'text' => array('type' => 'string', 'store' => 'no'),); + + $indexParams = array('index' => array('number_of_shards' => 1, 'number_of_replicas' => 0),); + + $index = $this->_createIndex(); + $type = new Type($index, 'test'); + + $index->create($indexParams, true); + $type->setMapping($indexMapping); + + $doc1 = new Document(1); + $doc1->addFile('file', BASE_PATH . '/data/test.pdf', 'application/pdf'); + $doc1->set('text', 'basel world'); + $type->addDocument($doc1); + + $doc2 = new Document(2); + $doc2->set('text', 'running in basel'); + $type->addDocument($doc2); + + $index->optimize(); + + $resultSet = $type->search('xodoa'); + $this->assertEquals(1, $resultSet->count()); + + $resultSet = $type->search('basel'); + $this->assertEquals(2, $resultSet->count()); + + // Author is ruflin + $resultSet = $type->search('ruflin'); + $this->assertEquals(1, $resultSet->count()); + + // String does not exist in file + $resultSet = $type->search('guschti'); + $this->assertEquals(0, $resultSet->count()); + } + + public function testAddPdfFileContent() + { + $this->_checkAttachmentsPlugin(); + $indexMapping = array('file' => array('type' => 'attachment', 'store' => 'no'), 'text' => array('type' => 'string', 'store' => 'no'),); + + $indexParams = array('index' => array('number_of_shards' => 1, 'number_of_replicas' => 0),); + + $index = $this->_createIndex(); + $type = new Type($index, 'test'); + + $index->create($indexParams, true); + $type->setMapping($indexMapping); + + $doc1 = new Document(1); + $doc1->addFileContent('file', file_get_contents(BASE_PATH . '/data/test.pdf')); + $doc1->set('text', 'basel world'); + $type->addDocument($doc1); + + $doc2 = new Document(2); + $doc2->set('text', 'running in basel'); + $type->addDocument($doc2); + + $index->optimize(); + + $resultSet = $type->search('xodoa'); + $this->assertEquals(1, $resultSet->count()); + + $resultSet = $type->search('basel'); + $this->assertEquals(2, $resultSet->count()); + + // Author is ruflin + $resultSet = $type->search('ruflin'); + $this->assertEquals(1, $resultSet->count()); + + // String does not exist in file + $resultSet = $type->search('guschti'); + $this->assertEquals(0, $resultSet->count()); + } + + public function testAddWordxFile() + { + $this->_checkAttachmentsPlugin(); + $indexMapping = array('file' => array('type' => 'attachment'), 'text' => array('type' => 'string', 'store' => 'no'),); + + $indexParams = array('index' => array('number_of_shards' => 1, 'number_of_replicas' => 0),); + + $index = $this->_createIndex(); + $type = new Type($index, 'content'); + + $index->create($indexParams, true); + $type->setMapping($indexMapping); + + $doc1 = new Document(1); + $doc1->addFile('file', BASE_PATH . '/data/test.docx'); + $doc1->set('text', 'basel world'); + $type->addDocument($doc1); + + $doc2 = new Document(2); + $doc2->set('text', 'running in basel'); + $type->addDocument($doc2); + + $index->optimize(); + + $resultSet = $type->search('xodoa'); + $this->assertEquals(1, $resultSet->count()); + + $resultSet = $type->search('basel'); + $this->assertEquals(2, $resultSet->count()); + + $resultSet = $type->search('ruflin'); + $this->assertEquals(0, $resultSet->count()); + } + + public function testExcludeFileSource() + { + $this->_checkAttachmentsPlugin(); + $indexMapping = array('file' => array('type' => 'attachment', 'store' => 'yes'), 'text' => array('type' => 'string', 'store' => 'yes'), + 'title' => array('type' => 'string', 'store' => 'yes'),); + + $indexParams = array('index' => array('number_of_shards' => 1, 'number_of_replicas' => 0),); + + $index = $this->_createIndex(); + $type = new Type($index, 'content'); + + $mapping = Mapping::create($indexMapping); + $mapping->setSource(array('excludes' => array('file'))); + + $mapping->setType($type); + + $index->create($indexParams, true); + $type->setMapping($mapping); + + $docId = 1; + $text = 'Basel World'; + $title = 'No Title'; + + $doc1 = new Document($docId); + $doc1->addFile('file', BASE_PATH . '/data/test.docx'); + $doc1->set('text', $text); + $doc1->set('title', $title); + $type->addDocument($doc1); + + // Optimization necessary, as otherwise source still in realtime get + $index->optimize(); + + $data = $type->getDocument($docId)->getData(); + $this->assertEquals($data['title'], $title); + $this->assertEquals($data['text'], $text); + $this->assertFalse(isset($data['file'])); + } + + /** + * @expectedException \Elastica\Exception\ResponseException + */ + public function testAddRemoveAlias() + { + $client = $this->_getClient(); + + $indexName1 = 'test1'; + $aliasName = 'test-alias'; + $typeName = 'test'; + + $index = $client->getIndex($indexName1); + $index->create(array('index' => array('number_of_shards' => 1, 'number_of_replicas' => 0)), true); + + $doc = new Document(1, array('id' => 1, 'email' => 'test@test.com', 'username' => 'ruflin')); + + $type = $index->getType($typeName); + $type->addDocument($doc); + $index->refresh(); + + $resultSet = $type->search('ruflin'); + + $this->assertEquals(1, $resultSet->count()); + + $data = $index->addAlias($aliasName, true)->getData(); + $this->assertTrue($data['acknowledged']); + + $index2 = $client->getIndex($aliasName); + $type2 = $index2->getType($typeName); + + $resultSet2 = $type2->search('ruflin'); + $this->assertEquals(1, $resultSet2->count()); + + $response = $index->removeAlias($aliasName)->getData(); + $this->assertTrue($response['acknowledged']); + + $client->getIndex($aliasName)->getType($typeName)->search('ruflin'); + } + + public function testCount() + { + $index = $this->_createIndex(); + + // Add document to normal index + $doc1 = new Document(null, array('name' => 'ruflin')); + $doc2 = new Document(null, array('name' => 'nicolas')); + + $type = $index->getType('test'); + $type->addDocument($doc1); + $type->addDocument($doc2); + + + $index->refresh(); + + $this->assertEquals(2, $index->count()); + + $query = new Term(); + $key = 'name'; + $value = 'nicolas'; + $query->setTerm($key, $value); + + $this->assertEquals(1, $index->count($query)); + } + + public function testDeleteIndexDeleteAlias() + { + $indexName = 'test'; + $aliasName = 'test-aliase'; + + $client = $this->_getClient(); + $index = $client->getIndex($indexName); + + $index->create(array(), true); + $index->addAlias($aliasName); + + $status = new Status($client); + $this->assertTrue($status->indexExists($indexName)); + $this->assertTrue($status->aliasExists($aliasName)); + + // Deleting index should also remove alias + $index->delete(); + + $status->refresh(); + $this->assertFalse($status->indexExists($indexName)); + $this->assertFalse($status->aliasExists($aliasName)); + } + + public function testAddAliasTwoIndices() + { + $indexName1 = 'test1'; + $indexName2 = 'test2'; + $aliasName = 'test-alias'; + + $client = $this->_getClient(); + $index1 = $client->getIndex($indexName1); + $index2 = $client->getIndex($indexName2); + + $index1->create(array(), true); + $index1->addAlias($aliasName); + $index2->create(array(), true); + + $index1->refresh(); + $index2->refresh(); + $index1->optimize(); + $index2->optimize(); + + $status = new Status($client); + + + $this->assertTrue($status->indexExists($indexName1)); + $this->assertTrue($status->indexExists($indexName2)); + + $this->assertTrue($status->aliasExists($aliasName)); + $this->assertTrue($index1->getStatus()->hasAlias($aliasName)); + $this->assertFalse($index2->getStatus()->hasAlias($aliasName)); + + $index2->addAlias($aliasName); + $this->assertTrue($index1->getStatus()->hasAlias($aliasName)); + $this->assertTrue($index2->getStatus()->hasAlias($aliasName)); + } + + public function testReplaceAlias() + { + $indexName1 = 'test1'; + $indexName2 = 'test2'; + $aliasName = 'test-alias'; + + $client = $this->_getClient(); + $index1 = $client->getIndex($indexName1); + $index2 = $client->getIndex($indexName2); + + $index1->create(array(), true); + $index1->addAlias($aliasName); + $index2->create(array(), true); + + $index1->refresh(); + $index2->refresh(); + + $status = new Status($client); + + $this->assertTrue($status->indexExists($indexName1)); + $this->assertTrue($status->indexExists($indexName2)); + $this->assertTrue($status->aliasExists($aliasName)); + $this->assertTrue($index1->getStatus()->hasAlias($aliasName)); + $this->assertFalse($index2->getStatus()->hasAlias($aliasName)); + + $index2->addAlias($aliasName, true); + $this->assertFalse($index1->getStatus()->hasAlias($aliasName)); + $this->assertTrue($index2->getStatus()->hasAlias($aliasName)); + } + + public function testAddDocumentVersion() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = new Type($index, 'test'); + + $doc1 = new Document(1); + $doc1->set('title', 'Hello world'); + + $return = $type->addDocument($doc1); + $data = $return->getData(); + $this->assertEquals(1, $data['_version']); + + $return = $type->addDocument($doc1); + $data = $return->getData(); + $this->assertEquals(2, $data['_version']); + } + + public function testClearCache() + { + $client = $this->_getClient(); + $index1 = $client->getIndex('test1'); + + $response = $index1->clearCache(); + $this->assertFalse($response->hasError()); + } + + public function testFlush() + { + $client = $this->_getClient(); + $index = $client->getIndex('test1'); + + $response = $index->flush(); + $this->assertFalse($response->hasError()); + } + + public function testExists() + { + $index = $this->_createIndex(); + + $this->assertTrue($index->exists()); + + $index->delete(); + + $this->assertFalse($index->exists()); + } + + /** + * Test $index->delete() return value for unknown index + * + * Tests if deleting an index that does not exist in Elasticsearch, + * correctly returns a boolean true from the hasError() method of + * the \Elastica\Response object + */ + public function testDeleteMissingIndexHasError() + { + $client = $this->_getClient(); + $index = $client->getIndex('index_does_not_exist'); + + try { + $index->delete(); + $this->fail('This should never be reached. Deleting an unknown index will throw an exception'); + } catch (ResponseException $error) { + $response = $error->getResponse(); + $this->assertTrue($response->hasError()); + $request = $error->getRequest(); + $this->assertInstanceOf('Elastica\Request', $request); + } + } + + /** + * Tests to see if the test type mapping exists when calling $index->getMapping() + */ + public function testIndexGetMapping() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + + $mapping = array('id' => array('type' => 'integer', 'store' => true), 'email' => array('type' => 'string', 'store' => 'no'), + 'username' => array('type' => 'string', 'store' => 'no'), 'test' => array('type' => 'integer', 'store' => 'no'),); + + $type->setMapping($mapping); + $index->refresh(); + $indexMappings = $index->getMapping(); + + $this->assertEquals($indexMappings['test']['properties']['id']['type'], 'integer'); + $this->assertEquals($indexMappings['test']['properties']['id']['store'], true); + $this->assertEquals($indexMappings['test']['properties']['email']['type'], 'string'); + $this->assertEquals($indexMappings['test']['properties']['username']['type'], 'string'); + $this->assertEquals($indexMappings['test']['properties']['test']['type'], 'integer'); + } + + /** + * Tests to see if the index is empty when there are no types set. + */ + public function testEmptyIndexGetMapping() + { + $index = $this->_createIndex(); + $indexMappings = $index->getMapping(); + + $this->assertTrue(empty($indexMappings['elastica_test'])); + } + + /** + * Test to see if search Default Limit works + */ + public function testLimitDefaultIndex() + { + $client = $this->_getClient(); + $index = $client->getIndex('zero'); + $index->create(array('index' => array('number_of_shards' => 1, 'number_of_replicas' => 0)), true); + + $docs = array(); + + $docs[] = new Document(1, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(2, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(3, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(4, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(5, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(6, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(7, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(8, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(9, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(10, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(11, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + + $type = $index->getType('zeroType'); + $type->addDocuments($docs); + $index->refresh(); + + // default limit results (default limit is 10) + $resultSet = $index->search('farrelley'); + $this->assertEquals(10, $resultSet->count()); + + // limit = 1 + $resultSet = $index->search('farrelley', 1); + $this->assertEquals(1, $resultSet->count()); + } + + /** + * @expectedException \Elastica\Exception\InvalidException + */ + public function testCreateArray() + { + $client = $this->_getClient(); + $indexName = 'test'; + + //Testing recreate (backward compatibility) + $index = $client->getIndex($indexName); + $index->create(array(), true); + $status = new Status($client); + $this->assertTrue($status->indexExists($indexName)); + + //Testing create index with array options + $opts = array('recreate' => true, 'routing' => 'r1,r2'); + $index->create(array(), $opts); + $status = new Status($client); + $this->assertTrue($status->indexExists($indexName)); + + //Testing invalid options + $opts = array('recreate' => true, 'routing' => 'r1,r2', 'testing_invalid_option' => true); + $index->create(array(), $opts); + $status = new Status($client); + $this->assertTrue($status->indexExists($indexName)); + } + + public function testCreateSearch() + { + $client = $this->_getClient(); + $index = new Index($client, 'test'); + + $query = new QueryString('test'); + $options = 5; + + $search = $index->createSearch($query, $options); + + $expected = array( + 'query' => array( + 'query_string' => array( + 'query' => 'test' + ) + ), + 'size' => 5 + ); + $this->assertEquals($expected, $search->getQuery()->toArray()); + $this->assertEquals(array('test'), $search->getIndices()); + $this->assertTrue($search->hasIndices()); + $this->assertTrue($search->hasIndex('test')); + $this->assertTrue($search->hasIndex($index)); + $this->assertEquals(array(), $search->getTypes()); + $this->assertFalse($search->hasTypes()); + $this->assertFalse($search->hasType('test_type')); + + $type = new Type($index, 'test_type2'); + $this->assertFalse($search->hasType($type)); + } + + public function testSearch() + { + $index = $this->_createIndex(); + + $type = new Type($index, 'user'); + + $docs = array(); + $docs[] = new Document(1, array('username' => 'hans', 'test' => array('2', '3', '5'))); + $docs[] = new Document(2, array('username' => 'john', 'test' => array('1', '3', '6'))); + $docs[] = new Document(3, array('username' => 'rolf', 'test' => array('2', '3', '7'))); + $type->addDocuments($docs); + $index->refresh(); + + $resultSet = $index->search('rolf'); + $this->assertEquals(1, $resultSet->count()); + + $count = $index->count('rolf'); + $this->assertEquals(1, $count); + + // Test if source is returned + $result = $resultSet->current(); + $this->assertEquals(3, $result->getId()); + $data = $result->getData(); + $this->assertEquals('rolf', $data['username']); + + $count = $index->count(); + $this->assertEquals(3, $count); + } + + public function testOptimize() + { + $index = $this->_createIndex(); + + $type = new Type($index, 'optimize'); + + $docs = array(); + $docs[] = new Document(1, array('foo' => 'bar')); + $docs[] = new Document(2, array('foo' => 'bar')); + $type->addDocuments($docs); + $index->refresh(); + + $stats = $index->getStats()->getData(); + $this->assertEquals(0, $stats['_all']['primaries']['docs']['deleted']); + + $type->deleteById(1); + $index->refresh(); + + $stats = $index->getStats()->getData(); + $this->assertEquals(1, $stats['_all']['primaries']['docs']['deleted']); + + $index->optimize(array('max_num_segments' => 1)); + + $stats = $index->getStats()->getData(); + $this->assertEquals(0, $stats['_all']['primaries']['docs']['deleted']); + } + + public function testAnalyze() + { + $index = $this->_createIndex('analyze'); + $index->optimize(); + sleep(2); + $returnedTokens = $index->analyze('foo'); + + $tokens = array( + array( + 'token' => 'foo', + 'start_offset' => 0, + 'end_offset' => 3, + 'type' => '<ALPHANUM>', + 'position' => 1, + ) + ); + + $this->assertEquals($tokens, $returnedTokens); + } + + /** + * Check for the presence of the mapper-attachments plugin and skip the current test if it is not found. + */ + protected function _checkAttachmentsPlugin() + { + $nodes = $this->_getClient()->getCluster()->getNodes(); + if (!$nodes[0]->getInfo()->hasPlugin('mapper-attachments')) { + $this->markTestSkipped('mapper-attachments plugin not installed'); + } + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/LogTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/LogTest.php new file mode 100644 index 00000000..188be933 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/LogTest.php @@ -0,0 +1,153 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Client; +use Elastica\Log; +use Elastica\Test\Base as BaseTest; +use Psr\Log\LogLevel; + +class LogTest extends BaseTest +{ + private $_context = array(); + private $_message = 'hello world'; + + protected function setUp() + { + if (!class_exists('Psr\Log\AbstractLogger')) { + $this->markTestSkipped('The Psr extension is not available.'); + } + } + + public function testLogInterface() + { + $log = new Log(); + $this->assertInstanceOf('Psr\Log\LoggerInterface', $log); + } + + public function testSetLogConfigPath() + { + $logPath = '/tmp/php.log'; + $client = new Client(array('log' => $logPath)); + $this->assertEquals($logPath, $client->getConfig('log')); + } + + public function testSetLogConfigEnable() + { + $client = new Client(array('log' => true)); + $this->assertTrue($client->getConfig('log')); + } + + public function testSetLogConfigEnable1() + { + $client = new Client(); + $client->setLogger(new Log()); + $this->assertFalse($client->getConfig('log')); + } + + public function testEmptyLogConfig() + { + $client = $this->_getClient(); + $this->assertEmpty($client->getConfig('log')); + } + + public function testGetLastMessage() + { + $log = new Log('/tmp/php.log'); + + $log->log(LogLevel::DEBUG, $this->_message, $this->_context); + + $this->_context['error_message'] = $this->_message; + $message = json_encode($this->_context); + + $this->assertEquals($message, $log->getLastMessage()); + } + + public function testGetLastMessage2() + { + $client = new Client(array('log' => true)); + $log = new Log($client); + + // Set log path temp path as otherwise test fails with output + $errorLog = ini_get('error_log'); + ini_set('error_log', sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'php.log'); + + $this->_context['error_message'] = $this->_message; + $message = json_encode($this->_context); + + $log->log(LogLevel::DEBUG, $this->_message, $this->_context); + ini_set('error_log', $errorLog); + + $this->assertEquals($message, $log->getLastMessage()); + } + + public function testGetLastMessageInfo() + { + $log = $this->initLog(); + $log->info($this->_message, $this->_context); + $this->assertEquals($this->getMessage(), $log->getLastMessage()); + } + + public function testGetLastMessageCritical() + { + $log = $this->initLog(); + $log->critical($this->_message, $this->_context); + $this->assertEquals($this->getMessage(), $log->getLastMessage()); + } + + public function testGetLastMessageAlert() + { + $log = $this->initLog(); + $log->alert($this->_message, $this->_context); + $this->assertEquals($this->getMessage(), $log->getLastMessage()); + } + + public function testGetLastMessageDebug() + { + $log = $this->initLog(); + $log->debug($this->_message, $this->_context); + $this->assertEquals($this->getMessage(), $log->getLastMessage()); + } + + public function testGetLastMessageEmergency() + { + $log = $this->initLog(); + $log->emergency($this->_message, $this->_context); + $this->assertEquals($this->getMessage(), $log->getLastMessage()); + } + + public function testGetLastMessageError() + { + $log = $this->initLog(); + $log->error($this->_message, $this->_context); + $this->assertEquals($this->getMessage(), $log->getLastMessage()); + } + + public function testGetLastMessageNotice() + { + $log = $this->initLog(); + $log->notice($this->_message, $this->_context); + $this->assertEquals($this->getMessage(), $log->getLastMessage()); + } + + public function testGetLastMessageWarning() + { + $log = $this->initLog(); + $log->warning($this->_message, $this->_context); + $this->assertEquals($this->getMessage(), $log->getLastMessage()); + } + + private function initLog() + { + $log = new Log('/tmp/php.log'); + + return $log; + } + + private function getMessage() + { + $this->_context['error_message'] = $this->_message; + + return json_encode($this->_context); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Multi/SearchTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Multi/SearchTest.php new file mode 100644 index 00000000..a62aaaad --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Multi/SearchTest.php @@ -0,0 +1,549 @@ +<?php + +namespace Elastica\Test\Multi; + +use Elastica\Document; +use Elastica\Multi\Search as MultiSearch; +use Elastica\Query; +use Elastica\Query\Range; +use Elastica\Query\Term; +use Elastica\Search; +use Elastica\Test\Base as BaseTest; + +class SearchTest extends BaseTest +{ + /** + * @return \Elastica\Type + */ + protected function _createType() + { + $client = $this->_getClient(); + + $index = $client->getIndex('zero'); + $index->create(array('index' => array('number_of_shards' => 1, 'number_of_replicas' => 0)), true); + + $docs = array(); + $docs[] = new Document(1, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(2, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(3, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(4, array('id' => 1, 'email' => 'test@test.com', 'username' => 'kate')); + $docs[] = new Document(5, array('id' => 1, 'email' => 'test@test.com', 'username' => 'kate')); + $docs[] = new Document(6, array('id' => 1, 'email' => 'test@test.com', 'username' => 'bunny')); + $docs[] = new Document(7, array('id' => 1, 'email' => 'test@test.com', 'username' => 'bunny')); + $docs[] = new Document(8, array('id' => 1, 'email' => 'test@test.com', 'username' => 'bunny')); + $docs[] = new Document(9, array('id' => 1, 'email' => 'test@test.com', 'username' => 'bunny')); + $docs[] = new Document(10, array('id' => 1, 'email' => 'test@test.com', 'username' => 'bunny')); + $docs[] = new Document(11, array('id' => 1, 'email' => 'test@test.com', 'username' => 'bunny')); + $type = $index->getType('zeroType'); + $type->addDocuments($docs); + $index->refresh(); + + return $type; + } + + public function testConstruct() + { + $client = $this->_getClient(); + $multiSearch = new MultiSearch($client); + + $this->assertInstanceOf('Elastica\Multi\Search', $multiSearch); + $this->assertSame($client, $multiSearch->getClient()); + } + + public function testSetSearches() + { + $client = $this->_getClient(); + $multiSearch = new MultiSearch($client); + + $search1 = new Search($client); + $search2 = new Search($client); + $search3 = new Search($client); + + $multiSearch->setSearches(array($search1, $search2, $search3)); + + $searches = $multiSearch->getSearches(); + + $this->assertInternalType('array', $searches); + $this->assertCount(3, $searches); + $this->assertArrayHasKey(0, $searches); + $this->assertSame($search1, $searches[0]); + $this->assertArrayHasKey(1, $searches); + $this->assertSame($search2, $searches[1]); + $this->assertArrayHasKey(2, $searches); + $this->assertSame($search3, $searches[2]); + + $multiSearch->clearSearches(); + $searches = $multiSearch->getSearches(); + + $this->assertInternalType('array', $searches); + $this->assertCount(0, $searches); + } + + public function testSetSearchesByKeys() + { + $client = $this->_getClient(); + $multiSearch = new MultiSearch($client); + + $search1 = new Search($client); + $search2 = new Search($client); + $search3 = new Search($client); + + $multiSearch->setSearches(array('search1' => $search1, 'search2' => $search2, $search3)); + + $searches = $multiSearch->getSearches(); + + $this->assertInternalType('array', $searches); + $this->assertCount(3, $searches); + $this->assertArrayHasKey('search1', $searches); + $this->assertSame($search1, $searches['search1']); + $this->assertArrayHasKey('search2', $searches); + $this->assertSame($search2, $searches['search2']); + $this->assertArrayHasKey(0, $searches); + $this->assertSame($search3, $searches[0]); + + $multiSearch->clearSearches(); + $searches = $multiSearch->getSearches(); + + $this->assertInternalType('array', $searches); + $this->assertCount(0, $searches); + } + + public function testSearch() + { + $type = $this->_createType(); + $index = $type->getIndex(); + $client = $index->getClient(); + + $multiSearch = new MultiSearch($client); + + $search1 = new Search($client); + $search1->addIndex($index)->addType($type); + $query1 = new Query(); + $termQuery1 = new Term(); + $termQuery1->setTerm('username', 'farrelley'); + $query1->setQuery($termQuery1); + $query1->setSize(2); + $search1->setQuery($query1); + + $multiSearch->addSearch($search1); + + $this->assertCount(1, $multiSearch->getSearches()); + + $search2 = new Search($client); + $search2->addIndex($index)->addType($type); + $query2 = new Query(); + $termQuery2 = new Term(); + $termQuery2->setTerm('username', 'bunny'); + $query2->setQuery($termQuery2); + $query2->setSize(3); + $search2->setQuery($query2); + + $multiSearch->addSearch($search2); + + $this->assertCount(2, $multiSearch->getSearches()); + + $searches = $multiSearch->getSearches(); + $this->assertSame($search1, $searches[0]); + $this->assertSame($search2, $searches[1]); + + $multiResultSet = $multiSearch->search(); + + $this->assertInstanceOf('Elastica\Multi\ResultSet', $multiResultSet); + $this->assertCount(2, $multiResultSet); + $this->assertInstanceOf('Elastica\Response', $multiResultSet->getResponse()); + + foreach ($multiResultSet as $resultSet) { + $this->assertInstanceOf('Elastica\ResultSet', $resultSet); + } + + $resultSets = $multiResultSet->getResultSets(); + + $this->assertInternalType('array', $resultSets); + + $this->assertArrayHasKey(0, $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets[0]); + $this->assertCount(2, $resultSets[0]); + $this->assertSame($query1, $resultSets[0]->getQuery()); + $this->assertEquals(3, $resultSets[0]->getTotalHits()); + + $this->assertArrayHasKey(1, $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets[1]); + $this->assertCount(3, $resultSets[1]); + $this->assertSame($query2, $resultSets[1]->getQuery()); + $this->assertEquals(6, $resultSets[1]->getTotalHits()); + + $this->assertFalse($multiResultSet->hasError()); + + $search1->setOption(Search::OPTION_SEARCH_TYPE, Search::OPTION_SEARCH_TYPE_COUNT); + $search2->setOption(Search::OPTION_SEARCH_TYPE, Search::OPTION_SEARCH_TYPE_COUNT); + + $multiResultSet = $multiSearch->search(); + + $this->assertInstanceOf('Elastica\Multi\ResultSet', $multiResultSet); + $this->assertCount(2, $multiResultSet); + $this->assertInstanceOf('Elastica\Response', $multiResultSet->getResponse()); + + $resultSets = $multiResultSet->getResultSets(); + + $this->assertInternalType('array', $resultSets); + + $this->assertArrayHasKey(0, $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets[0]); + $this->assertCount(0, $resultSets[0]); + $this->assertSame($query1, $resultSets[0]->getQuery()); + $this->assertEquals(3, $resultSets[0]->getTotalHits()); + + $this->assertArrayHasKey(1, $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets[1]); + $this->assertCount(0, $resultSets[1]); + $this->assertSame($query2, $resultSets[1]->getQuery()); + $this->assertEquals(6, $resultSets[1]->getTotalHits()); + } + + public function testSearchWithKeys() + { + $type = $this->_createType(); + $index = $type->getIndex(); + $client = $index->getClient(); + + $multiSearch = new MultiSearch($client); + + $search1 = new Search($client); + $search1->addIndex($index)->addType($type); + $query1 = new Query(); + $termQuery1 = new Term(); + $termQuery1->setTerm('username', 'farrelley'); + $query1->setQuery($termQuery1); + $query1->setSize(2); + $search1->setQuery($query1); + + $multiSearch->addSearch($search1, "search1"); + + $this->assertCount(1, $multiSearch->getSearches()); + + $search2 = new Search($client); + $search2->addIndex($index)->addType($type); + $query2 = new Query(); + $termQuery2 = new Term(); + $termQuery2->setTerm('username', 'bunny'); + $query2->setQuery($termQuery2); + $query2->setSize(3); + $search2->setQuery($query2); + + $multiSearch->addSearch($search2, "search2"); + + $this->assertCount(2, $multiSearch->getSearches()); + + $searches = $multiSearch->getSearches(); + $this->assertSame($search1, $searches["search1"]); + $this->assertSame($search2, $searches["search2"]); + + $multiResultSet = $multiSearch->search(); + + $this->assertInstanceOf('Elastica\Multi\ResultSet', $multiResultSet); + $this->assertCount(2, $multiResultSet); + $this->assertInstanceOf('Elastica\Response', $multiResultSet->getResponse()); + + foreach ($multiResultSet as $resultSet) { + $this->assertInstanceOf('Elastica\ResultSet', $resultSet); + } + + $this->assertInstanceOf('Elastica\ResultSet', $multiResultSet["search1"]); + $this->assertInstanceOf('Elastica\ResultSet', $multiResultSet["search2"]); + + $resultSets = $multiResultSet->getResultSets(); + + $this->assertInternalType('array', $resultSets); + + $this->assertArrayHasKey("search1", $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets["search1"]); + $this->assertCount(2, $resultSets["search1"]); + $this->assertSame($query1, $resultSets["search1"]->getQuery()); + $this->assertEquals(3, $resultSets["search1"]->getTotalHits()); + + $this->assertArrayHasKey("search2", $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets["search2"]); + $this->assertCount(3, $resultSets["search2"]); + $this->assertSame($query2, $resultSets["search2"]->getQuery()); + $this->assertEquals(6, $resultSets["search2"]->getTotalHits()); + + $this->assertFalse($multiResultSet->hasError()); + + $search1->setOption(Search::OPTION_SEARCH_TYPE, Search::OPTION_SEARCH_TYPE_COUNT); + $search2->setOption(Search::OPTION_SEARCH_TYPE, Search::OPTION_SEARCH_TYPE_COUNT); + + $multiResultSet = $multiSearch->search(); + + $this->assertInstanceOf('Elastica\Multi\ResultSet', $multiResultSet); + $this->assertCount(2, $multiResultSet); + $this->assertInstanceOf('Elastica\Response', $multiResultSet->getResponse()); + + $resultSets = $multiResultSet->getResultSets(); + + $this->assertInternalType('array', $resultSets); + + $this->assertArrayHasKey("search1", $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets["search1"]); + $this->assertCount(0, $resultSets["search1"]); + $this->assertSame($query1, $resultSets["search1"]->getQuery()); + $this->assertEquals(3, $resultSets["search1"]->getTotalHits()); + + $this->assertArrayHasKey("search2", $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets["search2"]); + $this->assertCount(0, $resultSets["search2"]); + $this->assertSame($query2, $resultSets["search2"]->getQuery()); + $this->assertEquals(6, $resultSets["search2"]->getTotalHits()); + } + + public function testSearchWithError() + { + $type = $this->_createType(); + $index = $type->getIndex(); + $client = $index->getClient(); + + $multiSearch = new MultiSearch($client); + + $searchGood = new Search($client); + $searchGood->setQuery('bunny'); + $searchGood->addIndex($index)->addType($type); + + $multiSearch->addSearch($searchGood); + + $searchBad = new Search($client); + $searchBadQuery = new Range(); + $searchBadQuery->addField('bad', array('from' => 0)); + $searchBadQuery->setParam('_cache', true); + $searchBad->setQuery($searchBadQuery); + $searchBad->addIndex($index)->addType($type); + + $multiSearch->addSearch($searchBad); + + $multiResultSet = $multiSearch->search(); + + $this->assertInstanceOf('Elastica\Multi\ResultSet', $multiResultSet); + $resultSets = $multiResultSet->getResultSets(); + $this->assertInternalType('array', $resultSets); + + $this->assertArrayHasKey(0, $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets[0]); + $this->assertSame($searchGood->getQuery(), $resultSets[0]->getQuery()); + $this->assertSame(6, $resultSets[0]->getTotalHits()); + $this->assertCount(6, $resultSets[0]); + + $this->assertArrayHasKey(1, $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets[1]); + $this->assertSame($searchBad->getQuery(), $resultSets[1]->getQuery()); + $this->assertSame(0, $resultSets[1]->getTotalHits()); + $this->assertCount(0, $resultSets[1]); + $this->assertTrue($resultSets[1]->getResponse()->hasError()); + + $this->assertTrue($multiResultSet->hasError()); + } + + public function testSearchWithErrorWithKeys() + { + $type = $this->_createType(); + $index = $type->getIndex(); + $client = $index->getClient(); + + $multiSearch = new MultiSearch($client); + + $searchGood = new Search($client); + $searchGood->setQuery('bunny'); + $searchGood->addIndex($index)->addType($type); + + $multiSearch->addSearch($searchGood, "search1"); + + $searchBad = new Search($client); + $searchBadQuery = new Range(); + $searchBadQuery->addField('bad', array('from' => 0)); + $searchBadQuery->setParam('_cache', true); + $searchBad->setQuery($searchBadQuery); + $searchBad->addIndex($index)->addType($type); + + $multiSearch->addSearch($searchBad); + + $multiResultSet = $multiSearch->search(); + + $this->assertInstanceOf('Elastica\Multi\ResultSet', $multiResultSet); + $resultSets = $multiResultSet->getResultSets(); + $this->assertInternalType('array', $resultSets); + + $this->assertArrayHasKey("search1", $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets["search1"]); + $this->assertSame($searchGood->getQuery(), $resultSets["search1"]->getQuery()); + $this->assertSame(6, $resultSets["search1"]->getTotalHits()); + $this->assertCount(6, $resultSets["search1"]); + + $this->assertArrayHasKey(0, $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets[0]); + $this->assertSame($searchBad->getQuery(), $resultSets[0]->getQuery()); + $this->assertSame(0, $resultSets[0]->getTotalHits()); + $this->assertCount(0, $resultSets[0]); + $this->assertTrue($resultSets[0]->getResponse()->hasError()); + + $this->assertTrue($multiResultSet->hasError()); + } + + public function testGlobalSearchTypeSearch() + { + $type = $this->_createType(); + $index = $type->getIndex(); + $client = $index->getClient(); + + $multiSearch = new MultiSearch($client); + + $search1 = new Search($client); + $search1->addIndex($index)->addType($type); + $query1 = new Query(); + $termQuery1 = new Term(); + $termQuery1->setTerm('username', 'farrelley'); + $query1->setQuery($termQuery1); + $query1->setSize(2); + $search1->setQuery($query1); + + $multiSearch->addSearch($search1); + + $this->assertCount(1, $multiSearch->getSearches()); + + $search2 = new Search($client); + $search2->addIndex($index)->addType($type); + $query2 = new Query(); + $termQuery2 = new Term(); + $termQuery2->setTerm('username', 'bunny'); + $query2->setQuery($termQuery2); + $query2->setSize(3); + $search2->setQuery($query2); + + $multiSearch->addSearch($search2); + + $multiSearch->setSearchType(Search::OPTION_SEARCH_TYPE_COUNT); + + $multiResultSet = $multiSearch->search(); + + $this->assertInstanceOf('Elastica\Multi\ResultSet', $multiResultSet); + $this->assertCount(2, $multiResultSet); + $this->assertInstanceOf('Elastica\Response', $multiResultSet->getResponse()); + + $resultSets = $multiResultSet->getResultSets(); + + $this->assertInternalType('array', $resultSets); + + $this->assertArrayHasKey(0, $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets[0]); + $this->assertCount(0, $resultSets[0]); + $this->assertSame($query1, $resultSets[0]->getQuery()); + $this->assertEquals(3, $resultSets[0]->getTotalHits()); + + $this->assertArrayHasKey(1, $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets[1]); + $this->assertCount(0, $resultSets[1]); + $this->assertSame($query2, $resultSets[1]->getQuery()); + $this->assertEquals(6, $resultSets[1]->getTotalHits()); + + $search1->setOption(Search::OPTION_SEARCH_TYPE, Search::OPTION_SEARCH_TYPE_QUERY_AND_FETCH); + + $multiResultSet = $multiSearch->search(); + + $this->assertInstanceOf('Elastica\Multi\ResultSet', $multiResultSet); + $this->assertCount(2, $multiResultSet); + $this->assertInstanceOf('Elastica\Response', $multiResultSet->getResponse()); + + $resultSets = $multiResultSet->getResultSets(); + + $this->assertInternalType('array', $resultSets); + + $this->assertArrayHasKey(0, $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets[0]); + $this->assertCount(2, $resultSets[0]); + $this->assertSame($query1, $resultSets[0]->getQuery()); + $this->assertEquals(3, $resultSets[0]->getTotalHits()); + + $this->assertArrayHasKey(1, $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets[1]); + $this->assertCount(0, $resultSets[1]); + $this->assertSame($query2, $resultSets[1]->getQuery()); + $this->assertEquals(6, $resultSets[1]->getTotalHits()); + } + + public function testGlobalSearchTypeSearchWithKeys() + { + $type = $this->_createType(); + $index = $type->getIndex(); + $client = $index->getClient(); + + $multiSearch = new MultiSearch($client); + + $search1 = new Search($client); + $search1->addIndex($index)->addType($type); + $query1 = new Query(); + $termQuery1 = new Term(); + $termQuery1->setTerm('username', 'farrelley'); + $query1->setQuery($termQuery1); + $query1->setSize(2); + $search1->setQuery($query1); + + $multiSearch->addSearch($search1); + + $this->assertCount(1, $multiSearch->getSearches()); + + $search2 = new Search($client); + $search2->addIndex($index)->addType($type); + $query2 = new Query(); + $termQuery2 = new Term(); + $termQuery2->setTerm('username', 'bunny'); + $query2->setQuery($termQuery2); + $query2->setSize(3); + $search2->setQuery($query2); + + $multiSearch->addSearch($search2); + + $multiSearch->setSearchType(Search::OPTION_SEARCH_TYPE_COUNT); + + $multiResultSet = $multiSearch->search(); + + $this->assertInstanceOf('Elastica\Multi\ResultSet', $multiResultSet); + $this->assertCount(2, $multiResultSet); + $this->assertInstanceOf('Elastica\Response', $multiResultSet->getResponse()); + + $resultSets = $multiResultSet->getResultSets(); + + $this->assertInternalType('array', $resultSets); + + $this->assertArrayHasKey(0, $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets[0]); + $this->assertCount(0, $resultSets[0]); + $this->assertSame($query1, $resultSets[0]->getQuery()); + $this->assertEquals(3, $resultSets[0]->getTotalHits()); + + $this->assertArrayHasKey(1, $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets[1]); + $this->assertCount(0, $resultSets[1]); + $this->assertSame($query2, $resultSets[1]->getQuery()); + $this->assertEquals(6, $resultSets[1]->getTotalHits()); + + $search1->setOption(Search::OPTION_SEARCH_TYPE, Search::OPTION_SEARCH_TYPE_QUERY_AND_FETCH); + + $multiResultSet = $multiSearch->search(); + + $this->assertInstanceOf('Elastica\Multi\ResultSet', $multiResultSet); + $this->assertCount(2, $multiResultSet); + $this->assertInstanceOf('Elastica\Response', $multiResultSet->getResponse()); + + $resultSets = $multiResultSet->getResultSets(); + + $this->assertInternalType('array', $resultSets); + + $this->assertArrayHasKey(0, $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets[0]); + $this->assertCount(2, $resultSets[0]); + $this->assertSame($query1, $resultSets[0]->getQuery()); + $this->assertEquals(3, $resultSets[0]->getTotalHits()); + + $this->assertArrayHasKey(1, $resultSets); + $this->assertInstanceOf('Elastica\ResultSet', $resultSets[1]); + $this->assertCount(0, $resultSets[1]); + $this->assertSame($query2, $resultSets[1]->getQuery()); + $this->assertEquals(6, $resultSets[1]->getTotalHits()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Node/InfoTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Node/InfoTest.php new file mode 100644 index 00000000..10886b2d --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Node/InfoTest.php @@ -0,0 +1,42 @@ +<?php + +namespace Elastica\Test\Node; + +use Elastica\Node; +use Elastica\Node\Info as NodeInfo; +use Elastica\Test\Base as BaseTest; + +class InfoTest extends BaseTest +{ + public function testGet() + { + $client = $this->_getClient(); + $names = $client->getCluster()->getNodeNames(); + $name = reset($names); + + $node = new Node($name, $client); + $info = new NodeInfo($node); + + $this->assertNull($info->get('os', 'mem', 'total')); + + // Load os infos + $info = new NodeInfo($node, array('os')); + + $this->assertTrue(!is_null($info->get('os', 'mem', 'total_in_bytes'))); + $this->assertInternalType('array', $info->get('os', 'mem')); + $this->assertNull($info->get('test', 'notest', 'notexist')); + } + + public function testHasPlugin() + { + $client = $this->_getClient(); + $nodes = $client->getCluster()->getNodes(); + $node = $nodes[0]; + $info = $node->getInfo(); + + $pluginName = 'mapper-attachments'; + + $this->assertTrue($info->hasPlugin($pluginName)); + $this->assertFalse($info->hasPlugin('foo')); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/NodeTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/NodeTest.php new file mode 100644 index 00000000..d70825d1 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/NodeTest.php @@ -0,0 +1,84 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Client; +use Elastica\Node; +use Elastica\Test\Base as BaseTest; + +class NodeTest extends BaseTest +{ + + public function testCreateNode() + { + $client = $this->_getClient(); + $names = $client->getCluster()->getNodeNames(); + $name = reset($names); + + $node = new Node($name, $client); + $this->assertInstanceOf('Elastica\Node', $node); + } + + public function testGetInfo() + { + $client = $this->_getClient(); + $names = $client->getCluster()->getNodeNames(); + $name = reset($names); + + $node = new Node($name, $client); + + $info = $node->getInfo(); + + $this->assertInstanceOf('Elastica\Node\Info', $info); + } + + public function testGetStats() + { + $client = $this->_getClient(); + $names = $client->getCluster()->getNodeNames(); + $name = reset($names); + + $node = new Node($name, $client); + + $stats = $node->getStats(); + + $this->assertInstanceOf('Elastica\Node\Stats', $stats); + } + + /** + * Shuts one of two nodes down (if two available) + */ + public function testShutdown() + { + $this->markTestSkipped('At least two nodes have to be running, because 1 node is shutdown'); + $client = $this->_getClient(); + $nodes = $client->getCluster()->getNodes(); + + $count = count($nodes); + if ($count < 2) { + $this->markTestSkipped('At least two nodes have to be running, because 1 node is shutdown'); + } + + // Store node info of node with port 9200 for later + foreach ($nodes as $key => $node) { + if ($node->getInfo()->getPort() == 9200) { + $info = $node->getInfo(); + unset($nodes[$key]); + } + } + + // Select one of the not port 9200 nodes and shut it down + $node = array_shift($nodes); + $node->shutdown('2s'); + + // Wait until node is shutdown + sleep(5); + + // Use still existing node + $client = new Client(array('host' => $info->getIp(), 'port' => $info->getPort())); + $names = $client->getCluster()->getNodeNames(); + + // One node less ... + $this->assertEquals($count - 1, count($names)); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/ParamTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/ParamTest.php new file mode 100644 index 00000000..fab77600 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/ParamTest.php @@ -0,0 +1,97 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Param; +use Elastica\Util; +use Elastica\Test\Base as BaseTest; + +class ParamTest extends BaseTest +{ + public function testToArrayEmpty() + { + $param = new Param(); + $this->assertInstanceOf('Elastica\Param', $param); + $this->assertEquals(array($this->_getFilterName($param) => array()), $param->toArray()); + } + + public function testSetParams() + { + $param = new Param(); + $params = array('hello' => 'word', 'nicolas' => 'ruflin'); + $param->setParams($params); + + $this->assertInstanceOf('Elastica\Param', $param); + $this->assertEquals(array($this->_getFilterName($param) => $params), $param->toArray()); + } + + public function testSetGetParam() + { + $param = new Param(); + + $key = 'name'; + $value = 'nicolas ruflin'; + + $params = array($key => $value); + $param->setParam($key, $value); + + $this->assertEquals($params, $param->getParams()); + $this->assertEquals($value, $param->getParam($key)); + } + + public function testAddParam() + { + $param = new Param(); + + $key = 'name'; + $value = 'nicolas ruflin'; + + $param->addParam($key, $value); + + $this->assertEquals(array($key => array($value)), $param->getParams()); + $this->assertEquals(array($value), $param->getParam($key)); + } + + public function testAddParam2() + { + $param = new Param(); + + $key = 'name'; + $value1 = 'nicolas'; + $value2 = 'ruflin'; + + $param->addParam($key, $value1); + $param->addParam($key, $value2); + + $this->assertEquals(array($key => array($value1, $value2)), $param->getParams()); + $this->assertEquals(array($value1, $value2), $param->getParam($key)); + } + + /** + * @expectedException \Elastica\Exception\InvalidException + */ + public function testGetParamInvalid() + { + $param = new Param(); + + $param->getParam('notest'); + } + + public function testHasParam() + { + $param = new Param(); + + $key = 'name'; + $value = 'nicolas ruflin'; + + $this->assertFalse($param->hasParam($key)); + + $param->setParam($key, $value); + $this->assertTrue($param->hasParam($key)); + } + + protected function _getFilterName($filter) + { + return Util::getParamName($filter); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/PercolatorTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/PercolatorTest.php new file mode 100644 index 00000000..f4cfae0c --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/PercolatorTest.php @@ -0,0 +1,224 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Client; +use Elastica\Document; +use Elastica\Index; +use Elastica\Percolator; +use Elastica\Query\Term; +use Elastica\Query; +use Elastica\Test\Base as BaseTest; + +class PercolatorTest extends BaseTest +{ + public function testConstruct() + { + $percolatorName = 'percotest'; + + $index = $this->_createIndex($percolatorName); + $percolator = new Percolator($index); + + $query = new Term(array('field1' => 'value1')); + $response = $percolator->registerQuery($percolatorName, $query); + + $data = $response->getData(); + + $expectedArray = array( + '_type' => '.percolator', + '_index' => $index->getName(), + '_id' => $percolatorName, + '_version' => 1, + 'created' => 1 + ); + + $this->assertEquals($expectedArray, $data); + + $index->delete(); + } + + public function testMatchDoc() + { + $index = $this->_createIndex(); + $percolator = new Percolator($index); + + $percolatorName = 'percotest'; + + $query = new Term(array('name' => 'ruflin')); + $response = $percolator->registerQuery($percolatorName, $query); + + $this->assertTrue($response->isOk()); + $this->assertFalse($response->hasError()); + + $doc1 = new Document(); + $doc1->set('name', 'ruflin'); + + $doc2 = new Document(); + $doc2->set('name', 'nicolas'); + + $index->refresh(); + + $matches1 = $percolator->matchDoc($doc1); + + $this->assertCount(1, $matches1); + $firstPercolatorFound = false; + foreach ($matches1 as $match) { + if ($match['_id'] == $percolatorName) { + $firstPercolatorFound = true; + } + } + $this->assertTrue($firstPercolatorFound); + + $matches2 = $percolator->matchDoc($doc2); + $this->assertEmpty($matches2); + + $index->delete(); + } + + /** + * Test case for using filtered percolator queries based on the Elasticsearch documentation examples. + */ + public function testFilteredMatchDoc() + { + // step one: register create index and setup the percolator query from the ES documentation. + $index = $this->_createIndex(); + $percolator = new Percolator($index); + $baseQuery = new Term(array('field1' => 'value1')); + $fields = array('color' => 'blue'); + + $response = $percolator->registerQuery('kuku', $baseQuery, $fields); + + $this->assertTrue($response->isOk()); + $this->assertFalse($response->hasError()); + + // refreshing is required in order to ensure the query is really ready for execution. + $index->refresh(); + + // step two: match a document which should match the kuku query when filtered on the blue color + $doc = new Document(); + $doc->set('field1', 'value1'); + + $matches = $percolator->matchDoc($doc, new Term(array('color' => 'blue'))); + $this->assertCount(1, $matches, 'No or too much registered query matched.'); + $this->assertEquals('kuku', $matches[0]['_id'], 'A wrong registered query has matched.'); + + // step three: validate that using a different color, no registered query matches. + $matches = $percolator->matchDoc($doc, new Term(array('color' => 'green'))); + $this->assertCount(0, $matches, 'A registered query matched, although nothing should match at all.'); + + $index->delete(); + } + + /** + * Test case for using filtered percolator queries based on the Elasticsearch documentation examples. + */ + public function testRegisterAndUnregisterPercolator() + { + // step one: register create index and setup the percolator query from the ES documentation. + $index = $this->_createIndex(); + $percolator = new Percolator($index); + $baseQuery = new Term(array('field1' => 'value1')); + $fields = array('color' => 'blue'); + + $response = $percolator->registerQuery('kuku', $baseQuery, $fields); + + $this->assertTrue($response->isOk()); + $this->assertFalse($response->hasError()); + + // refreshing is required in order to ensure the query is really ready for execution. + $index->refresh(); + + // step two: match a document which should match the kuku query when filtered on the blue color + $doc = new Document(); + $doc->set('field1', 'value1'); + + $matches = $percolator->matchDoc($doc, new Term(array('color' => 'blue'))); + $this->assertCount(1, $matches, 'No or too much registered query matched.'); + $this->assertEquals('kuku', $matches[0]['_id'], 'A wrong registered query has matched.'); + + // step three: validate that using a different color, no registered query matches. + $matches = $percolator->matchDoc($doc, new Term(array('color' => 'green'))); + $this->assertCount(0, $matches, 'A registered query matched, although nothing should match at all.'); + + + // unregister percolator query + $response = $percolator->unregisterQuery('kuku'); + + $this->assertTrue($response->isOk()); + $this->assertFalse($response->hasError()); + + // refreshing is required in order to ensure the query is really ready for execution. + $index->refresh(); + + $matches = $percolator->matchDoc($doc, new Term(array('color' => 'blue'))); + $this->assertCount(0, $matches, 'Percolator query did not get deleted.'); + + $index->delete(); + } + + protected function _getDefaultPercolator($percolatorName = 'existingDoc') + { + $index = $this->_createIndex(); + $percolator = new Percolator($index); + + $query = new Term(array('name' => 'foobar')); + $percolator->registerQuery($percolatorName, $query); + return $percolator; + } + + protected function _addDefaultDocuments($index, $type='testing') + { + $type = $index->getType('testing'); + $doc1 = new Document(1, array('name' => 'foobar')); + $doc2 = new Document(2, array('name' => 'barbaz')); + $type->addDocument($doc1); + $type->addDocument($doc2); + $index->refresh(); + return $type; + } + + public function testPercolateExistingDocWithoutAnyParameter() + { + $percolator = $this->_getDefaultPercolator(); + $index = $percolator->getIndex(); + $type = $this->_addDefaultDocuments($index); + + $matches = $percolator->matchExistingDoc(1, $type->getName()); + + $this->assertCount(1, $matches); + $this->assertEquals('existingDoc', $matches[0]['_id']); + $index->delete(); + } + + public function testPercolateExistingDocWithPercolateFormatIds() + { + $percolator = $this->_getDefaultPercolator(); + $index = $percolator->getIndex(); + $type = $this->_addDefaultDocuments($index); + + $parameter = array('percolate_format' => 'ids'); + $matches = $percolator->matchExistingDoc(1, $type->getName(), null, $parameter); + + $this->assertCount(1, $matches); + $this->assertEquals('existingDoc', $matches[0]); + $index->delete(); + } + + public function testPercolateExistingDocWithIdThatShouldBeUrlEncoded() + { + $percolator = $this->_getDefaultPercolator(); + $index = $percolator->getIndex(); + $type = $this->_addDefaultDocuments($index); + + // id with whitespace, should be urlencoded + $id = "foo bar 1"; + + $type->addDocument(new Document($id, array('name' => 'foobar'))); + $index->refresh(); + + $matches = $percolator->matchExistingDoc($id, $type->getName()); + + $this->assertCount(1, $matches); + $index->delete(); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/BoolTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/BoolTest.php new file mode 100644 index 00000000..d3bd90cd --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/BoolTest.php @@ -0,0 +1,114 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Document; +use Elastica\Index; +use Elastica\Query\Bool; +use Elastica\Query\Ids; +use Elastica\Query\Term; +use Elastica\Test\Base as BaseTest; +use Elastica\Type; + +class BoolTest extends BaseTest +{ + public function testToArray() + { + $query = new Bool(); + + $idsQuery1 = new Ids(); + $idsQuery1->setIds(1); + + $idsQuery2 = new Ids(); + $idsQuery2->setIds(2); + + $idsQuery3 = new Ids(); + $idsQuery3->setIds(3); + + $boost = 1.2; + $minMatch = 2; + + $query->setBoost($boost); + $query->setMinimumNumberShouldMatch($minMatch); + $query->addMust($idsQuery1); + $query->addMustNot($idsQuery2); + $query->addShould($idsQuery3->toArray()); + + $expectedArray = array( + 'bool' => array( + 'must' => array($idsQuery1->toArray()), + 'should' => array($idsQuery3->toArray()), + 'minimum_number_should_match' => $minMatch, + 'must_not' => array($idsQuery2->toArray()), + 'boost' => $boost, + ) + ); + + $this->assertEquals($expectedArray, $query->toArray()); + } + + /** + * Test to resolve the following issue + * + * https://groups.google.com/forum/?fromgroups#!topic/elastica-php-client/zK_W_hClfvU + */ + public function testToArrayStructure() + { + $boolQuery = new Bool(); + + $term1 = new Term(); + $term1->setParam('interests', 84); + + $term2 = new Term(); + $term2->setParam('interests', 92); + + $boolQuery->addShould($term1)->addShould($term2); + + $jsonString = '{"bool":{"should":[{"term":{"interests":84}},{"term":{"interests":92}}]}}'; + $this->assertEquals($jsonString, json_encode($boolQuery->toArray())); + } + + public function testSearch() + { + $client = $this->_getClient(); + $index = new Index($client, 'test'); + $index->create(array(), true); + + $type = new Type($index, 'helloworld'); + + $doc = new Document(1, array('id' => 1, 'email' => 'hans@test.com', 'username' => 'hans', 'test' => array('2', '3', '5'))); + $type->addDocument($doc); + $doc = new Document(2, array('id' => 2, 'email' => 'emil@test.com', 'username' => 'emil', 'test' => array('1', '3', '6'))); + $type->addDocument($doc); + $doc = new Document(3, array('id' => 3, 'email' => 'ruth@test.com', 'username' => 'ruth', 'test' => array('2', '3', '7'))); + $type->addDocument($doc); + + // Refresh index + $index->refresh(); + + $boolQuery = new Bool(); + $termQuery1 = new Term(array('test' => '2')); + $boolQuery->addMust($termQuery1); + $resultSet = $type->search($boolQuery); + + $this->assertEquals(2, $resultSet->count()); + + $termQuery2 = new Term(array('test' => '5')); + $boolQuery->addMust($termQuery2); + $resultSet = $type->search($boolQuery); + + $this->assertEquals(1, $resultSet->count()); + + $termQuery3 = new Term(array('username' => 'hans')); + $boolQuery->addMust($termQuery3); + $resultSet = $type->search($boolQuery); + + $this->assertEquals(1, $resultSet->count()); + + $termQuery4 = new Term(array('username' => 'emil')); + $boolQuery->addMust($termQuery4); + $resultSet = $type->search($boolQuery); + + $this->assertEquals(0, $resultSet->count()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/BoostingTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/BoostingTest.php new file mode 100644 index 00000000..f5af8740 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/BoostingTest.php @@ -0,0 +1,99 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Document; +use Elastica\Query\Boosting; +use Elastica\Test\Base as BaseTest; + +class BoostingTest extends BaseTest +{ + /** + * @var \Elastica\Index + */ + protected $index; + + /** + * @var \Elastica\Type + */ + protected $type; + + /* + * @var array + */ + protected $sampleData; + + protected function setUp() + { + parent::setUp(); + $this->index = $this->_createIndex('test_boostingquery'); + $this->type = $this->index->getType('test'); + $this->type->setMapping(array( + 'name' => array('type' => 'string', 'index' => 'analyzed'), + 'price' => array('type' => 'float') + )); + + $this->sampleData = array( + array("name" => "Vital Lama", "price" => 5.2), + array("name" => "Vital Match", "price" => 2.1), + array("name" => "Mercury Vital", "price" => 7.5), + array("name" => "Fist Mercury", "price" => 3.8), + array("name" => "Lama Vital 2nd", "price" => 3.2) + ); + + foreach($this->sampleData as $key => $value) { + $this->type->addDocument(new Document($key, $value)); + } + + $this->index->refresh(); + } + + protected function tearDown() + { + $this->index->delete(); + parent::tearDown(); + } + + public function testToArray() + { + $keyword = "vital"; + $negativeKeyword = "Mercury"; + + $query = new Boosting(); + $positiveQuery = new \Elastica\Query\Term(array('name' => $keyword)); + $negativeQuery = new \Elastica\Query\Term(array('name' => $negativeKeyword)); + $query->setPositiveQuery($positiveQuery); + $query->setNegativeQuery($negativeQuery); + $query->setNegativeBoost(0.3); + + $expected = array( + 'boosting' => array( + 'positive' => $positiveQuery->toArray(), + 'negative' => $negativeQuery->toArray(), + 'negative_boost' => 0.3 + ) + ); + $this->assertEquals($expected, $query->toArray()); + } + + public function testNegativeBoost() + { + $keyword = "vital"; + $negativeKeyword = "mercury"; + + $query = new Boosting(); + $positiveQuery = new \Elastica\Query\Term(array('name' => $keyword)); + $negativeQuery = new \Elastica\Query\Term(array('name' => $negativeKeyword)); + $query->setPositiveQuery($positiveQuery); + $query->setNegativeQuery($negativeQuery); + $query->setNegativeBoost(0.2); + + $response = $this->type->search($query); + $results = $response->getResults(); + + $this->assertEquals($response->getTotalHits(), 4); + + $lastResult = $results[3]->getData(); + $this->assertEquals($lastResult['name'], $this->sampleData[2]['name']); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/BuilderTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/BuilderTest.php new file mode 100644 index 00000000..5875c4ba --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/BuilderTest.php @@ -0,0 +1,270 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Query\Builder; +use Elastica\Test\Base as BaseTest; + +class BuilderTest extends BaseTest +{ + /** + * @var \Elastica\Query\Builder + */ + private $builder; + + public function setUp() + { + $this->builder = new Builder(); + } + + public function tearDown() + { + $this->builder = null; + } + + /** + * @covers \Elastica\Query\Builder::factory + * @covers \Elastica\Query\Builder::__construct + */ + public function testFactory() + { + $this->assertInstanceOf( + 'Elastica\Query\Builder', + Builder::factory('some string') + ); + } + + public function getQueryData() + { + return array( + array('allowLeadingWildcard', false, '{"allow_leading_wildcard":"false"}'), + array('allowLeadingWildcard', true, '{"allow_leading_wildcard":"true"}'), + array('analyzeWildcard', false, '{"analyze_wildcard":"false"}'), + array('analyzeWildcard', true, '{"analyze_wildcard":"true"}'), + array('analyzer', 'someAnalyzer', '{"analyzer":"someAnalyzer"}'), + array('autoGeneratePhraseQueries', true, '{"auto_generate_phrase_queries":"true"}'), + array('autoGeneratePhraseQueries', false, '{"auto_generate_phrase_queries":"false"}'), + array('boost', 2, '{"boost":"2"}'), + array('boost', 4.2, '{"boost":"4.2"}'), + array('defaultField', 'fieldName', '{"default_field":"fieldName"}'), + array('defaultOperator', 'OR', '{"default_operator":"OR"}'), + array('defaultOperator', 'AND', '{"default_operator":"AND"}'), + array('enablePositionIncrements', true, '{"enable_position_increments":"true"}'), + array('enablePositionIncrements', false, '{"enable_position_increments":"false"}'), + array('explain', true, '{"explain":"true"}'), + array('explain', false, '{"explain":"false"}'), + array('from', 42, '{"from":"42"}'), + array('fuzzyMinSim', 4.2, '{"fuzzy_min_sim":"4.2"}'), + array('fuzzyPrefixLength', 2, '{"fuzzy_prefix_length":"2"}'), + array('gt', 10, '{"gt":"10"}'), + array('gte', 11, '{"gte":"11"}'), + array('lowercaseExpandedTerms', true, '{"lowercase_expanded_terms":"true"}'), + array('lt', 10, '{"lt":"10"}'), + array('lte', 11, '{"lte":"11"}'), + array('minimumNumberShouldMatch', 21, '{"minimum_number_should_match":"21"}'), + array('phraseSlop', 6, '{"phrase_slop":"6"}'), + array('size', 7, '{"size":"7"}'), + array('tieBreakerMultiplier', 7, '{"tie_breaker_multiplier":"7"}'), + array('matchAll', 1.1, '{"match_all":{"boost":"1.1"}}'), + array('fields', array("age", "sex", "location"), '{"fields":["age","sex","location"]}'), + ); + } + + /** + * @dataProvider getQueryData + * @covers \Elastica\Query\Builder::__toString + * @covers \Elastica\Query\Builder::allowLeadingWildcard + * @covers \Elastica\Query\Builder::analyzeWildcard + * @covers \Elastica\Query\Builder::analyzer + * @covers \Elastica\Query\Builder::autoGeneratePhraseQueries + * @covers \Elastica\Query\Builder::boost + * @covers \Elastica\Query\Builder::defaultField + * @covers \Elastica\Query\Builder::defaultOperator + * @covers \Elastica\Query\Builder::enablePositionIncrements + * @covers \Elastica\Query\Builder::explain + * @covers \Elastica\Query\Builder::from + * @covers \Elastica\Query\Builder::fuzzyMinSim + * @covers \Elastica\Query\Builder::fuzzyPrefixLength + * @covers \Elastica\Query\Builder::gt + * @covers \Elastica\Query\Builder::gte + * @covers \Elastica\Query\Builder::lowercaseExpandedTerms + * @covers \Elastica\Query\Builder::lt + * @covers \Elastica\Query\Builder::lte + * @covers \Elastica\Query\Builder::minimumNumberShouldMatch + * @covers \Elastica\Query\Builder::phraseSlop + * @covers \Elastica\Query\Builder::size + * @covers \Elastica\Query\Builder::tieBreakerMultiplier + * @covers \Elastica\Query\Builder::matchAll + * @covers \Elastica\Query\Builder::fields + */ + public function testAllowLeadingWildcard($method, $argument, $result) + { + $this->assertSame($this->builder, $this->builder->$method($argument)); + $this->assertSame($result, (string) $this->builder); + } + + public function getQueryTypes() + { + return array( + array('bool', 'bool'), + array('constantScore', 'constant_score'), + array('disMax', 'dis_max'), + array('facets', 'facets'), + array('filter', 'filter'), + array('filteredQuery', 'filtered'), + array('must', 'must'), + array('mustNot', 'must_not'), + array('prefix', 'prefix'), + array('query', 'query'), + array('queryString', 'query_string'), + array('range', 'range'), + array('should', 'should'), + array('sort', 'sort'), + array('term', 'term'), + array('textPhrase', 'text_phrase'), + array('wildcard', 'wildcard'), + ); + } + + /** + * @dataProvider getQueryTypes + * + * @covers \Elastica\Query\Builder::fieldClose + * @covers \Elastica\Query\Builder::close + * + * @covers \Elastica\Query\Builder::bool + * @covers \Elastica\Query\Builder::boolClose + * @covers \Elastica\Query\Builder::constantScore + * @covers \Elastica\Query\Builder::constantScoreClose + * @covers \Elastica\Query\Builder::disMax + * @covers \Elastica\Query\Builder::disMaxClose + * @covers \Elastica\Query\Builder::facets + * @covers \Elastica\Query\Builder::facetsClose + * @covers \Elastica\Query\Builder::filter + * @covers \Elastica\Query\Builder::filterClose + * @covers \Elastica\Query\Builder::filteredQuery + * @covers \Elastica\Query\Builder::filteredQueryClose + * @covers \Elastica\Query\Builder::must + * @covers \Elastica\Query\Builder::mustClose + * @covers \Elastica\Query\Builder::mustNot + * @covers \Elastica\Query\Builder::mustNotClose + * @covers \Elastica\Query\Builder::prefix + * @covers \Elastica\Query\Builder::prefixClose + * @covers \Elastica\Query\Builder::query + * @covers \Elastica\Query\Builder::queryClose + * @covers \Elastica\Query\Builder::queryString + * @covers \Elastica\Query\Builder::queryStringClose + * @covers \Elastica\Query\Builder::range + * @covers \Elastica\Query\Builder::rangeClose + * @covers \Elastica\Query\Builder::should + * @covers \Elastica\Query\Builder::shouldClose + * @covers \Elastica\Query\Builder::sort + * @covers \Elastica\Query\Builder::sortClose + * @covers \Elastica\Query\Builder::term + * @covers \Elastica\Query\Builder::termClose + * @covers \Elastica\Query\Builder::textPhrase + * @covers \Elastica\Query\Builder::textPhraseClose + * @covers \Elastica\Query\Builder::wildcard + * @covers \Elastica\Query\Builder::wildcardClose + */ + public function testQueryTypes($method, $queryType) + { + $this->assertSame($this->builder, $this->builder->$method()); // open + $this->assertSame($this->builder, $this->builder->{$method."Close"}()); // close + $this->assertSame('{"' . $queryType . '":{}}', (string) $this->builder); + } + + /** + * @covers \Elastica\Query\Builder::fieldOpen + * @covers \Elastica\Query\Builder::fieldClose + * @covers \Elastica\Query\Builder::open + * @covers \Elastica\Query\Builder::close + */ + public function testFieldOpenAndClose() + { + $this->assertSame($this->builder, $this->builder->fieldOpen('someField')); + $this->assertSame($this->builder, $this->builder->fieldClose()); + $this->assertSame('{"someField":{}}', (string) $this->builder); + } + + /** + * @covers \Elastica\Query\Builder::sortField + */ + public function testSortField() + { + $this->assertSame($this->builder, $this->builder->sortField('name', true)); + $this->assertSame('{"sort":{"name":{"reverse":"true"}}}', (string) $this->builder); + } + + /** + * @covers \Elastica\Query\Builder::sortFields + */ + public function testSortFields() + { + $this->assertSame($this->builder, $this->builder->sortFields(array('field1' => 'asc', 'field2' => 'desc', 'field3' => 'asc'))); + $this->assertSame('{"sort":[{"field1":"asc"},{"field2":"desc"},{"field3":"asc"}]}', (string) $this->builder); + } + + /** + * @covers \Elastica\Query\Builder::queries + */ + public function testQueries() + { + $queries = array(); + + $b1 = clone $this->builder; + $b2 = clone $this->builder; + + $queries[] = $b1->term()->field('age', 34)->termClose(); + $queries[] = $b2->term()->field('name', 'christer')->termClose(); + + $this->assertSame($this->builder, $this->builder->queries($queries)); + $this->assertSame('{"queries":[{"term":{"age":"34"}},{"term":{"name":"christer"}}]}', (string) $this->builder); + } + + public function getFieldData() + { + return array( + array('name', 'value', '{"name":"value"}'), + array('name', true, '{"name":"true"}'), + array('name', false, '{"name":"false"}'), + array('name', array(1, 2, 3), '{"name":["1","2","3"]}'), + array('name', array('foo', 'bar', 'baz'), '{"name":["foo","bar","baz"]}'), + ); + } + + /** + * @dataProvider getFieldData + * @covers \Elastica\Query\Builder::field + */ + public function testField($name, $value, $result) + { + $this->assertSame($this->builder, $this->builder->field($name, $value)); + $this->assertSame($result, (string) $this->builder); + } + + /** + * @expectedException \Elastica\Exception\InvalidException + * @covers \Elastica\Query\Builder::toArray + */ + public function testToArrayWithInvalidData() + { + $this->builder->open('foo'); + $this->builder->toArray(); + } + + /** + * @covers \Elastica\Query\Builder::toArray + */ + public function testToArray() + { + $this->builder->query()->term()->field('category.id', array(1, 2, 3))->termClose()->queryClose(); + $this->assertEquals(array( + 'query' => array( + 'term' => array( + 'category.id' => array(1, 2, 3) + ) + ) + ), $this->builder->toArray()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/CommonTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/CommonTest.php new file mode 100644 index 00000000..a84d6397 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/CommonTest.php @@ -0,0 +1,59 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Query\Common; +use Elastica\Test\Base as BaseTest; + +class CommonTest extends BaseTest +{ + public function testToArray() + { + $query = new Common('body', 'test query', .001); + $query->setLowFrequencyOperator(Common::OPERATOR_AND); + + $expected = array( + 'common' => array( + 'body' => array( + 'query' => 'test query', + 'cutoff_frequency' => .001, + 'low_freq_operator' => 'and' + ) + ) + ); + + $this->assertEquals($expected, $query->toArray()); + } + + public function testQuery() + { + $index = $this->_createIndex('common_test'); + $type = $index->getType('test'); + + //add documents to create common terms + $docs = array(); + for ($i = 0; $i < 20; $i++) { + $docs[] = new \Elastica\Document($i, array('body' => 'foo bar')); + } + $type->addDocuments($docs); + + $type->addDocument(new \Elastica\Document(20, array('body' => 'foo baz'))); + $type->addDocument(new \Elastica\Document(21, array('body' => 'foo bar baz'))); + $type->addDocument(new \Elastica\Document(22, array('body' => 'foo bar baz bat'))); + $index->refresh(); + + $query = new Common('body', 'foo bar baz bat', .5); + $results = $type->search($query)->getResults(); + + //documents containing only common words should not be returned + $this->assertEquals(3, sizeof($results)); + + $query->setMinimumShouldMatch(2); + $results = $type->search($query); + + //only the document containing both low frequency terms should match + $this->assertEquals(1, $results->count()); + + $index->delete(); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/ConstantScoreTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/ConstantScoreTest.php new file mode 100644 index 00000000..27143eb6 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/ConstantScoreTest.php @@ -0,0 +1,158 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Filter\Term; +use Elastica\Filter\Ids; +use Elastica\Query\ConstantScore; +use Elastica\Query\MatchAll; +use Elastica\Test\Base as BaseTest; +use Elastica\Index; +use Elastica\Document; +use Elastica\Type; + +class ConstantScoreTest extends BaseTest +{ + public function dataProviderSampleQueries() + { + return array( + array( + new Term(array('foo', 'bar')), + array( + 'constant_score' => array( + 'filter' => array( + 'term' => array( + 'foo', + 'bar', + ), + ), + ), + ), + ), + array( + array( + 'and' => array( + array( + 'query' => array( + 'query_string' => array( + 'query' => 'foo', + 'default_field' => 'something', + ), + ), + ), + array( + 'query' => array( + 'query_string' => array( + 'query' => 'bar', + 'default_field' => 'something', + ), + ), + ), + ), + ), + '{"constant_score":{"filter":{"and":[{"query":{"query_string":{"query":"foo","default_field":"something"}}},{"query":{"query_string":{"query":"bar","default_field":"something"}}}]}}}', + ), + ); + } + /** + * @dataProvider dataProviderSampleQueries + */ + public function testSimple($filter, $expected) + { + $query = new ConstantScore(); + $query->setFilter($filter); + if (is_string($expected)) { + $expected = json_decode($expected, true); + } + $this->assertEquals($expected, $query->toArray()); + } + + public function testToArray() + { + $query = new ConstantScore(); + + $boost = 1.2; + $filter = new Ids(); + $filter->setIds(array(1)); + + $query->setFilter($filter); + $query->setBoost($boost); + + $expectedArray = array( + 'constant_score' => array( + 'filter' => $filter->toArray(), + 'boost' => $boost + ) + ); + + $this->assertEquals($expectedArray, $query->toArray()); + } + + public function testConstruct() + { + $filter = new Ids(); + $filter->setIds(array(1)); + + $query = new ConstantScore($filter); + + $expectedArray = array( + 'constant_score' => array( + 'filter' => $filter->toArray(), + ) + ); + + $this->assertEquals($expectedArray, $query->toArray()); + + } + + public function testQuery() + { + + $client = $this->_getClient(); + $index = new Index($client, 'test'); + $index->create(array(), true); + + $type = new Type($index, 'constant_score'); + + $doc = new Document(1, array('id' => 1, 'email' => 'hans@test.com', 'username' => 'hans')); + $type->addDocument($doc); + $doc = new Document(2, array('id' => 2, 'email' => 'emil@test.com', 'username' => 'emil')); + $type->addDocument($doc); + $doc = new Document(3, array('id' => 3, 'email' => 'ruth@test.com', 'username' => 'ruth')); + $type->addDocument($doc); + + // Refresh index + $index->refresh(); + + $boost = 1.3; + $query_match = new MatchAll(); + + $query = new ConstantScore(); + $query->setQuery($query_match); + $query->setBoost($boost); + + $expectedArray = array( + 'constant_score' => array( + 'query' => $query_match->toArray(), + 'boost' => $boost + ) + ); + + $this->assertEquals($expectedArray, $query->toArray()); + $resultSet = $type->search($query); + + $results = $resultSet->getResults(); + + $this->assertEquals($resultSet->count(), 3); + $this->assertEquals($results[1]->getScore(), 1); + + } + + public function testConstructEmpty() + { + $query = new ConstantScore(); + $expectedArray = array('constant_score' => array()); + + $this->assertEquals($expectedArray, $query->toArray()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/DisMaxTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/DisMaxTest.php new file mode 100644 index 00000000..31c8437d --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/DisMaxTest.php @@ -0,0 +1,83 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Document; +use Elastica\Query\DisMax; +use Elastica\Query\Ids; +use Elastica\Query\QueryString; +use Elastica\Test\Base as BaseTest; + +class DisMaxTest extends BaseTest +{ + public function testToArray() + { + $query = new DisMax(); + + $idsQuery1 = new Ids(); + $idsQuery1->setIds(1); + + $idsQuery2 = new Ids(); + $idsQuery2->setIds(2); + + $idsQuery3 = new Ids(); + $idsQuery3->setIds(3); + + $boost = 1.2; + $tieBreaker = 2; + + $query->setBoost($boost); + $query->setTieBreaker($tieBreaker); + $query->addQuery($idsQuery1); + $query->addQuery($idsQuery2); + $query->addQuery($idsQuery3->toArray()); + + $expectedArray = array( + 'dis_max' => array( + 'tie_breaker' => $tieBreaker, + 'boost' => $boost, + 'queries' => array( + $idsQuery1->toArray(), + $idsQuery2->toArray(), + $idsQuery3->toArray() + ) + ) + ); + + $this->assertEquals($expectedArray, $query->toArray()); + } + + public function testQuery() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('test'); + + $doc = new Document(1, array('name' => 'Basel-Stadt')); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'New York')); + $type->addDocument($doc); + $doc = new Document(3, array('name' => 'Baden')); + $type->addDocument($doc); + $doc = new Document(4, array('name' => 'Baden Baden')); + $type->addDocument($doc); + + $index->refresh(); + + $queryString1 = new QueryString('Bade*'); + $queryString2 = new QueryString('Base*'); + + $boost = 1.2; + $tieBreaker = 2; + + $query = new DisMax(); + $query->setBoost($boost); + $query->setTieBreaker($tieBreaker); + $query->addQuery($queryString1); + $query->addQuery($queryString2); + $resultSet = $type->search($query); + + $this->assertEquals(3, $resultSet->count()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/FilteredTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/FilteredTest.php new file mode 100644 index 00000000..c6bd9096 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/FilteredTest.php @@ -0,0 +1,112 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Document; +use Elastica\Filter\Term; +use Elastica\Query\Filtered; +use Elastica\Query\QueryString; +use Elastica\Test\Base as BaseTest; + +class FilteredTest extends BaseTest +{ + public function testFilteredSearch() + { + $index = $this->_createIndex(); + $type = $index->getType('helloworld'); + + $doc = new Document(1, array('id' => 1, 'email' => 'test@test.com', 'username' => 'hanswurst', 'test' => array('2', '3', '5'))); + $type->addDocument($doc); + $doc = new Document(2, array('id' => 2, 'email' => 'test@test.com', 'username' => 'peter', 'test' => array('2', '3', '5'))); + $type->addDocument($doc); + + $queryString = new QueryString('test*'); + + $filter1 = new Term(); + $filter1->setTerm('username', 'peter'); + + $filter2 = new Term(); + $filter2->setTerm('username', 'qwerqwer'); + + $query1 = new Filtered($queryString, $filter1); + $query2 = new Filtered($queryString, $filter2); + $index->refresh(); + + $resultSet = $type->search($queryString); + $this->assertEquals(2, $resultSet->count()); + + $resultSet = $type->search($query1); + $this->assertEquals(1, $resultSet->count()); + + $resultSet = $type->search($query2); + $this->assertEquals(0, $resultSet->count()); + } + + public function testFilteredGetter() + { + $queryString = new QueryString('test*'); + + $filter1 = new Term(); + $filter1->setTerm('username', 'peter'); + + $filter2 = new Term(); + $filter2->setTerm('username', 'qwerqwer'); + + $query1 = new Filtered($queryString, $filter1); + $query2 = new Filtered($queryString, $filter2); + + $this->assertEquals($query1->getQuery(), $queryString); + $this->assertEquals($query2->getQuery(), $queryString); + $this->assertEquals($query1->getFilter(), $filter1); + $this->assertEquals($query2->getFilter(), $filter2); + } + + /** + * @expectedException \Elastica\Exception\InvalidException + */ + public function testFilteredWithoutArgumentsShouldRaiseException() + { + $query = new Filtered(); + $query->toArray(); + } + + public function testFilteredSearchNoQuery() + { + $index = $this->_createIndex(); + $type = $index->getType('helloworld'); + + $doc = new Document(1, array('id' => 1, 'email' => 'test@test.com', 'username' => 'hanswurst', 'test' => array('2', '3', '5'))); + $type->addDocument($doc); + $doc = new Document(2, array('id' => 2, 'email' => 'test@test.com', 'username' => 'peter', 'test' => array('2', '3', '5'))); + $type->addDocument($doc); + + $filter = new Term(); + $filter->setTerm('username', 'peter'); + + $query = new Filtered(null, $filter); + $index->refresh(); + + $resultSet = $type->search($query); + $this->assertEquals(1, $resultSet->count()); + } + + public function testFilteredSearchNoFilter() + { + $index = $this->_createIndex(); + $type = $index->getType('helloworld'); + + $doc = new Document(1, array('id' => 1, 'email' => 'test@test.com', 'username' => 'hanswurst', 'test' => array('2', '3', '5'))); + $type->addDocument($doc); + $doc = new Document(2, array('id' => 2, 'email' => 'test@test.com', 'username' => 'peter', 'test' => array('2', '3', '5'))); + $type->addDocument($doc); + + $queryString = new QueryString('hans*'); + + $query = new Filtered($queryString); + $index->refresh(); + + $resultSet = $type->search($query); + $this->assertEquals(1, $resultSet->count()); + } + +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/FunctionScoreTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/FunctionScoreTest.php new file mode 100644 index 00000000..47d9dd2c --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/FunctionScoreTest.php @@ -0,0 +1,210 @@ +<?php +/** + * User: Joe Linn + * Date: 9/16/13 + * Time: 5:05 PM + */ + +namespace Elastica\Test\Query; + +use Elastica\Document; +use Elastica\Filter\Term; +use Elastica\Query\FunctionScore; +use Elastica\Script; +use Elastica\Test\Base as BaseTest; + +class FunctionScoreTest extends BaseTest +{ + /** + * @var \Elastica\Index + */ + protected $index; + + /** + * @var \Elastica\Type + */ + protected $type; + + protected $locationOrigin = "32.804654, -117.242594"; + + protected function setUp() + { + parent::setUp(); + $this->index = $this->_createIndex('test_functionscore'); + $this->type = $this->index->getType('test'); + $this->type->setMapping(array( + 'name' => array('type' => 'string', 'index' => 'not_analyzed'), + 'location' => array('type' => 'geo_point'), + 'price' => array('type' => 'float') + )); + + $this->type->addDocument(new Document(1, array( + 'name' => "Mr. Frostie's", + 'location' => array('lat' => 32.799605, 'lon' => -117.243027), + 'price' => 4.5 + ))); + $this->type->addDocument(new Document(2, array( + 'name' => "Miller's Field", + 'location' => array('lat' => 32.795964, 'lon' => -117.255028), + 'price' => 9.5 + ))); + + $this->index->refresh(); + } + + protected function tearDown() + { + $this->index->delete(); + parent::tearDown(); + } + + public function testToArray() + { + $priceOrigin = 0; + $locationScale = '2mi'; + $priceScale = 9.25; + $query = new FunctionScore(); + $childQuery = new \Elastica\Query\MatchAll(); + $query->setQuery($childQuery); + $query->addDecayFunction(FunctionScore::DECAY_GAUSS, 'location', $this->locationOrigin, $locationScale); + $query->addDecayFunction(FunctionScore::DECAY_GAUSS, 'price', $priceOrigin, $priceScale); + $expected = array( + 'function_score' => array( + 'query' => $childQuery->toArray(), + 'functions' => array( + array( + 'gauss' => array( + 'location' => array( + 'origin' => $this->locationOrigin, + 'scale' => $locationScale + ) + ) + ), + array( + 'gauss' => array( + 'price' => array( + 'origin' => $priceOrigin, + 'scale' => $priceScale + ) + ) + ) + ) + ) + ); + $this->assertEquals($expected, $query->toArray()); + } + + public function testGauss() + { + $query = new FunctionScore(); + $query->addDecayFunction(FunctionScore::DECAY_GAUSS, 'location', $this->locationOrigin, "4mi"); + $query->addDecayFunction(FunctionScore::DECAY_GAUSS, 'price', 0, 10); + $response = $this->type->search($query); + $results = $response->getResults(); + + // the document with the closest location and lowest price should be scored highest + $result0 = $results[0]->getData(); + $this->assertEquals("Mr. Frostie's", $result0['name']); + } + + public function testBoostFactor() + { + $filter = new Term(array('price' => 4.5)); + $query = new FunctionScore(); + $query->addBoostFactorFunction(5.0, $filter); + $expected = array( + 'function_score' => array( + 'functions' => array( + array( + 'boost_factor' => 5.0, + 'filter' => array( + 'term' => array( + 'price' => 4.5 + ) + ) + ) + ) + ) + ); + + $this->assertEquals($expected, $query->toArray()); + + $response = $this->type->search($query); + $results = $response->getResults(); + + // the document with price = 4.5 should be scored highest + $result0 = $results[0]->getData(); + $this->assertEquals("Mr. Frostie's", $result0['name']); + } + + public function testRandomScore() + { + $filter = new Term(array('price' => 4.5)); + $query = new FunctionScore(); + $query->addRandomScoreFunction(2, $filter); + $expected = array( + 'function_score' => array( + 'functions' => array( + array( + 'random_score' => array( + 'seed' => 2 + ), + 'filter' => array( + 'term' => array( + 'price' => 4.5 + ) + ) + ) + ) + ) + ); + + $this->assertEquals($expected, $query->toArray()); + + $response = $this->type->search($query); + $results = $response->getResults(); + + // the document with the random score should have a score > 1, means it is the first result + $result0 = $results[1]->getData(); + + $this->assertEquals("Miller's Field", $result0['name']); + } + + public function testRandomScoreWithoutSeed() + { + $query = new FunctionScore(); + $query->setRandomScore(); + + $response = $this->type->search($query); + + $this->assertEquals(2, $response->count()); + } + + public function testScriptScore() + { + $scriptString = "_score * doc['price'].value"; + $script = new Script($scriptString); + $query = new FunctionScore(); + $query->addScriptScoreFunction($script); + $expected = array( + 'function_score' => array( + 'functions' => array( + array( + 'script_score' => array( + 'script' => $scriptString + ) + ) + ) + ) + ); + + $this->assertEquals($expected, $query->toArray()); + + $response = $this->type->search($query); + $results = $response->getResults(); + + // the document the highest price should be scored highest + $result0 = $results[0]->getData(); + $this->assertEquals("Miller's Field", $result0['name']); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/FuzzyLikeThisTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/FuzzyLikeThisTest.php new file mode 100644 index 00000000..c842c1a8 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/FuzzyLikeThisTest.php @@ -0,0 +1,228 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Document; +use Elastica\Index; +use Elastica\Query\FuzzyLikeThis; +use Elastica\Type; +use Elastica\Type\Mapping; +use Elastica\Test\Base as BaseTest; + +class FuzzyLikeThisTest extends BaseTest +{ + public function testSearch() + { + $client = $this->_getClient(); + $index = new Index($client, 'test'); + $index->create(array(), true); + $index->getSettings()->setNumberOfReplicas(0); + //$index->getSettings()->setNumberOfShards(1); + + $type = new Type($index, 'helloworldfuzzy'); + $mapping = new Mapping($type , array( + 'email' => array('store' => 'yes', 'type' => 'string', 'index' => 'analyzed'), + 'content' => array('store' => 'yes', 'type' => 'string', 'index' => 'analyzed'), + )); + + $mapping->setSource(array('enabled' => false)); + $type->setMapping($mapping); + + $doc = new Document(1000, array('email' => 'testemail@gmail.com', 'content' => 'This is a sample post. Hello World Fuzzy Like This!')); + $type->addDocument($doc); + + // Refresh index + $index->refresh(); + + $fltQuery = new FuzzyLikeThis(); + $fltQuery->setLikeText("sample gmail"); + $fltQuery->addFields(array("email","content")); + $fltQuery->setMinSimilarity(0.3); + $fltQuery->setMaxQueryTerms(3); + $resultSet = $type->search($fltQuery); + $this->assertEquals(1, $resultSet->count()); + } + + public function testSetPrefixLength() + { + $query = new FuzzyLikeThis(); + + $length = 3; + $query->setPrefixLength($length); + + $data = $query->toArray(); + + $this->assertEquals($length, $data['fuzzy_like_this']['prefix_length']); + } + + public function testAddFields() + { + $query = new FuzzyLikeThis(); + + $fields = array('test1', 'test2'); + $query->addFields($fields); + + $data = $query->toArray(); + + $this->assertEquals($fields, $data['fuzzy_like_this']['fields']); + } + + public function testSetLikeText() + { + $query = new FuzzyLikeThis(); + + $text = ' hello world'; + $query->setLikeText($text); + + $data = $query->toArray(); + + $this->assertEquals(trim($text), $data['fuzzy_like_this']['like_text']); + } + + public function testSetIgnoreTF() + { + $query = new FuzzyLikeThis(); + + $ignoreTF = false; + $query->setIgnoreTF($ignoreTF); + $data = $query->toArray(); + $this->assertEquals($ignoreTF, $data['fuzzy_like_this']['ignore_tf']); + + $ignoreTF = true; + $query->setIgnoreTF($ignoreTF); + $data = $query->toArray(); + $this->assertEquals($ignoreTF, $data['fuzzy_like_this']['ignore_tf']); + } + + public function testSetIgnoreTFDefault() + { + $query = new FuzzyLikeThis(); + + $data = $query->toArray(); + + $defaultIgnoreTF = false; + $this->assertEquals($defaultIgnoreTF, $data['fuzzy_like_this']['ignore_tf']); + } + + public function testSetMinSimilarity() + { + $query = new FuzzyLikeThis(); + + $similarity = 2; + $query->setMinSimilarity($similarity); + + $data = $query->toArray(); + + $this->assertEquals($similarity, $data['fuzzy_like_this']['min_similarity']); + } + + public function testSetBoost() + { + $query = new FuzzyLikeThis(); + + $boost = 2.2; + $query->setBoost($boost); + + $data = $query->toArray(); + + $this->assertEquals($boost, $data['fuzzy_like_this']['boost']); + } + + public function testAddAnalyzerViasetParam() + { + $analyzer = 'snowball'; + + $query = new FuzzyLikeThis(); + $query->setParam('analyzer', $analyzer); + + $data = $query->toArray(); + $this->assertEquals($analyzer, $data['fuzzy_like_this']['analyzer']); + } + + public function testSetAnalyzer() + { + $analyzer = 'snowball'; + + $query = new FuzzyLikeThis(); + $query->setAnalyzer($analyzer); + + $data = $query->toArray(); + $this->assertEquals($analyzer, $data['fuzzy_like_this']['analyzer']); + } + + public function testAnalyzerNotPresentInArrayToMaintainDefaultOfField() + { + $query = new FuzzyLikeThis(); + + $data = $query->toArray(); + $this->assertArrayNotHasKey('analyzer', $data); + } + + public function testArgArrayFieldsOverwrittenBySetParams() + { + $query = new FuzzyLikeThis(); + $query->setMaxQueryTerms(100); + $query->setParam('max_query_terms', 200); + + $data = $query->toArray(); + $this->assertEquals(200, $data['fuzzy_like_this']['max_query_terms']); + } + + public function testSearchSetAnalyzer() + { + $client = $this->_getClient(); + $index = new Index($client, 'test'); + $index->create(array('analysis' => array( + 'analyzer' => array( + 'searchAnalyzer' => array( + 'type' => 'custom', + 'tokenizer' => 'standard', + 'filter' => array('myStopWords') + ) + ), + 'filter' => array( + 'myStopWords' => array( + 'type' => 'stop', + 'stopwords' => array('The') + ) + ) + )), true); + + $index->getSettings()->setNumberOfReplicas(0); + //$index->getSettings()->setNumberOfShards(1); + + $type = new Type($index, 'helloworldfuzzy'); + $mapping = new Mapping($type , array( + 'email' => array('store' => 'yes', 'type' => 'string', 'index' => 'analyzed'), + 'content' => array('store' => 'yes', 'type' => 'string', 'index' => 'analyzed'), + )); + + $mapping->setSource(array('enabled' => false)); + $type->setMapping($mapping); + + $doc = new Document(1000, array('email' => 'testemail@gmail.com', 'content' => 'The Fuzzy Test!')); + $type->addDocument($doc); + + $doc = new Document(1001, array('email' => 'testemail@gmail.com', 'content' => 'Elastica Fuzzy Test')); + $type->addDocument($doc); + + // Refresh index + $index->refresh(); + + $fltQuery = new FuzzyLikeThis(); + $fltQuery->addFields(array("email","content")); + $fltQuery->setLikeText("The"); + + $fltQuery->setMinSimilarity(0.1); + $fltQuery->setMaxQueryTerms(3); + + // Test before analyzer applied, should return 1 result + $resultSet = $type->search($fltQuery); + $this->assertEquals(1, $resultSet->count()); + + $fltQuery->setParam('analyzer', 'searchAnalyzer'); + + $resultSet = $type->search($fltQuery); + $this->assertEquals(0, $resultSet->count()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/FuzzyTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/FuzzyTest.php new file mode 100644 index 00000000..57659293 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/FuzzyTest.php @@ -0,0 +1,129 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Document; +use Elastica\Query\Fuzzy; +use Elastica\Test\Base as BaseTest; + +class FuzzyTest extends BaseTest +{ + public function testToArray() + { + $fuzzy = new Fuzzy(); + $fuzzy->addField('user', array('value' => 'Nicolas', 'boost' => 1.0)); + $expectedArray = array( + 'fuzzy' => array( + 'user' => array( + 'value' => 'Nicolas', + 'boost' => 1.0 + ) + ) + ); + $this->assertEquals($expectedArray, $fuzzy->toArray(), 'Deprecated method failed'); + + $fuzzy = new Fuzzy('user', 'Nicolas'); + $expectedArray = array( + 'fuzzy' => array( + 'user' => array( + 'value' => 'Nicolas', + ) + ) + ); + $this->assertEquals($expectedArray, $fuzzy->toArray()); + + $fuzzy = new Fuzzy(); + $fuzzy->setField('user', 'Nicolas')->setFieldOption('boost', 1.0); + $expectedArray = array( + 'fuzzy' => array( + 'user' => array( + 'value' => 'Nicolas', + 'boost' => 1.0 + ) + ) + ); + $this->assertEquals($expectedArray, $fuzzy->toArray()); + } + + public function testQuery() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('test'); + + $doc = new Document(1, array('name' => 'Basel-Stadt')); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'New York')); + $type->addDocument($doc); + $doc = new Document(3, array('name' => 'Baden')); + $type->addDocument($doc); + $doc = new Document(4, array('name' => 'Baden Baden')); + $type->addDocument($doc); + + $index->refresh(); + + $field = 'name'; + + $query = new Fuzzy(); + $query->setField($field, 'Baden'); + + $resultSet = $index->search($query); + + $this->assertEquals(2, $resultSet->count()); + } + + public function testBadArguments () + { + $this->setExpectedException('Elastica\Exception\InvalidException'); + $query = new Fuzzy(); + $query->addField('name', array(array('value' => 'Baden'))); + + $this->setExpectedException('Elastica\Exception\InvalidException'); + $query = new Fuzzy(); + $query->setField('name', array()); + + $this->setExpectedException('Elastica\Exception\InvalidException'); + $query = new Fuzzy(); + $query->setField('name', 'value'); + $query->setField('name1', 'value1'); + } + + public function testFuzzyWithFacets() { + + $index = $this->_createIndex(); + $type = $index->getType('test'); + + $doc = new Document(1, array('name' => 'Basel-Stadt')); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'New York')); + $type->addDocument($doc); + $doc = new Document(3, array('name' => 'Baden')); + $type->addDocument($doc); + $doc = new Document(4, array('name' => 'Baden Baden')); + $type->addDocument($doc); + + $index->refresh(); + + $field = 'name'; + + $fuzzyQuery = new Fuzzy(); + $fuzzyQuery->setField($field, 'Baden'); + + $facet = new \Elastica\Facet\Terms('test'); + $facet->setField('name'); + + $query = new \Elastica\Query($fuzzyQuery); + $query->addFacet($facet); + + $resultSet = $index->search($query); + + // Assert query worked ok + $this->assertEquals(2, $resultSet->count()); + + // Check Facets + $this->assertTrue($resultSet->hasFacets()); + $facets = $resultSet->getFacets(); + $this->assertEquals(2, $facets['test']['total']); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/HasChildTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/HasChildTest.php new file mode 100644 index 00000000..bb1b5b96 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/HasChildTest.php @@ -0,0 +1,107 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Document; +use Elastica\Query\HasChild; +use Elastica\Query\MatchAll; +use Elastica\Test\Base as BaseTest; + +class HasChildTest extends BaseTest +{ + public function testToArray() + { + $q = new MatchAll(); + + $type = 'test'; + + $query = new HasChild($q, $type); + + $expectedArray = array( + 'has_child' => array( + 'query' => $q->toArray(), + 'type' => $type + ) + ); + + $this->assertEquals($expectedArray, $query->toArray()); + } + + public function testSetScope() + { + $q = new MatchAll(); + + $type = 'test'; + + $scope = 'foo'; + + $query = new HasChild($q, $type); + $query->setScope($scope); + + $expectedArray = array( + 'has_child' => array( + 'query' => $q->toArray(), + 'type' => $type, + '_scope' => $scope + ) + ); + + $this->assertEquals($expectedArray, $query->toArray()); + } + + public function testTypeInsideHasChildSearch() + { + $index = $this->prepareSearchData(); + + $f = new \Elastica\Query\Match(); + $f->setField('alt.name', 'testname'); + $query = new HasChild($f, 'child'); + + $searchQuery = new \Elastica\Query(); + $searchQuery->setQuery($query); + $searchResults = $index->search($searchQuery); + + $this->assertEquals(1, $searchResults->count()); + + $result = $searchResults->current()->getData(); + $expected = array('id' => 'parent2', 'user' => 'parent2', 'email' => 'parent2@test.com'); + + $this->assertEquals($expected, $result); + } + + private function prepareSearchData() + { + $client = $this->_getClient(); + $index = $client->getIndex('has_child_test'); + $index->create(array(), true); + + $parentType = $index->getType('parent'); + + $childType = $index->getType('child'); + $childMapping = new \Elastica\Type\Mapping($childType); + $childMapping->setParent('parent'); + $childMapping->send(); + + $altType = $index->getType('alt'); + $altDoc = new Document('alt1', array('name' => 'altname')); + $altType->addDocument($altDoc); + + $parent1 = new Document('parent1', array('id' => 'parent1', 'user' => 'parent1', 'email' => 'parent1@test.com')); + $parentType->addDocument($parent1); + $parent2 = new Document('parent2', array('id' => 'parent2', 'user' => 'parent2', 'email' => 'parent2@test.com')); + $parentType->addDocument($parent2); + + $child1 = new Document('child1', array('id' => 'child1', 'user' => 'child1', 'email' => 'child1@test.com')); + $child1->setParent('parent1'); + $childType->addDocument($child1); + $child2 = new Document('child2', array('id' => 'child2', 'user' => 'child2', 'email' => 'child2@test.com')); + $child2->setParent('parent2'); + $childType->addDocument($child2); + $child3 = new Document('child3', array('id' => 'child3', 'user' => 'child3', 'email' => 'child3@test.com', 'alt' => array(array('name' => 'testname')))); + $child3->setParent('parent2'); + $childType->addDocument($child3); + + $index->refresh(); + return $index; + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/HasParentTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/HasParentTest.php new file mode 100644 index 00000000..d417c887 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/HasParentTest.php @@ -0,0 +1,50 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Query\HasParent; +use Elastica\Query\MatchAll; +use Elastica\Test\Base as BaseTest; + +class HasParentTest extends BaseTest +{ + public function testToArray() + { + $q = new MatchAll(); + + $type = 'test'; + + $query = new HasParent($q, $type); + + $expectedArray = array( + 'has_parent' => array( + 'query' => $q->toArray(), + 'type' => $type + ) + ); + + $this->assertEquals($expectedArray, $query->toArray()); + } + + public function testSetScope() + { + $q = new MatchAll(); + + $type = 'test'; + + $scope = 'foo'; + + $query = new HasParent($q, $type); + $query->setScope($scope); + + $expectedArray = array( + 'has_parent' => array( + 'query' => $q->toArray(), + 'type' => $type, + '_scope' => $scope + ) + ); + + $this->assertEquals($expectedArray, $query->toArray()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/HighlightTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/HighlightTest.php new file mode 100644 index 00000000..4b1b6c5e --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/HighlightTest.php @@ -0,0 +1,49 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Document; +use Elastica\Query; +use Elastica\Query\QueryString; +use Elastica\Test\Base as BaseTest; + +class HighlightTest extends BaseTest +{ + public function testHightlightSearch() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('helloworld'); + + $phrase = 'My name is ruflin'; + + $doc = new Document(1, array('id' => 1, 'phrase' => $phrase, 'username' => 'hanswurst', 'test' => array('2', '3', '5'))); + $type->addDocument($doc); + $doc = new Document(2, array('id' => 2, 'phrase' => $phrase, 'username' => 'peter', 'test' => array('2', '3', '5'))); + $type->addDocument($doc); + + $queryString = new QueryString('rufl*'); + $query = new Query($queryString); + $query->setHighlight(array( + 'pre_tags' => array('<em class="highlight">'), + 'post_tags' => array('</em>'), + 'fields' => array( + 'phrase' => array( + 'fragment_size' => 200, + 'number_of_fragments' => 1, + ), + ), + )); + + $index->refresh(); + + $resultSet = $type->search($query); + foreach ($resultSet as $result) { + $highlight = $result->getHighlights(); + $this->assertEquals(array('phrase' => array(0 => 'My name is <em class="highlight">ruflin</em>')), $highlight); + } + $this->assertEquals(2, $resultSet->count()); + + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/IdsTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/IdsTest.php new file mode 100644 index 00000000..d1bf901e --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/IdsTest.php @@ -0,0 +1,165 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Document; +use Elastica\Query\Ids; +use Elastica\Test\Base as BaseTest; + +class IdsTest extends BaseTest +{ + protected $_index; + protected $_type; + + public function setUp() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + + $type1 = $index->getType('helloworld1'); + $type2 = $index->getType('helloworld2'); + + $doc = new Document(1, array('name' => 'hello world')); + $type1->addDocument($doc); + + $doc = new Document(2, array('name' => 'nicolas ruflin')); + $type1->addDocument($doc); + + $doc = new Document(3, array('name' => 'ruflin')); + $type1->addDocument($doc); + + $doc = new Document(4, array('name' => 'hello world again')); + $type2->addDocument($doc); + + $index->refresh(); + + $this->_type = $type1; + $this->_index = $index; + } + + public function tearDown() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->delete(); + } + + public function testSetIdsSearchSingle() + { + $query = new Ids(); + $query->setIds('1'); + + $resultSet = $this->_type->search($query); + + $this->assertEquals(1, $resultSet->count()); + } + + public function testSetIdsSearchArray() + { + $query = new Ids(); + $query->setIds(array('1', '2')); + + $resultSet = $this->_type->search($query); + + $this->assertEquals(2, $resultSet->count()); + } + + public function testAddIdsSearchSingle() + { + $query = new Ids(); + $query->addId('3'); + + $resultSet = $this->_type->search($query); + + $this->assertEquals(1, $resultSet->count()); + } + + public function testComboIdsSearchArray() + { + $query = new Ids(); + + $query->setIds(array('1', '2')); + $query->addId('3'); + + $resultSet = $this->_type->search($query); + + $this->assertEquals(3, $resultSet->count()); + } + + public function testSetTypeSingleSearchSingle() + { + $query = new Ids(); + + $query->setIds('1'); + $query->setType('helloworld1'); + + $resultSet = $this->_index->search($query); + + $this->assertEquals(1, $resultSet->count()); + } + + public function testSetTypeSingleSearchArray() + { + $query = new Ids(); + + $query->setIds(array('1', '2')); + $query->setType('helloworld1'); + + $resultSet = $this->_index->search($query); + + $this->assertEquals(2, $resultSet->count()); + } + + public function testSetTypeSingleSearchSingleDocInOtherType() + { + $query = new Ids(); + + // Doc 4 is in the second type... + $query->setIds('4'); + $query->setType('helloworld1'); + + $resultSet = $this->_index->search($query); + + // ...therefore 0 results should be returned + $this->assertEquals(0, $resultSet->count()); + } + + public function testSetTypeSingleSearchArrayDocInOtherType() + { + $query = new Ids(); + + // Doc 4 is in the second type... + $query->setIds(array('1', '4')); + $query->setType('helloworld1'); + + $resultSet = $this->_index->search($query); + + // ...therefore only 1 result should be returned + $this->assertEquals(1, $resultSet->count()); + } + + public function testSetTypeArraySearchArray() + { + $query = new Ids(); + + $query->setIds(array('1', '4')); + $query->setType(array('helloworld1', 'helloworld2')); + + $resultSet = $this->_index->search($query); + + $this->assertEquals(2, $resultSet->count()); + } + + public function testSetTypeArraySearchSingle() + { + $query = new Ids(); + + $query->setIds('4'); + $query->setType(array('helloworld1', 'helloworld2')); + + $resultSet = $this->_index->search($query); + + $this->assertEquals(1, $resultSet->count()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/MatchAllTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/MatchAllTest.php new file mode 100644 index 00000000..3731e659 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/MatchAllTest.php @@ -0,0 +1,44 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Document; +use Elastica\Query\MatchAll; +use Elastica\Search; +use Elastica\Test\Base as BaseTest; + +class MatchAllTest extends BaseTest +{ + public function testToArray() + { + $query = new MatchAll(); + + $expectedArray = array('match_all' => new \stdClass()); + + $this->assertEquals($expectedArray, $query->toArray()); + } + + public function testMatchAllIndicesTypes() + { + $index1 = $this->_createIndex('test1'); + $index2 = $this->_createIndex('test2'); + + $client = $index1->getClient(); + + $search1 = new Search($client); + $resultSet1 = $search1->search(new MatchAll()); + + $doc1 = new Document(1, array('name' => 'ruflin')); + $doc2 = new Document(1, array('name' => 'ruflin')); + $index1->getType('test')->addDocument($doc1); + $index2->getType('test')->addDocument($doc2); + + $index1->refresh(); + $index2->refresh(); + + $search2 = new Search($client); + $resultSet2 = $search2->search(new MatchAll()); + + $this->assertEquals($resultSet1->getTotalHits() + 2, $resultSet2->getTotalHits()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/MatchTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/MatchTest.php new file mode 100644 index 00000000..ed164663 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/MatchTest.php @@ -0,0 +1,187 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Document; +use Elastica\Query\Match; +use Elastica\Test\Base as BaseTest; + +class MatchTest extends BaseTest +{ + public function testToArray() + { + $field = 'test'; + $testQuery = 'Nicolas Ruflin'; + $type = 'phrase'; + $operator = 'and'; + $analyzer = 'myanalyzer'; + $boost = 2.0; + $minimumShouldMatch = 2; + $fuzziness = 0.3; + $fuzzyRewrite = 'constant_score_boolean'; + $prefixLength = 3; + $maxExpansions = 12; + + $query = new Match(); + $query->setFieldQuery($field, $testQuery); + $query->setFieldType($field, $type); + $query->setFieldOperator($field, $operator); + $query->setFieldAnalyzer($field, $analyzer); + $query->setFieldBoost($field, $boost); + $query->setFieldMinimumShouldMatch($field, $minimumShouldMatch); + $query->setFieldFuzziness($field, $fuzziness); + $query->setFieldFuzzyRewrite($field, $fuzzyRewrite); + $query->setFieldPrefixLength($field, $prefixLength); + $query->setFieldMaxExpansions($field, $maxExpansions); + + $expectedArray = array( + 'match' => array( + $field => array( + 'query' => $testQuery, + 'type' => $type, + 'operator' => $operator, + 'analyzer' => $analyzer, + 'boost' => $boost, + 'minimum_should_match' => $minimumShouldMatch, + 'fuzziness' => $fuzziness, + 'fuzzy_rewrite' => $fuzzyRewrite, + 'prefix_length' => $prefixLength, + 'max_expansions' => $maxExpansions + ) + ) + ); + + $this->assertEquals($expectedArray, $query->toArray()); + } + + public function testMatch() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('test'); + + $doc = new Document(1, array('name' => 'Basel-Stadt')); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'New York')); + $type->addDocument($doc); + $doc = new Document(3, array('name' => 'New Hampshire')); + $type->addDocument($doc); + $doc = new Document(4, array('name' => 'Basel Land')); + $type->addDocument($doc); + + $index->refresh(); + + $field = 'name'; + $operator = 'or'; + + $query = new Match(); + $query->setFieldQuery($field, 'Basel New'); + $query->setFieldOperator($field, $operator); + + $resultSet = $index->search($query); + + $this->assertEquals(4, $resultSet->count()); + } + + public function testMatchZeroTerm() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('test'); + $doc = new Document(1, array('name' => 'Basel-Stadt')); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'New York')); + $type->addDocument($doc); + $index->refresh(); + + $query = new Match(); + $query->setFieldQuery('name', ''); + $query->setFieldZeroTermsQuery('name', Match::ZERO_TERM_ALL); + + $resultSet = $index->search($query); + + $this->assertEquals(2, $resultSet->count()); + } + + public function testMatchPhrase() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('test'); + + $doc = new Document(1, array('name' => 'Basel-Stadt')); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'New York')); + $type->addDocument($doc); + $doc = new Document(3, array('name' => 'New Hampshire')); + $type->addDocument($doc); + $doc = new Document(4, array('name' => 'Basel Land')); + $type->addDocument($doc); + + $index->refresh(); + + $field = 'name'; + $type = 'phrase'; + + $query = new Match(); + $query->setFieldQuery($field, 'New York'); + $query->setFieldType($field, $type); + + $resultSet = $index->search($query); + + $this->assertEquals(1, $resultSet->count()); + } + + public function testMatchPhrasePrefix() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('test'); + + $doc = new Document(1, array('name' => 'Basel-Stadt')); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'New York')); + $type->addDocument($doc); + $doc = new Document(3, array('name' => 'New Hampshire')); + $type->addDocument($doc); + $doc = new Document(4, array('name' => 'Basel Land')); + $type->addDocument($doc); + + $index->refresh(); + + $field = 'name'; + $type = 'phrase_prefix'; + + $query = new Match(); + $query->setFieldQuery($field, 'New'); + $query->setFieldType($field, $type); + + $resultSet = $index->search($query); + + $this->assertEquals(2, $resultSet->count()); + } + + + public function testMatchFuzzinessType() + { + $field = 'test'; + $query = new Match(); + + $fuzziness = "AUTO"; + $query->setFieldFuzziness($field, $fuzziness); + + $parameters = $query->getParam($field); + $this->assertEquals($fuzziness, $parameters['fuzziness']); + + + $fuzziness = 0.3; + $query->setFieldFuzziness($field, $fuzziness); + + $parameters = $query->getParam($field); + $this->assertEquals($fuzziness, $parameters['fuzziness']); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/MoreLikeThisTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/MoreLikeThisTest.php new file mode 100644 index 00000000..b352e23a --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/MoreLikeThisTest.php @@ -0,0 +1,176 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Document; +use Elastica\Index; +use Elastica\Query; +use Elastica\Query\MoreLikeThis; +use Elastica\Type; +use Elastica\Type\Mapping; +use Elastica\Test\Base as BaseTest; + +class MoreLikeThisTest extends BaseTest +{ + public function testSearch() + { + $client = $this->_getClient(); + $index = new Index($client, 'test'); + $index->create(array(), true); + $index->getSettings()->setNumberOfReplicas(0); + //$index->getSettings()->setNumberOfShards(1); + + $type = new Type($index, 'helloworldmlt'); + $mapping = new Mapping($type , array( + 'email' => array('store' => 'yes', 'type' => 'string', 'index' => 'analyzed'), + 'content' => array('store' => 'yes', 'type' => 'string', 'index' => 'analyzed'), + )); + + $mapping->setSource(array('enabled' => false)); + $type->setMapping($mapping); + + $doc = new Document(1000, array('email' => 'testemail@gmail.com', 'content' => 'This is a sample post. Hello World Fuzzy Like This!')); + $type->addDocument($doc); + + $doc = new Document(1001, array('email' => 'nospam@gmail.com', 'content' => 'This is a fake nospam email address for gmail')); + $type->addDocument($doc); + + // Refresh index + $index->refresh(); + + $mltQuery = new MoreLikeThis(); + $mltQuery->setLikeText('fake gmail sample'); + $mltQuery->setFields(array('email','content')); + $mltQuery->setMaxQueryTerms(1); + $mltQuery->setMinDocFrequency(1); + $mltQuery->setMinTermFrequency(1); + + $query = new Query(); + $query->setFields(array('email', 'content')); + $query->setQuery($mltQuery); + + $resultSet = $type->search($query); + $resultSet->getResponse()->getData(); + $this->assertEquals(2, $resultSet->count()); + } + + public function testSetFields() + { + $query = new MoreLikeThis(); + + $fields = array('firstname', 'lastname'); + $query->setFields($fields); + + $data = $query->toArray(); + $this->assertEquals($fields, $data['more_like_this']['fields']); + } + + public function testSetLikeText() + { + $query = new MoreLikeThis(); + $query->setLikeText(' hello world'); + + $data = $query->toArray(); + $this->assertEquals('hello world', $data['more_like_this']['like_text']); + } + + public function testSetBoost() + { + $query = new MoreLikeThis(); + + $boost = 1.3; + $query->setBoost($boost); + + $this->assertEquals($boost, $query->getParam('boost')); + } + + public function testSetMaxQueryTerms() + { + $query = new MoreLikeThis(); + + $max = 3; + $query->setMaxQueryTerms($max); + + $this->assertEquals($max, $query->getParam('max_query_terms')); + } + + public function testSetPercentTermsToMatch() + { + $query = new MoreLikeThis(); + + $match = 0.8; + $query->setPercentTermsToMatch($match); + + $this->assertEquals($match, $query->getParam('percent_terms_to_match')); + } + + public function testSetMinDocFrequency() + { + $query = new MoreLikeThis(); + + $freq = 2; + $query->setMinDocFrequency($freq); + + $this->assertEquals($freq, $query->getParam('min_doc_freq')); + } + + public function testSetMaxDocFrequency() + { + $query = new MoreLikeThis(); + + $freq = 2; + $query->setMaxDocFrequency($freq); + + $this->assertEquals($freq, $query->getParam('max_doc_freq')); + } + + public function testSetMinWordLength() + { + $query = new MoreLikeThis(); + + $length = 4; + $query->setMinWordLength($length); + + $this->assertEquals($length, $query->getParam('min_word_length')); + } + + public function testSetMaxWordLength() + { + $query = new MoreLikeThis(); + + $length = 5; + $query->setMaxWordLength($length); + + $this->assertEquals($length, $query->getParam('max_word_length')); + } + + public function testSetBoostTerms() + { + $query = new MoreLikeThis(); + + $boost = false; + $query->setBoostTerms($boost); + + $this->assertEquals($boost, $query->getParam('boost_terms')); + } + + public function testSetAnalyzer() + { + $query = new MoreLikeThis(); + + $analyzer = 'UpperCase'; + $query->setAnalyzer($analyzer); + + $this->assertEquals($analyzer, $query->getParam('analyzer')); + } + + public function testSetStopWords() + { + $query = new MoreLikeThis(); + + $stopWords = array('no', 'yes', 'test'); + $query->setStopWords($stopWords); + + $this->assertEquals($stopWords, $query->getParam('stop_words')); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/MultiMatchTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/MultiMatchTest.php new file mode 100644 index 00000000..78a8a8fe --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/MultiMatchTest.php @@ -0,0 +1,187 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Document; +use Elastica\Index; +use Elastica\Query; +use Elastica\Query\MultiMatch; +use Elastica\Test\Base as BaseTest; +use Elastica\Type; +use Elastica\Type\Mapping; + +class MultiMatchTest extends BaseTest +{ + private $index; + private $multiMatch; + + private static $data = array( + array('id' => 1, 'name' => 'Rodolfo', 'last_name' => 'Moraes', 'full_name' => 'Rodolfo Moraes'), + array('id' => 2, 'name' => 'Tristan', 'last_name' => 'Maindron', 'full_name' => 'Tristan Maindron'), + array('id' => 3, 'name' => 'Monique', 'last_name' => 'Maindron', 'full_name' => 'Monique Maindron'), + array('id' => 4, 'name' => 'John', 'last_name' => 'not Doe', 'full_name' => 'John not Doe'), + ); + + protected function setUp() + { + $this->index = $this->_generateIndex(); + $this->multiMatch = new MultiMatch(); + } + + public function testMinimumShouldMatch() + { + $this->multiMatch->setQuery('Tristan Maindron'); + $this->multiMatch->setFields(array('full_name', 'name')); + $this->multiMatch->setMinimumShouldMatch(2); + $resultSet = $this->_getResults(); + + $this->assertEquals(1, $resultSet->count()); + } + + public function testAndOperator() + { + $this->multiMatch->setQuery('Monique Maindron'); + $this->multiMatch->setFields(array('full_name', 'name')); + $this->multiMatch->setOperator(MultiMatch::OPERATOR_AND); + $resultSet = $this->_getResults(); + + $this->assertEquals(1, $resultSet->count()); + } + + public function testType() + { + $this->multiMatch->setQuery('Trist'); + $this->multiMatch->setFields(array('full_name', 'name')); + $this->multiMatch->setType(MultiMatch::TYPE_PHRASE_PREFIX); + $resultSet = $this->_getResults(); + + $this->assertEquals(1, $resultSet->count()); + } + + public function testFuzzy() + { + $this->multiMatch->setQuery('Tritsan'); // Mispell on purpose + $this->multiMatch->setFields(array('full_name', 'name')); + $this->multiMatch->setFuzziness(2); + $resultSet = $this->_getResults(); + + $this->assertEquals(1, $resultSet->count()); + + $this->multiMatch->setQuery('Tritsan'); // Mispell on purpose + $this->multiMatch->setFields(array('full_name', 'name')); + $this->multiMatch->setFuzziness(0); + $resultSet = $this->_getResults(); + + $this->assertEquals(0, $resultSet->count()); + } + + public function testFuzzyWithOptions1() + { + // Here Elasticsearch will not accept mispells + // on the first 6 letters. + $this->multiMatch->setQuery('Tritsan'); // Mispell on purpose + $this->multiMatch->setFields(array('full_name', 'name')); + $this->multiMatch->setFuzziness(2); + $this->multiMatch->setPrefixLength(6); + $resultSet = $this->_getResults(); + + $this->assertEquals(0, $resultSet->count()); + } + + public function testFuzzyWithOptions2() { + + // Here with a 'M' search we should hit 'Moraes' first + // and then stop because MaxExpansion = 1. + // If MaxExpansion was set to 2, we could hit "Maindron" too. + $this->multiMatch->setQuery('M'); + $this->multiMatch->setFields(array('name')); + $this->multiMatch->setType(MultiMatch::TYPE_PHRASE_PREFIX); + $this->multiMatch->setPrefixLength(0); + $this->multiMatch->setMaxExpansions(1); + $resultSet = $this->_getResults(); + + $this->assertEquals(1, $resultSet->count()); + } + + public function testZeroTerm() + { + $this->multiMatch->setQuery('not'); // This is a stopword. + $this->multiMatch->setFields(array('full_name', 'last_name')); + $this->multiMatch->setZeroTermsQuery(MultiMatch::ZERO_TERM_NONE); + $this->multiMatch->setAnalyzer('stops'); + $resultSet = $this->_getResults(); + + $this->assertEquals(0, $resultSet->count()); + + $this->multiMatch->setZeroTermsQuery(MultiMatch::ZERO_TERM_ALL); + $resultSet = $this->_getResults(); + + $this->assertEquals(4, $resultSet->count()); + } + + public function testBaseMultiMatch() + { + $this->multiMatch->setQuery('Rodolfo'); + $this->multiMatch->setFields(array('name', 'last_name')); + $resultSet = $this->_getResults(); + + $this->assertEquals(1, $resultSet->count()); + + $this->multiMatch->setQuery('Moraes'); + $this->multiMatch->setFields(array('name', 'last_name')); + $resultSet = $this->_getResults(); + + $this->assertEquals(1, $resultSet->count()); + } + + /** + * Executes the query with the current multimatch. + */ + private function _getResults() + { + return $this->index->search(new Query($this->multiMatch)); + } + + /** + * Builds an index for testing. + */ + private function _generateIndex() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + + $index->create(array( + 'analysis' => array( + 'analyzer' => array( + 'noStops' => array( + 'type' => 'standard', + 'stopwords' => '_none_' + ), + 'stops' => array( + 'type' => 'standard', + 'stopwords' => array('not') + ), + ), + ) + ), true); + + $type = $index->getType('test'); + + $mapping = new Mapping($type, array( + 'name' => array('type' => 'string', 'store' => 'no', 'analyzer' => 'noStops'), + 'last_name' => array('type' => 'string', 'store' => 'no', 'analyzer' => 'noStops'), + 'full_name' => array('type' => 'string', 'store' => 'no', 'analyzer' => 'noStops'), + )); + + $type->setMapping($mapping); + + foreach (self::$data as $key => $docData) { + $type->addDocument(new Document($key, $docData)); + } + + // Refresh index + $index->refresh(); + + return $index; + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/NestedTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/NestedTest.php new file mode 100644 index 00000000..310a728b --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/NestedTest.php @@ -0,0 +1,28 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Query\Nested; +use Elastica\Query\QueryString; +use Elastica\Test\Base as BaseTest; + +class NestedTest extends BaseTest +{ + public function testSetQuery() + { + $nested = new Nested(); + $path = 'test1'; + + $queryString = new QueryString('test'); + $this->assertInstanceOf('Elastica\Query\Nested', $nested->setQuery($queryString)); + $this->assertInstanceOf('Elastica\Query\Nested', $nested->setPath($path)); + $expected = array( + 'nested' => array( + 'query' => $queryString->toArray(), + 'path' => $path, + ) + ); + + $this->assertEquals($expected, $nested->toArray()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/PostFilterTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/PostFilterTest.php new file mode 100644 index 00000000..16b7e07b --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/PostFilterTest.php @@ -0,0 +1,83 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Document; +use Elastica\Filter\Term; +use Elastica\Index; +use Elastica\Query\Match; +use Elastica\Query; +use Elastica\Test\Base as BaseTest; + +class PostFilterTest extends BaseTest +{ + /** + * @var Index + */ + protected $_index; + + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex("query"); + $docs = array( + new Document("1", array("color" => "green", "make" => "ford")), + new Document("2", array("color" => "blue", "make" => "volvo")), + new Document("3", array("color" => "red", "make" => "ford")), + new Document("4", array("color" => "green", "make" => "renault")), + ); + $this->_index->getType("test")->addDocuments($docs); + $this->_index->refresh(); + + } + + protected function tearDown() + { + parent::tearDown(); + if ($this->_index instanceof Index) { + $this->_index->delete(); + } + } + + public function testToArray() + { + $query = new Query(); + + $post_filter = new Term(array('color' => 'green')); + $query->setPostFilter($post_filter->toArray()); + + $data = $query->toArray(); + + $this->assertArrayHasKey('post_filter', $data); + $this->assertEquals(array('term' => array('color' => 'green')), $data['post_filter']); + + $query->setPostFilter(array()); + + $this->assertArrayNotHasKey('post_filter', $query->toArray()); + } + + public function testQuery() + { + $query = new Query(); + + $match = new Match(); + $match->setField('make', 'ford'); + + $query->setQuery($match); + + $filter = new Term(); + $filter->setTerm('color', 'green'); + + $query->setPostFilter($filter->toArray()); + + $results = $this->_index->search($query); + + $this->assertEquals(1, $results->getTotalHits()); + + } + + protected function _createIndex($name = 'test', $delete = true, $shards = 1) + { + return parent::_createIndex('test_postfilter_' . $name, $delete, $shards); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/PrefixTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/PrefixTest.php new file mode 100644 index 00000000..e6852c2e --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/PrefixTest.php @@ -0,0 +1,26 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Query\Prefix; +use Elastica\Test\Base as BaseTest; + +class PrefixTest extends BaseTest +{ + + public function testToArray() + { + $query = new Prefix(); + $key = 'name'; + $value = 'ni'; + $boost = 2; + $query->setPrefix($key, $value, $boost); + + $data = $query->toArray(); + + $this->assertInternalType('array', $data['prefix']); + $this->assertInternalType('array', $data['prefix'][$key]); + $this->assertEquals($data['prefix'][$key]['value'], $value); + $this->assertEquals($data['prefix'][$key]['boost'], $boost); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/QueryStringTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/QueryStringTest.php new file mode 100644 index 00000000..059bad2d --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/QueryStringTest.php @@ -0,0 +1,126 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Document; +use Elastica\Index; +use Elastica\Type; +use Elastica\Query\QueryString; +use Elastica\Test\Base as BaseTest; + +class QueryStringTest extends BaseTest +{ + public function testSearchMultipleFields() + { + $str = md5(rand()); + $query = new QueryString($str); + + $expected = array( + 'query' => $str + ); + + $this->assertEquals(array('query_string' => $expected), $query->toArray()); + + $fields = array(); + $max = rand() % 10 + 1; + for ($i = 0; $i < $max; $i++) { + $fields[] = md5(rand()); + } + + $query->setFields($fields); + $expected['fields'] = $fields; + $this->assertEquals(array('query_string' => $expected), $query->toArray()); + + foreach (array(false, true) as $val) { + $query->setUseDisMax($val); + $expected['use_dis_max'] = $val; + + $this->assertEquals(array('query_string' => $expected), $query->toArray()); + } + } + + public function testSearch() + { + $client = $this->_getClient(); + $index = new Index($client, 'test'); + $index->create(array(), true); + $index->getSettings()->setNumberOfReplicas(0); + //$index->getSettings()->setNumberOfShards(1); + + $type = new Type($index, 'helloworld'); + + $doc = new Document(1, array('email' => 'test@test.com', 'username' => 'hanswurst', 'test' => array('2', '3', '5'))); + $type->addDocument($doc); + + // Refresh index + $index->refresh(); + + $queryString = new QueryString('test*'); + $resultSet = $type->search($queryString); + + $this->assertEquals(1, $resultSet->count()); + } + + /** + * Tests if search in multiple fields is possible + */ + public function testSearchFields() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + + $doc = new Document(1, array('title' => 'hello world', 'firstname' => 'nicolas', 'lastname' => 'ruflin', 'price' => '102', 'year' => '2012')); + $type->addDocument($doc); + $index->refresh(); + + $query = new QueryString(); + $query = $query->setQuery('ruf*'); + $query = $query->setDefaultField('title'); + $query = $query->setFields(array('title', 'firstname', 'lastname', 'price', 'year')); + + $resultSet = $type->search($query); + $this->assertEquals(1, $resultSet->count()); + } + + public function testSetDefaultOperator() + { + $operator = 'AND'; + $query = new QueryString('test'); + $query->setDefaultOperator($operator); + + $data = $query->toArray(); + + $this->assertEquals($data['query_string']['default_operator'], $operator); + } + + public function testSetDefaultField() + { + $default = 'field1'; + $query = new QueryString('test'); + $query->setDefaultField($default); + + $data = $query->toArray(); + + $this->assertEquals($data['query_string']['default_field'], $default); + } + + public function testSetRewrite() + { + $rewrite = 'scoring_boolean'; + $query = new QueryString('test'); + $query->setRewrite($rewrite); + + $data = $query->toArray(); + + $this->assertEquals($data['query_string']['rewrite'], $rewrite); + } + + /** + * @expectedException \Elastica\Exception\InvalidException + */ + public function testSetQueryInvalid() + { + $query = new QueryString(); + $query->setQuery(array()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/RangeTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/RangeTest.php new file mode 100644 index 00000000..4cd75bc8 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/RangeTest.php @@ -0,0 +1,73 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Document; +use Elastica\Query\Range; +use Elastica\Test\Base as BaseTest; + +class RangeTest extends BaseTest +{ + public function testQuery() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('test'); + + $doc = new Document(1, array('age' => 16, 'height' => 140)); + $type->addDocument($doc); + $doc = new Document(2, array('age' => 21, 'height' => 155)); + $type->addDocument($doc); + $doc = new Document(3, array('age' => 33, 'height' => 160)); + $type->addDocument($doc); + $doc = new Document(4, array('age' => 68, 'height' => 160)); + $type->addDocument($doc); + + $index->optimize(); + $index->refresh(); + + $query = new Range('age', array('from' => 10, 'to' => 20)); + $result = $type->search($query)->count(); + $this->assertEquals(1, $result); + + $query = new Range(); + $query->addField('height', array('gte' => 160)); + + $result = $type->search($query)->count(); + $this->assertEquals(2, $result); + } + + public function testToArray() + { + $range = new Range(); + + $field = array('from' => 20, 'to' => 40); + $range->addField('age', $field); + + $expectedArray = array( + 'range' => array( + 'age' => $field, + ) + ); + + $this->assertEquals($expectedArray, $range->toArray()); + } + + public function testConstruct() + { + $ranges = array('from' => 20, 'to' => 40); + $range = new Range( + 'age', + $ranges + ); + + $expectedArray = array( + 'range' => array( + 'age' => $ranges, + ) + ); + + $this->assertEquals($expectedArray, $range->toArray()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/RescoreTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/RescoreTest.php new file mode 100644 index 00000000..4396ceb4 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/RescoreTest.php @@ -0,0 +1,165 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Rescore\Query as QueryRescore; +use Elastica\Query\Term; +use Elastica\Query\Match; +use Elastica\Query; +use Elastica\Test\Base as BaseTest; + +class RescoreTest extends BaseTest +{ + /** + * @var Index + */ + protected $_index; + + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex("rescore_test"); + $this->_index->refresh(); + } + + public function testToArray() + { + $query = new Query(); + $mainQuery = new Match(); + $mainQuery = $mainQuery->setFieldQuery('test1', 'foo'); + $secQuery = new Term(); + $secQuery = $secQuery->setTerm('test2', 'bar', 2); + $queryRescore = new QueryRescore($secQuery); + $query->setQuery($mainQuery); + $query->setRescore($queryRescore); + $data = $query->toArray(); + + $expected = array( + 'query' => array( + 'match' => array( + 'test1' => array( + 'query' => 'foo', + ), + ), + ), + 'rescore' => array( + 'query' => array( + 'rescore_query' => array( + 'term' => array( + 'test2' => array( + 'value' => 'bar', + 'boost' => 2, + ), + ), + ), + ), + ), + ); + + $this->assertEquals($expected, $data); + } + + public function testSetSize() + { + $query = new Query(); + $mainQuery = new Match(); + $mainQuery = $mainQuery->setFieldQuery('test1', 'foo'); + $secQuery = new Term(); + $secQuery = $secQuery->setTerm('test2', 'bar', 2); + $queryRescore = new QueryRescore($secQuery); + $queryRescore->setWindowSize(50); + $query->setQuery($mainQuery); + $query->setRescore($queryRescore); + $data = $query->toArray(); + + $expected = array( + 'query' => array( + 'match' => array( + 'test1' => array( + 'query' => 'foo', + ), + ), + ), + 'rescore' => array( + 'window_size' => 50, + 'query' => array( + 'rescore_query' => array( + 'term' => array( + 'test2' => array( + 'value' => 'bar', + 'boost' => 2, + ), + ), + ), + ), + ), + ); + + $this->assertEquals($expected, $data); + } + + public function testSetWeights() + { + $query = new Query(); + $mainQuery = new Match(); + $mainQuery = $mainQuery->setFieldQuery('test1', 'foo'); + $secQuery = new Term(); + $secQuery = $secQuery->setTerm('test2', 'bar', 2); + $queryRescore = new QueryRescore($secQuery); + $queryRescore->setWindowSize(50); + $queryRescore->setQueryWeight(.7); + $queryRescore->setRescoreQueryWeight(1.2); + $query->setQuery($mainQuery); + $query->setRescore($queryRescore); + $data = $query->toArray(); + + $expected = array( + 'query' => array( + 'match' => array( + 'test1' => array( + 'query' => 'foo', + ), + ), + ), + 'rescore' => array( + 'window_size' => 50, + 'query' => array( + 'rescore_query' => array( + 'term' => array( + 'test2' => array( + 'value' => 'bar', + 'boost' => 2, + ), + ), + ), + 'query_weight' => 0.7, + 'rescore_query_weight' => 1.2 + ), + ), + ); + + $this->assertEquals($expected, $data); + } + + public function testQuery() + { + $query = new Query(); + $mainQuery = new Match(); + $mainQuery = $mainQuery->setFieldQuery('test1', 'foo'); + $secQuery = new Term(); + $secQuery = $secQuery->setTerm('test2', 'bar', 2); + $queryRescore = new QueryRescore($secQuery); + $queryRescore->setWindowSize(50); + $queryRescore->setQueryWeight(.7); + $queryRescore->setRescoreQueryWeight(1.2); + $query->setQuery($mainQuery); + $query->setRescore($queryRescore); + $data = $query->toArray(); + + $results = $this->_index->search($query); + $response = $results->getResponse(); + + $this->assertEquals(true, $response->isOk()); + $this->assertEquals(0, $results->getTotalHits()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/SimpleQueryStringTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/SimpleQueryStringTest.php new file mode 100644 index 00000000..eff9b8a1 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/SimpleQueryStringTest.php @@ -0,0 +1,73 @@ +<?php + +namespace Elastica\Test\Query; + + +use Elastica\Document; +use Elastica\Index; +use Elastica\Query\SimpleQueryString; +use Elastica\Test\Base; + +class SimpleQueryStringTest extends Base +{ + /** + * @var Index + */ + protected $_index; + + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex("simple_query_string_test"); + $docs = array( + new Document(1, array('make' => 'Gibson', 'model' => 'Les Paul')), + new Document(2, array('make' => 'Gibson', 'model' => 'SG Standard')), + new Document(3, array('make' => 'Gibson', 'model' => 'SG Supreme')), + new Document(4, array('make' => 'Gibson', 'model' => 'SG Faded')), + new Document(5, array('make' => 'Fender', 'model' => 'Stratocaster')) + ); + $this->_index->getType("guitars")->addDocuments($docs); + $this->_index->refresh(); + } + + protected function tearDown() + { + parent::tearDown(); + $this->_index->delete(); + } + + public function testToArray() + { + $string = "this is a test"; + $fields = array('field1', 'field2'); + $query = new SimpleQueryString($string, $fields); + $query->setDefaultOperator(SimpleQueryString::OPERATOR_OR); + $query->setAnalyzer("whitespace"); + + $expected = array( + "simple_query_string" => array( + "query" => $string, + "fields" => $fields, + "analyzer" => "whitespace", + "default_operator" => SimpleQueryString::OPERATOR_OR + ) + ); + + $this->assertEquals($expected, $query->toArray()); + } + + public function testQuery() + { + $query = new SimpleQueryString("gibson +sg +-faded", array("make", "model")); + $results = $this->_index->search($query); + + $this->assertEquals(2, $results->getTotalHits()); + + $query->setFields(array("model")); + $results = $this->_index->search($query); + + // We should not get any hits, since the "make" field was not included in the query. + $this->assertEquals(0, $results->getTotalHits()); + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/SimpleTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/SimpleTest.php new file mode 100644 index 00000000..08a5f55d --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/SimpleTest.php @@ -0,0 +1,17 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Query\Simple; +use Elastica\Test\Base as BaseTest; + +class SimpleTest extends BaseTest +{ + public function testToArray() + { + $testQuery = array('hello' => array('world'), 'name' => 'ruflin'); + $query = new Simple($testQuery); + + $this->assertEquals($testQuery, $query->toArray()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/TermTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/TermTest.php new file mode 100644 index 00000000..887c3849 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/TermTest.php @@ -0,0 +1,26 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Query\Term; +use Elastica\Test\Base as BaseTest; + +class TermTest extends BaseTest +{ + + public function testToArray() + { + $query = new Term(); + $key = 'name'; + $value = 'nicolas'; + $boost = 2; + $query->setTerm($key, $value, $boost); + + $data = $query->toArray(); + + $this->assertInternalType('array', $data['term']); + $this->assertInternalType('array', $data['term'][$key]); + $this->assertEquals($data['term'][$key]['value'], $value); + $this->assertEquals($data['term'][$key]['boost'], $boost); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/TermsTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/TermsTest.php new file mode 100644 index 00000000..184f3ad6 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/TermsTest.php @@ -0,0 +1,62 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Document; +use Elastica\Query\Terms; +use Elastica\Test\Base as BaseTest; + +class TermsTest extends BaseTest +{ + public function testFilteredSearch() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + $index->create(array(), true); + $type = $index->getType('helloworld'); + + $doc = new Document(1, array('name' => 'hello world')); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'nicolas ruflin')); + $type->addDocument($doc); + $doc = new Document(3, array('name' => 'ruflin')); + $type->addDocument($doc); + + $query = new Terms(); + $query->setTerms('name', array('nicolas', 'hello')); + + $index->refresh(); + + $resultSet = $type->search($query); + + $this->assertEquals(2, $resultSet->count()); + + $query->addTerm('ruflin'); + $resultSet = $type->search($query); + + $this->assertEquals(3, $resultSet->count()); + } + + public function testSetMinimum() + { + $key = 'name'; + $terms = array('nicolas', 'ruflin'); + $minimum = 2; + + $query = new Terms($key, $terms); + $query->setMinimumMatch($minimum); + + $data = $query->toArray(); + $this->assertEquals($minimum, $data['terms']['minimum_match']); + } + + /** + * @expectedException \Elastica\Exception\InvalidException + */ + public function testInvalidParams() + { + $query = new Terms(); + + $query->toArray(); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/WildcardTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/WildcardTest.php new file mode 100644 index 00000000..077e6d4f --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Query/WildcardTest.php @@ -0,0 +1,101 @@ +<?php + +namespace Elastica\Test\Query; + +use Elastica\Document; +use Elastica\Query\Wildcard; +use Elastica\Test\Base as BaseTest; +use Elastica\Type\Mapping; + +class WildcardTest extends BaseTest +{ + public function testConstructEmpty() + { + $wildcard = new Wildcard(); + $this->assertEmpty($wildcard->getParams()); + } + + public function testToArray() + { + $key = 'name'; + $value = 'Ru*lin'; + $boost = 2.0; + + $wildcard = new Wildcard($key, $value, $boost); + + $expectedArray = array( + 'wildcard' => array( + $key => array( + 'value' => $value, + 'boost' => $boost + ) + ) + ); + + $this->assertEquals($expectedArray, $wildcard->toArray()); + } + + public function testSearchWithAnalyzer() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + + $indexParams = array( + 'analysis' => array( + 'analyzer' => array( + 'lw' => array( + 'type' => 'custom', + 'tokenizer' => 'keyword', + 'filter' => array('lowercase') + ) + ), + ) + ); + + $index->create($indexParams, true); + $type = $index->getType('test'); + + $mapping = new Mapping($type, array( + 'name' => array('type' => 'string', 'store' => 'no', 'analyzer' => 'lw'), + ) + ); + $type->setMapping($mapping); + + $doc = new Document(1, array('name' => 'Basel-Stadt')); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'New York')); + $type->addDocument($doc); + $doc = new Document(3, array('name' => 'Baden')); + $type->addDocument($doc); + $doc = new Document(4, array('name' => 'Baden Baden')); + $type->addDocument($doc); + $doc = new Document(5, array('name' => 'New Orleans')); + $type->addDocument($doc); + + $index->refresh(); + + $query = new Wildcard(); + $query->setValue('name', 'ba*'); + $resultSet = $index->search($query); + + $this->assertEquals(3, $resultSet->count()); + + $query = new Wildcard(); + $query->setValue('name', 'baden*'); + $resultSet = $index->search($query); + + $this->assertEquals(2, $resultSet->count()); + + $query = new Wildcard(); + $query->setValue('name', 'baden b*'); + $resultSet = $index->search($query); + + $this->assertEquals(1, $resultSet->count()); + + $query = new Wildcard(); + $query->setValue('name', 'baden bas*'); + $resultSet = $index->search($query); + + $this->assertEquals(0, $resultSet->count()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/QueryTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/QueryTest.php new file mode 100644 index 00000000..ece9f4c2 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/QueryTest.php @@ -0,0 +1,194 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Document; +use Elastica\Exception\InvalidException; +use Elastica\Query\Builder; +use Elastica\Query\Term; +use Elastica\Query\Text; +use Elastica\Query; +use Elastica\Facet\Terms; +use Elastica\Test\Base as BaseTest; + +class QueryTest extends BaseTest +{ + public function testStringConversion() + { + $queryString = '{ + "query" : { + "filtered" : { + "filter" : { + "range" : { + "due" : { + "gte" : "2011-07-18 00:00:00", + "lt" : "2011-07-25 00:00:00" + } + } + }, + "query" : { + "text_phrase" : { + "title" : "Call back request" + } + } + } + }, + "sort" : { + "due" : { + "reverse" : true + } + }, + "fields" : [ + "created", "assigned_to" + ] + }'; + + $query = new Builder($queryString); + $queryArray = $query->toArray(); + + $this->assertInternalType('array', $queryArray); + + $this->assertEquals('2011-07-18 00:00:00', $queryArray['query']['filtered']['filter']['range']['due']['gte']); + } + + public function testRawQuery() + { + $textQuery = new Term(array('title' => 'test')); + + $query1 = Query::create($textQuery); + + $query2 = new Query(); + $query2->setRawQuery(array('query' => array('term' => array('title' => 'test')))); + + $this->assertEquals($query1->toArray(), $query2->toArray()); + } + + public function testArrayQuery() + { + $query = array( + 'query' => array( + 'text' => array( + 'title' => 'test' + ) + ) + ); + + $query1 = Query::create($query); + + $query2 = new Query(); + $query2->setRawQuery(array('query' => array('text' => array('title' => 'test')))); + + $this->assertEquals($query1->toArray(), $query2->toArray()); + } + + public function testSetSort() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + + $doc = new Document(1, array('name' => 'hello world')); + $type->addDocument($doc); + $doc = new Document(2, array('firstname' => 'guschti', 'lastname' => 'ruflin')); + $type->addDocument($doc); + $doc = new Document(3, array('firstname' => 'nicolas', 'lastname' => 'ruflin')); + $type->addDocument($doc); + + $queryTerm = new Term(); + $queryTerm->setTerm('lastname', 'ruflin'); + + $index->refresh(); + + $query = Query::create($queryTerm); + + // ASC order + $query->setSort(array(array('firstname' => array('order' => 'asc')))); + $resultSet = $type->search($query); + $this->assertEquals(2, $resultSet->count()); + + $first = $resultSet->current()->getData(); + $second = $resultSet->next()->getData(); + + $this->assertEquals('guschti', $first['firstname']); + $this->assertEquals('nicolas', $second['firstname']); + + // DESC order + $query->setSort(array('firstname' => array('order' => 'desc'))); + $resultSet = $type->search($query); + $this->assertEquals(2, $resultSet->count()); + + $first = $resultSet->current()->getData(); + $second = $resultSet->next()->getData(); + + $this->assertEquals('nicolas', $first['firstname']); + $this->assertEquals('guschti', $second['firstname']); + } + + public function testAddSort() + { + $query = new Query(); + $sortParam = array('firstname' => array('order' => 'asc')); + $query->addSort($sortParam); + + $this->assertEquals($query->getParam('sort'), array($sortParam)); + } + + public function testSetRawQuery() + { + $query = new Query(); + + $params = array('query' => 'test'); + $query->setRawQuery($params); + + $this->assertEquals($params, $query->toArray()); + } + + public function testSetFields() + { + $query = new Query(); + + $params = array('query' => 'test'); + + $query->setFields(array('firstname', 'lastname')); + + $data = $query->toArray(); + + $this->assertContains('firstname', $data['fields']); + $this->assertContains('lastname', $data['fields']); + $this->assertEquals(2, count($data['fields'])); + } + + public function testGetQuery() + { + $query = new Query(); + + try { + $query->getQuery(); + $this->fail('should throw exception because query does not exist'); + } catch (InvalidException $e) { + $this->assertTrue(true); + } + + $termQuery = new Term(); + $termQuery->setTerm('text', 'value'); + $query->setQuery($termQuery); + + $this->assertEquals($termQuery->toArray(), $query->getQuery()); + } + + public function testSetFacets() + { + $query = new Query(); + + $facet = new Terms('text'); + $query->setFacets(array($facet)); + + $data = $query->toArray(); + + $this->assertArrayHasKey('facets', $data); + $this->assertEquals(array('text' => array('terms' => array())), $data['facets']); + + $query->setFacets(array()); + + $this->assertArrayNotHasKey('facets', $query->toArray()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/RequestTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/RequestTest.php new file mode 100644 index 00000000..8896adeb --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/RequestTest.php @@ -0,0 +1,87 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Connection; +use Elastica\Request; +use Elastica\Test\Base as BaseTest; + +class RequestTest extends BaseTest +{ + + public function testConstructor() + { + $path = 'test'; + $method = Request::POST; + $query = array('no' => 'params'); + $data = array('key' => 'value'); + + $request = new Request($path, $method, $data, $query); + + $this->assertEquals($path, $request->getPath()); + $this->assertEquals($method, $request->getMethod()); + $this->assertEquals($query, $request->getQuery()); + $this->assertEquals($data, $request->getData()); + } + + /** + * @expectedException \Elastica\Exception\InvalidException + */ + public function testInvalidConnection() + { + $request = new Request('', Request::GET); + $request->send(); + } + + public function testSend() + { + $connection = new Connection(); + $connection->setHost('localhost'); + $connection->setPort('9200'); + + $request = new Request('_status', Request::GET, array(), array(), $connection); + + $response = $request->send(); + + $this->assertInstanceOf('Elastica\Response', $response); + } + + public function testToString() + { + $path = 'test'; + $method = Request::POST; + $query = array('no' => 'params'); + $data = array('key' => 'value'); + + $connection = new Connection(); + $connection->setHost('localhost'); + $connection->setPort('9200'); + + $request = new Request($path, $method, $data, $query, $connection); + + $data = $request->toArray(); + + $this->assertInternalType('array', $data); + $this->assertArrayHasKey('method', $data); + $this->assertArrayHasKey('path', $data); + $this->assertArrayHasKey('query', $data); + $this->assertArrayHasKey('data', $data); + $this->assertArrayHasKey('connection', $data); + $this->assertEquals($request->getMethod(), $data['method']); + $this->assertEquals($request->getPath(), $data['path']); + $this->assertEquals($request->getQuery(), $data['query']); + $this->assertEquals($request->getData(), $data['data']); + $this->assertInternalType('array', $data['connection']); + $this->assertArrayHasKey('host', $data['connection']); + $this->assertArrayHasKey('port', $data['connection']); + $this->assertEquals($request->getConnection()->getHost(), $data['connection']['host']); + $this->assertEquals($request->getConnection()->getPort(), $data['connection']['port']); + + $string = $request->toString(); + + $this->assertInternalType('string', $string); + + $string = (string) $request; + $this->assertInternalType('string', $string); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/ResponseTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/ResponseTest.php new file mode 100644 index 00000000..1e026eae --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/ResponseTest.php @@ -0,0 +1,94 @@ +<?php + +namespace Elastica\Test; +use Elastica\Document; +use Elastica\Facet\DateHistogram; +use Elastica\Query; +use Elastica\Query\MatchAll; +use Elastica\Request; +use Elastica\Type\Mapping; +use Elastica\Test\Base as BaseTest; + +class ResponseTest extends BaseTest +{ + public function testClassHierarchy() + { + $facet = new DateHistogram('dateHist1'); + $this->assertInstanceOf('Elastica\Facet\Histogram', $facet); + $this->assertInstanceOf('Elastica\Facet\AbstractFacet', $facet); + unset($facet); + } + + public function testResponse() + { + $index = $this->_createIndex(); + $type = $index->getType('helloworld'); + + $mapping = new Mapping($type, array( + 'name' => array('type' => 'string', 'store' => 'no'), + 'dtmPosted' => array('type' => 'date', 'store' => 'no', 'format' => 'yyyy-MM-dd HH:mm:ss') + )); + $type->setMapping($mapping); + + $doc = new Document(1, array('name' => 'nicolas ruflin', 'dtmPosted' => "2011-06-23 21:53:00")); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'raul martinez jr', 'dtmPosted' => "2011-06-23 09:53:00")); + $type->addDocument($doc); + $doc = new Document(3, array('name' => 'rachelle clemente', 'dtmPosted' => "2011-07-08 08:53:00")); + $type->addDocument($doc); + $doc = new Document(4, array('name' => 'elastica search', 'dtmPosted' => "2011-07-08 01:53:00")); + $type->addDocument($doc); + + $query = new Query(); + $query->setQuery(new MatchAll()); + $index->refresh(); + + $resultSet = $type->search($query); + + $engineTime = $resultSet->getResponse()->getEngineTime(); + $shardsStats = $resultSet->getResponse()->getShardsStatistics(); + + $this->assertInternalType('int', $engineTime); + $this->assertTrue(is_array($shardsStats)); + $this->assertArrayHasKey('total', $shardsStats); + $this->assertArrayHasKey('successful', $shardsStats); + } + + public function testIsOk() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + + $doc = new Document(1, array('name' => 'ruflin')); + $response = $type->addDocument($doc); + + $this->assertTrue($response->isOk()); + } + + public function testIsOkMultiple() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + + $docs = array( + new Document(1, array('name' => 'ruflin')), + new Document(2, array('name' => 'ruflin')) + ); + $response = $type->addDocuments($docs); + + $this->assertTrue($response->isOk()); + } + + public function testGetDataEmpty() + { + $index = $this->_createIndex(); + + $response = $index->request( + 'non-existant-type/_mapping', + Request::GET + )->getData(); + + $this->assertEquals(0, count($response)); + } + +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/ResultSetTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/ResultSetTest.php new file mode 100644 index 00000000..2a62111d --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/ResultSetTest.php @@ -0,0 +1,93 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Client; +use Elastica\Document; +use Elastica\Query; +use Elastica\Query\Match; +use Elastica\Result; +use Elastica\Test\Base as BaseTest; + +class ResultSetTest extends BaseTest +{ + public function testGetters() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + + $doc = new Document(1, array('name' => 'elastica search')); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'elastica library')); + $type->addDocument($doc); + $doc = new Document(3, array('name' => 'elastica test')); + $type->addDocument($doc); + $index->refresh(); + + $resultSet = $type->search('elastica search'); + + $this->assertInstanceOf('Elastica\ResultSet', $resultSet); + $this->assertEquals(3, $resultSet->getTotalHits()); + $this->assertGreaterThan(0, $resultSet->getMaxScore()); + $this->assertInternalType('array', $resultSet->getResults()); + $this->assertEquals(3, count($resultSet)); + } + + public function testArrayAccess() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + + $doc = new Document(1, array('name' => 'elastica search')); + $type->addDocument($doc); + $doc = new Document(2, array('name' => 'elastica library')); + $type->addDocument($doc); + $doc = new Document(3, array('name' => 'elastica test')); + $type->addDocument($doc); + $index->refresh(); + + $resultSet = $type->search('elastica search'); + + $this->assertInstanceOf('Elastica\ResultSet', $resultSet); + $this->assertInstanceOf('Elastica\Result', $resultSet[0]); + $this->assertInstanceOf('Elastica\Result', $resultSet[1]); + $this->assertInstanceOf('Elastica\Result', $resultSet[2]); + + $this->assertFalse(isset($resultSet[3])); + } + + /** + * @expectedException \Elastica\Exception\InvalidException + */ + public function testInvalidOffsetCreation() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + + $doc = new Document(1, array('name' => 'elastica search')); + $type->addDocument($doc); + $index->refresh(); + + $resultSet = $type->search('elastica search'); + + $result = new Result(array('_id' => 'fakeresult')); + $resultSet[1] = $result; + } + + /** + * @expectedException \Elastica\Exception\InvalidException + */ + public function testInvalidOffsetGet() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + + $doc = new Document(1, array('name' => 'elastica search')); + $type->addDocument($doc); + $index->refresh(); + + $resultSet = $type->search('elastica search'); + + return $resultSet[3]; + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/ResultTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/ResultTest.php new file mode 100644 index 00000000..54d3ce55 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/ResultTest.php @@ -0,0 +1,121 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Client; +use Elastica\Document; +use Elastica\Result; +use Elastica\Type\Mapping; +use Elastica\Test\Base as BaseTest; + +class ResultTest extends BaseTest +{ + public function testGetters() + { + // Creates a new index 'xodoa' and a type 'user' inside this index + $typeName = 'user'; + + $index = $this->_createIndex(); + $type = $index->getType($typeName); + + // Adds 1 document to the index + $docId = 3; + $doc1 = new Document($docId, array('username' => 'hans')); + $type->addDocument($doc1); + + // Refreshes index + $index->refresh(); + + $resultSet = $type->search('hans'); + + $this->assertEquals(1, $resultSet->count()); + + $result = $resultSet->current(); + + $this->assertInstanceOf('Elastica\Result', $result); + $this->assertEquals($index->getName(), $result->getIndex()); + $this->assertEquals($typeName, $result->getType()); + $this->assertEquals($docId, $result->getId()); + $this->assertGreaterThan(0, $result->getScore()); + $this->assertInternalType('array', $result->getData()); + $this->assertTrue(isset($result->username)); + $this->assertEquals('hans', $result->username); + } + + public function testGetIdNoSource() + { + // Creates a new index 'xodoa' and a type 'user' inside this index + $indexName = 'xodoa'; + $typeName = 'user'; + + $client = $this->_getClient(); + $index = $client->getIndex($indexName); + $index->create(array(), true); + $type = $index->getType($typeName); + + $mapping = new Mapping($type); + $mapping->disableSource(); + $mapping->send(); + + // Adds 1 document to the index + $docId = 3; + $doc1 = new Document($docId, array('username' => 'hans')); + $type->addDocument($doc1); + + // Refreshes index + $index->refresh(); + + $resultSet = $type->search('hans'); + + $this->assertEquals(1, $resultSet->count()); + + $result = $resultSet->current(); + + $this->assertEquals(array(), $result->getSource()); + $this->assertInstanceOf('Elastica\Result', $result); + $this->assertEquals($indexName, $result->getIndex()); + $this->assertEquals($typeName, $result->getType()); + $this->assertEquals($docId, $result->getId()); + $this->assertGreaterThan(0, $result->getScore()); + $this->assertInternalType('array', $result->getData()); + } + + public function testGetTotalTimeReturnsExpectedResults() + { + $typeName = 'user'; + $index = $this->_createIndex(); + $type = $index->getType($typeName); + + // Adds 1 document to the index + $docId = 3; + $doc1 = new Document($docId, array('username' => 'hans')); + $type->addDocument($doc1); + + // Refreshes index + $index->refresh(); + + $resultSet = $type->search('hans'); + + $this->assertNotNull($resultSet->getTotalTime(), 'Get Total Time should never be a null value'); + $this->assertEquals( + 'integer', + getType($resultSet->getTotalTime()), + 'Total Time should be an integer' + ); + } + + public function testHasFields() + { + $data = array('value set'); + + $result = new Result(array()); + $this->assertFalse($result->hasFields()); + + $result = new Result(array('_source' => $data)); + $this->assertFalse($result->hasFields()); + + $result = new Result(array('fields' => $data)); + $this->assertTrue($result->hasFields()); + $this->assertEquals($data, $result->getFields()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/ScanAndScrollTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/ScanAndScrollTest.php new file mode 100644 index 00000000..a64670bb --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/ScanAndScrollTest.php @@ -0,0 +1,115 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Document; +use Elastica\Query; +use Elastica\ResultSet; +use Elastica\ScanAndScroll; +use Elastica\Search; +use Elastica\Test\Base as BaseTest; + +class ScanAndScrollTest extends BaseTest { + + public function testConstruct() { + $scanAndScroll = $this->_prepareScanAndScroll(); + + $this->assertInstanceOf('Elastica\ScanAndScroll', $scanAndScroll); + } + + public function testDefaultProperties() { + $scanAndScroll = $this->_prepareScanAndScroll(); + + $this->assertEquals('1m', $scanAndScroll->expiryTime); + $this->assertEquals(1000, $scanAndScroll->sizePerShard); + } + + public function testQuerySizeOverride() { + $query = new Query(); + $query->setSize(100); + + $index = $this->_createIndex('test_1'); + $index->refresh(); // Waits for the index to be fully created. + $type = $index->getType('scanAndScrollTest'); + + $search = new Search($this->_getClient()); + $search->addIndex($index)->addType($type); + $search->setQuery($query); + + $scanAndScroll = new ScanAndScroll($search); + $scanAndScroll->sizePerShard = 10; + $scanAndScroll->rewind(); + + $this->assertEquals(10, $query->getParam('size')); + } + + public function testSizePerShard() { + $search = $this->_prepareSearch('test_2', 2, 20); + + $scanAndScroll = new ScanAndScroll($search); + $scanAndScroll->sizePerShard = 5; + $scanAndScroll->rewind(); + + $this->assertEquals(10, $scanAndScroll->current()->count()); + } + + public function testScrollId() { + $search = $this->_prepareSearch('test_3', 1, 2); + + $scanAndScroll = new ScanAndScroll($search); + $scanAndScroll->sizePerShard = 1; + + $scanAndScroll->rewind(); + $this->assertEquals( + $scanAndScroll->current()->getResponse()->getScrollId(), + $scanAndScroll->key() + ); + } + + public function testForeach() { + $search = $this->_prepareSearch('test_4', 2, 11); + + $scanAndScroll = new ScanAndScroll($search); + $scanAndScroll->sizePerShard = 5; + + // We expect 2 scrolls: + // 1. with 10 hits, + // 2. with 1 hit + // Note: there is a 3. scroll with 0 hits + + $count = 0; + foreach($scanAndScroll as $resultSet) { + /** @var ResultSet $resultSet */ + $count++; + + switch(true) { + case $count == 1: $this->assertEquals(10, $resultSet->count()); break; + case $count == 2: $this->assertEquals(1, $resultSet->count()); break; + } + } + + $this->assertEquals(2, $count); + } + + private function _prepareScanAndScroll() { + return new ScanAndScroll(new Search($this->_getClient())); + } + + private function _prepareSearch($indexName, $indexShards, $docs) { + $index = $this->_createIndex($indexName, true, $indexShards); + $type = $index->getType('scanAndScrollTest'); + + $insert = array(); + for ($x = 1; $x <= $docs; $x++) { + $insert[] = new Document($x, array('id' => $x, 'key' => 'value')); + } + + $type->addDocuments($insert); + $index->refresh(); + + $search = new Search($this->_getClient()); + $search->addIndex($index)->addType($type); + + return $search; + } +}
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/ScriptFieldsTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/ScriptFieldsTest.php new file mode 100644 index 00000000..a3dd0d51 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/ScriptFieldsTest.php @@ -0,0 +1,95 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Document; +use Elastica\Query; +use Elastica\Script; +use Elastica\ScriptFields; +use Elastica\Test\Base as BaseTest; + +class ScriptFieldsTest extends BaseTest +{ + protected $index; + + public function setUp() + { + $this->index = $this->_createIndex(); + } + + public function tearDown() + { + $this->index->delete(); + } + + public function testNewScriptFields() + { + $script = new Script('1 + 2'); + + // addScript + $scriptFields = new ScriptFields; + $scriptFields->addScript('test', $script); + $this->assertEquals($scriptFields->getParam('test'), $script->toArray()); + + // setScripts + $scriptFields = new ScriptFields; + $scriptFields->setScripts(array( + 'test' => $script + )); + $this->assertEquals($scriptFields->getParam('test'), $script->toArray()); + + // Constructor + $scriptFields = new ScriptFields(array( + 'test' => $script + )); + $this->assertEquals($scriptFields->getParam('test'), $script->toArray()); + } + + public function testSetScriptFields() + { + $query = new Query; + $script = new Script('1 + 2'); + + $scriptFields = new ScriptFields(array( + 'test' => $script + )); + $query->setScriptFields($scriptFields); + $this->assertEquals($query->getParam('script_fields'), $scriptFields->toArray()); + + $query->setScriptFields(array( + 'test' => $script + )); + $this->assertEquals($query->getParam('script_fields'), $scriptFields->toArray()); + } + + /** + * @expectedException \Elastica\Exception\InvalidException + */ + public function testNameException() + { + $script = new Script('1 + 2'); + $scriptFields = new ScriptFields(array($script)); + } + + public function testQuery() + { + $type = $this->index->getType('test'); + + $doc = new Document(1, array('firstname' => 'guschti', 'lastname' => 'ruflin')); + $type->addDocument($doc); + $this->index->refresh(); + + $query = new Query(); + $script = new Script('1 + 2'); + $scriptFields = new ScriptFields(array( + 'test' => $script + )); + $query->setScriptFields($scriptFields); + + $resultSet = $type->search($query); + $first = $resultSet->current()->getData(); + + // 1 + 2 + $this->assertEquals(3, $first['test'][0]); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/ScriptTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/ScriptTest.php new file mode 100644 index 00000000..0a11d118 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/ScriptTest.php @@ -0,0 +1,129 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Script; +use Elastica\Test\Base as BaseTest; + +class ScriptTest extends BaseTest +{ + public function testConstructor() + { + $value = "_score * doc['my_numeric_field'].value"; + $script = new Script($value); + + $expected = array( + 'script' => $value, + ); + $this->assertEquals($value, $script->getScript()); + $this->assertEquals($expected, $script->toArray()); + + $params = array( + 'param1' => 'one', + 'param2' => 10, + ); + + $script = new Script($value, $params); + + $expected = array( + 'script' => $value, + 'params' => $params, + ); + + $this->assertEquals($value, $script->getScript()); + $this->assertEquals($params, $script->getParams()); + $this->assertEquals($expected, $script->toArray()); + + $lang = 'mvel'; + + $script = new Script($value, $params, $lang); + + $expected = array( + 'script' => $value, + 'params' => $params, + 'lang' => $lang, + ); + + $this->assertEquals($value, $script->getScript()); + $this->assertEquals($params, $script->getParams()); + $this->assertEquals($lang, $script->getLang()); + $this->assertEquals($expected, $script->toArray()); + } + + public function testCreateString() + { + $string = '_score * 2.0'; + $script = Script::create($string); + + $this->assertInstanceOf('Elastica\Script', $script); + + $this->assertEquals($string, $script->getScript()); + + $expected = array( + 'script' => $string, + ); + $this->assertEquals($expected, $script->toArray()); + } + + public function testCreateScript() + { + $data = new Script('_score * 2.0'); + + $script = Script::create($data); + + $this->assertInstanceOf('Elastica\Script', $script); + $this->assertSame($data, $script); + } + + public function testCreateArray() + { + $string = '_score * 2.0'; + $lang = 'mvel'; + $params = array( + 'param1' => 'one', + 'param2' => 1, + ); + $array = array( + 'script' => $string, + 'lang' => $lang, + 'params' => $params, + ); + + $script = Script::create($array); + + $this->assertInstanceOf('Elastica\Script', $script); + + $this->assertEquals($string, $script->getScript()); + $this->assertEquals($params, $script->getParams()); + $this->assertEquals($lang, $script->getLang()); + + $this->assertEquals($array, $script->toArray()); + } + + /** + * @dataProvider dataProviderCreateInvalid + * @expectedException \Elastica\Exception\InvalidException + */ + public function testCreateInvalid($data) + { + Script::create($data); + } + + /** + * @return array + */ + public function dataProviderCreateInvalid() + { + return array( + array( + new \stdClass + ), + array( + array('params' => array('param1' => 'one')), + ), + array( + array('script' => '_score * 2.0', 'params' => 'param'), + ) + ); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/SearchTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/SearchTest.php new file mode 100644 index 00000000..e08d2d60 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/SearchTest.php @@ -0,0 +1,500 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Client; +use Elastica\Document; +use Elastica\Index; +use Elastica\Query\Builder; +use Elastica\Query\MatchAll; +use Elastica\Query\QueryString; +use Elastica\Query\FunctionScore; +use Elastica\Query; +use Elastica\Script; +use Elastica\Search; +use Elastica\Test\Base as BaseTest; +use Elastica\Type; + +class SearchTest extends BaseTest +{ + public function testConstruct() + { + $client = $this->_getClient(); + $search = new Search($client); + + $this->assertInstanceOf('Elastica\Search', $search); + $this->assertSame($client, $search->getClient()); + } + + public function testAddIndex() + { + $client = $this->_getClient(); + $search = new Search($client); + + $index1 = $this->_createIndex('test1'); + $index2 = $this->_createIndex('test2'); + + $search->addIndex($index1); + $indices = $search->getIndices(); + + $this->assertEquals(1, count($indices)); + + $search->addIndex($index2); + $indices = $search->getIndices(); + + $this->assertEquals(2, count($indices)); + + $this->assertTrue(in_array($index1->getName(), $indices)); + $this->assertTrue(in_array($index2->getName(), $indices)); + + // Add string + $search->addIndex('test3'); + $indices = $search->getIndices(); + + $this->assertEquals(3, count($indices)); + $this->assertTrue(in_array('test3', $indices)); + } + + public function testAddIndices() + { + $client = $this->_getClient(); + $search = new Search($client); + + $indices = array(); + $indices[] = $client->getIndex('elastica_test1'); + $indices[] = $client->getIndex('elastica_test2'); + + $search->addIndices($indices); + + $this->assertEquals(2, count($search->getIndices())); + } + + public function testAddType() + { + $client = $this->_getClient(); + $search = new Search($client); + + $index = $this->_createIndex(); + + $type1 = $index->getType('type1'); + $type2 = $index->getType('type2'); + + $this->assertEquals(array(), $search->getTypes()); + + $search->addType($type1); + $types = $search->getTypes(); + + $this->assertEquals(1, count($types)); + + $search->addType($type2); + $types = $search->getTypes(); + + $this->assertEquals(2, count($types)); + + $this->assertTrue(in_array($type1->getName(), $types)); + $this->assertTrue(in_array($type2->getName(), $types)); + + // Add string + $search->addType('test3'); + $types = $search->getTypes(); + + $this->assertEquals(3, count($types)); + $this->assertTrue(in_array('test3', $types)); + } + + public function testAddTypes() + { + $client = $this->_getClient(); + $search = new Search($client); + + $index = $this->_createIndex(); + + $types = array(); + $types[] = $index->getType('type1'); + $types[] = $index->getType('type2'); + + $search->addTypes($types); + + $this->assertEquals(2, count($search->getTypes())); + } + + /** + * @expectedException \Elastica\Exception\InvalidException + */ + public function testAddTypeInvalid() + { + $client = $this->_getClient(); + $search = new Search($client); + + $search->addType(new \stdClass()); + } + + /** + * @expectedException \Elastica\Exception\InvalidException + */ + public function testAddIndexInvalid() + { + $client = $this->_getClient(); + $search = new Search($client); + + $search->addIndex(new \stdClass()); + } + + public function testGetPath() + { + $client = $this->_getClient(); + $search1 = new Search($client); + $search2 = new Search($client); + + $index1 = $this->_createIndex('test1'); + $index2 = $this->_createIndex('test2'); + + $type1 = $index1->getType('type1'); + $type2 = $index1->getType('type2'); + + // No index + $this->assertEquals('/_search', $search1->getPath()); + + // Only index + $search1->addIndex($index1); + $this->assertEquals($index1->getName() . '/_search', $search1->getPath()); + + // MUltiple index, no types + $search1->addIndex($index2); + $this->assertEquals($index1->getName() . ',' . $index2->getName() . '/_search', $search1->getPath()); + + // Single type, no index + $search2->addType($type1); + $this->assertEquals('_all/' . $type1->getName() . '/_search', $search2->getPath()); + + // Multiple types + $search2->addType($type2); + $this->assertEquals('_all/' . $type1->getName() . ',' . $type2->getName() . '/_search', $search2->getPath()); + + // Combine index and types + $search2->addIndex($index1); + $this->assertEquals($index1->getName() . '/' . $type1->getName() . ',' . $type2->getName() . '/_search', $search2->getPath()); + } + + public function testSearchRequest() + { + $client = $this->_getClient(); + $search1 = new Search($client); + + $index1 = $this->_createIndex('test1'); + $index2 = $this->_createIndex('test2'); + + $type1 = $index1->getType('hello1'); + + $result = $search1->search(array()); + $this->assertFalse($result->getResponse()->hasError()); + + $search1->addIndex($index1); + + $result = $search1->search(array()); + $this->assertFalse($result->getResponse()->hasError()); + + $search1->addIndex($index2); + + $result = $search1->search(array()); + $this->assertFalse($result->getResponse()->hasError()); + + $search1->addType($type1); + + $result = $search1->search(array()); + $this->assertFalse($result->getResponse()->hasError()); + } + + public function testSearchScrollRequest() + { + $client = $this->_getClient(); + + $index = $this->_createIndex('test'); + $type = $index->getType('scrolltest'); + + $docs = array(); + for ($x = 1; $x <= 10; $x++) { + $docs[] = new Document($x, array('id' => $x, 'testscroll' => 'jbafford')); + } + + $type->addDocuments($docs); + $index->refresh(); + + $search = new Search($client); + $search->addIndex($index)->addType($type); + $result = $search->search(array(), array( + Search::OPTION_SEARCH_TYPE => Search::OPTION_SEARCH_TYPE_SCAN, + Search::OPTION_SCROLL => '5m', + Search::OPTION_SIZE => 5, + )); + $this->assertFalse($result->getResponse()->hasError()); + + $scrollId = $result->getResponse()->getScrollId(); + $this->assertNotEmpty($scrollId); + + //There are 10 items, and we're scrolling with a size of 5 + //So we should get two results of 5 items, and then no items + //We should also have sent the raw scroll_id as the HTTP request body + $search = new Search($client); + $result = $search->search(array(), array( + Search::OPTION_SCROLL => '5m', + Search::OPTION_SCROLL_ID => $scrollId, + )); + $this->assertFalse($result->getResponse()->hasError()); + $this->assertEquals(5, count($result->getResults())); + $this->assertArrayNotHasKey(Search::OPTION_SCROLL_ID, $search->getClient()->getLastRequest()->getQuery()); + $this->assertEquals($scrollId, $search->getClient()->getLastRequest()->getData()); + + $result = $search->search(array(), array( + Search::OPTION_SCROLL => '5m', + Search::OPTION_SCROLL_ID => $scrollId, + )); + $this->assertFalse($result->getResponse()->hasError()); + $this->assertEquals(5, count($result->getResults())); + $this->assertArrayNotHasKey(Search::OPTION_SCROLL_ID, $search->getClient()->getLastRequest()->getQuery()); + $this->assertEquals($scrollId, $search->getClient()->getLastRequest()->getData()); + + $result = $search->search(array(), array( + Search::OPTION_SCROLL => '5m', + Search::OPTION_SCROLL_ID => $scrollId, + )); + $this->assertFalse($result->getResponse()->hasError()); + $this->assertEquals(0, count($result->getResults())); + $this->assertArrayNotHasKey(Search::OPTION_SCROLL_ID, $search->getClient()->getLastRequest()->getQuery()); + $this->assertEquals($scrollId, $search->getClient()->getLastRequest()->getData()); + } + + /** + * Default Limit tests for \Elastica\Search + */ + public function testLimitDefaultSearch() + { + $client = $this->_getClient(); + $search = new Search($client); + + $index = $client->getIndex('zero'); + $index->create(array('index' => array('number_of_shards' => 1, 'number_of_replicas' => 0)), true); + + $docs = array(); + $docs[] = new Document(1, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(2, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(3, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(4, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(5, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(6, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(7, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(8, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(9, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(10, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(11, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $type = $index->getType('zeroType'); + $type->addDocuments($docs); + $index->refresh(); + + $search->addIndex($index)->addType($type); + + // default limit results (default limit is 10) + $resultSet = $search->search('farrelley'); + $this->assertEquals(10, $resultSet->count()); + + // limit = 1 + $resultSet = $search->search('farrelley', 1); + $this->assertEquals(1, $resultSet->count()); + } + + /** + * @expectedException \Elastica\Exception\InvalidException + */ + public function testArrayConfigSearch() + { + $client = $this->_getClient(); + $search = new Search($client); + + $index = $client->getIndex('zero'); + $index->create(array('index' => array('number_of_shards' => 1, 'number_of_replicas' => 0)), true); + + $docs = array(); + for ($i = 0; $i < 11; $i++) { + $docs[] = new Document($i, array('id' => 1, 'email' => 'test@test.com', 'username' => 'test')); + } + + $type = $index->getType('zeroType'); + $type->addDocuments($docs); + $index->refresh(); + + $search->addIndex($index)->addType($type); + //Backward compatibility, integer => limit + // default limit results (default limit is 10) + $resultSet = $search->search('test'); + $this->assertEquals(10, $resultSet->count()); + + // limit = 1 + $resultSet = $search->search('test', 1); + $this->assertEquals(1, $resultSet->count()); + + //Array with limit + $resultSet = $search->search('test', array('limit' => 2)); + $this->assertEquals(2, $resultSet->count()); + + //Array with size + $resultSet = $search->search('test', array('size' => 2)); + $this->assertEquals(2, $resultSet->count()); + + //Array with from + $resultSet = $search->search('test', array('from' => 10)); + $this->assertEquals(10, $resultSet->current()->getId()); + + //Array with routing + $resultSet = $search->search('test', array('routing' => 'r1,r2')); + $this->assertEquals(10, $resultSet->count()); + + //Array with limit and routing + $resultSet = $search->search('test', array('limit' => 5, 'routing' => 'r1,r2')); + $this->assertEquals(5, $resultSet->count()); + + //Search types + $resultSet = $search->search('test', array('limit' => 5, 'search_type' => 'count')); + $this->assertTrue(($resultSet->count() === 0) && $resultSet->getTotalHits() === 11); + + //Timeout - this one is a bit more tricky to test + $script = new Script('Thread.sleep(100); return _score;'); + $query = new FunctionScore(); + $query->addScriptScoreFunction($script); + $resultSet = $search->search($query, array('timeout' => 50)); + $this->assertTrue($resultSet->hasTimedOut()); + + // Throws InvalidException + $resultSet = $search->search('test', array('invalid_option' => 'invalid_option_value')); + } + + public function testSearchWithVersionOption() + { + $index = $this->_createIndex('test1'); + $doc = new Document(1, array('id' => 1, 'email' => 'test@test.com', 'username' => 'ruflin')); + $index->getType('test')->addDocument($doc); + $index->refresh(); + + $search = new Search($index->getClient()); + $search->addIndex($index); + + // Version param should not be inside by default + $results = $search->search(new MatchAll()); + $hit = $results->current(); + $this->assertEquals(array(), $hit->getParam('_version')); + + // Added version param to result + $results = $search->search(new MatchAll(), array('version' => true)); + $hit = $results->current(); + $this->assertEquals(1, $hit->getParam('_version')); + } + + public function testCountRequest() + { + $client = $this->_getClient(); + $search = new Search($client); + + $index = $client->getIndex('zero'); + $index->create(array('index' => array('number_of_shards' => 1, 'number_of_replicas' => 0)), true); + + $docs = array(); + $docs[] = new Document(1, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(2, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(3, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(4, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(5, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(6, array('id' => 1, 'email' => 'test@test.com', 'username' => 'marley')); + $docs[] = new Document(7, array('id' => 1, 'email' => 'test@test.com', 'username' => 'marley')); + $docs[] = new Document(8, array('id' => 1, 'email' => 'test@test.com', 'username' => 'marley')); + $docs[] = new Document(9, array('id' => 1, 'email' => 'test@test.com', 'username' => 'marley')); + $docs[] = new Document(10, array('id' => 1, 'email' => 'test@test.com', 'username' => 'marley')); + $docs[] = new Document(11, array('id' => 1, 'email' => 'test@test.com', 'username' => 'marley')); + + $type = $index->getType('zeroType'); + $type->addDocuments($docs); + $index->refresh(); + + $search->addIndex($index)->addType($type); + + $count = $search->count('farrelley'); + $this->assertEquals(5, $count); + + $count = $search->count('marley'); + $this->assertEquals(6, $count); + + $count = $search->count(); + $this->assertEquals(6, $count, 'Uses previous query set'); + + $count = $search->count(new MatchAll()); + $this->assertEquals(11, $count); + + $count = $search->count('bunny'); + $this->assertEquals(0, $count); + } + + public function testEmptySearch() + { + $client = $this->_getClient(); + $search = new Search($client); + + $index = $client->getIndex('zero'); + $index->create(array('index' => array('number_of_shards' => 1, 'number_of_replicas' => 0)), true); + $docs = array(); + $docs[] = new Document(1, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(2, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(3, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(4, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(5, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(6, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(7, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(8, array('id' => 1, 'email' => 'test@test.com', 'username' => 'bunny')); + $docs[] = new Document(9, array('id' => 1, 'email' => 'test@test.com', 'username' => 'bunny')); + $docs[] = new Document(10, array('id' => 1, 'email' => 'test@test.com', 'username' => 'bunny')); + $docs[] = new Document(11, array('id' => 1, 'email' => 'test@test.com', 'username' => 'bunny')); + $type = $index->getType('zeroType'); + $type->addDocuments($docs); + $index->refresh(); + + $search->addIndex($index)->addType($type); + $resultSet = $search->search(); + $this->assertInstanceOf('Elastica\ResultSet', $resultSet); + $this->assertCount(10, $resultSet); + $this->assertEquals(11, $resultSet->getTotalHits()); + + $query = new QueryString('bunny'); + $search->setQuery($query); + + $resultSet = $search->search(); + + $this->assertCount(4, $resultSet); + $this->assertEquals(4, $resultSet->getTotalHits()); + $source = $resultSet->current()->getSource(); + $this->assertEquals('bunny', $source['username']); + } + + public function testCount() { + $index = $this->_createIndex('eeee'); + $search = new Search($index->getClient()); + $type = $index->getType('test'); + + $doc = new Document(1, array('id' => 1, 'username' => 'ruflin')); + + $type->addDocument($doc); + $index->refresh(); + + $search->addIndex($index); + $search->addType($type); + + $result1 = $search->count(new \Elastica\Query\MatchAll()); + $this->assertEquals(1, $result1); + + + $result2 = $search->count(new \Elastica\Query\MatchAll(), true); + $this->assertInstanceOf('\Elastica\ResultSet', $result2); + $this->assertEquals(1, $result2->getTotalHits()); + } + + public function testScanAndScroll() { + $search = new Search($this->_getClient()); + $this->assertInstanceOf('Elastica\ScanAndScroll', $search->scanAndScroll()); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/SnapshotTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/SnapshotTest.php new file mode 100644 index 00000000..3ac5bfe2 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/SnapshotTest.php @@ -0,0 +1,112 @@ +<?php + +namespace Elastica\Test; + + +use Elastica\Document; +use Elastica\Index; +use Elastica\Snapshot; + +class SnapshotTest extends Base +{ + /** + * @var Snapshot + */ + protected $_snapshot; + + /** + * @var Index + */ + protected $_index; + + /** + * @var Document[] + */ + protected $_docs; + + protected function setUp() + { + parent::setUp(); + $this->_snapshot = new Snapshot($this->_getClient()); + + $this->_index = $this->_createIndex("test_snapshot"); + $this->_docs = array( + new Document("1", array("city" => "San Diego")), + new Document("2", array("city" => "San Luis Obispo")), + new Document("3", array("city" => "San Francisco")), + ); + $this->_index->getType("test")->addDocuments($this->_docs); + $this->_index->refresh(); + } + + protected function tearDown() + { + parent::tearDown(); + $this->_index->delete(); + } + + public function testRegisterRepository() + { + $name = "test_register"; + $location = "/tmp/test_register"; + + $response = $this->_snapshot->registerRepository($name, "fs", array("location" => $location)); + $this->assertTrue($response->isOk()); + + $response = $this->_snapshot->getRepository($name); + $this->assertEquals($location, $response["settings"]["location"]); + + // attempt to retrieve a repository which does not exist + $this->setExpectedException('Elastica\Exception\NotFoundException'); + $this->_snapshot->getRepository("foobar"); + } + + public function testSnapshotAndRestore() + { + $repositoryName = "test_repository"; + $location = "/tmp/{$repositoryName}"; + + // register the repository + $response = $this->_snapshot->registerRepository($repositoryName, "fs", array("location" => $location)); + $this->assertTrue($response->isOk()); + + // create a snapshot of our test index + $snapshotName = "test_snapshot_1"; + $response = $this->_snapshot->createSnapshot($repositoryName, $snapshotName, array("indices" => $this->_index->getName()), true); + + // ensure that the snapshot was created properly + $this->assertTrue($response->isOk()); + $this->assertArrayHasKey("snapshot", $response->getData()); + $data = $response->getData(); + $this->assertContains($this->_index->getName(), $data["snapshot"]["indices"]); + $this->assertEquals(1, sizeof($data["snapshot"]["indices"])); // only the specified index should be present + $this->assertEquals($snapshotName, $data["snapshot"]["snapshot"]); + + // retrieve data regarding the snapshot + $response = $this->_snapshot->getSnapshot($repositoryName, $snapshotName); + $this->assertContains($this->_index->getName(), $response["indices"]); + + // delete our test index + $this->_index->delete(); + + // restore the index from our snapshot + $response = $this->_snapshot->restoreSnapshot($repositoryName, $snapshotName, array(), true); + $this->assertTrue($response->isOk()); + + $this->_index->refresh(); + $this->_index->optimize(); + + // ensure that the index has been restored + $count = $this->_index->getType("test")->count(); + $this->assertEquals(sizeof($this->_docs), $count); + + // delete the snapshot + $response = $this->_snapshot->deleteSnapshot($repositoryName, $snapshotName); + $this->assertTrue($response->isOk()); + + // ensure that the snapshot has been deleted + $this->setExpectedException('Elastica\Exception\NotFoundException'); + $this->_snapshot->getSnapshot($repositoryName, $snapshotName); + } +} +
\ No newline at end of file diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/StatusTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/StatusTest.php new file mode 100644 index 00000000..14d7950a --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/StatusTest.php @@ -0,0 +1,116 @@ +<?php + +namespace Elastica\Test; +use Elastica\Client; +use Elastica\Exception\ResponseException; +use Elastica\Status; +use Elastica\Test\Base as BaseTest; + +class StatusTest extends BaseTest +{ + public function testGetResponse() + { + $index = $this->_createIndex(); + $status = new Status($index->getClient()); + $this->assertInstanceOf('Elastica\Response', $status->getResponse()); + } + + public function testGetIndexStatuses() + { + $index = $this->_createIndex(); + + $status = new Status($index->getClient()); + $statuses = $status->getIndexStatuses(); + + $this->assertInternalType('array', $statuses); + + foreach ($statuses as $indexStatus) { + $this->assertInstanceOf('Elastica\Index\Status', $indexStatus); + } + } + + public function testGetIndexNames() + { + $indexName = 'test'; + $client = $this->_getClient(); + $index = $client->getIndex($indexName); + $index->create(array(), true); + $index = $this->_createIndex(); + $index->refresh(); + $index->optimize(); + + $status = new Status($index->getClient()); + $names = $status->getIndexNames(); + + $this->assertInternalType('array', $names); + $this->assertContains($index->getName(), $names); + + foreach ($names as $name) { + $this->assertInternalType('string', $name); + } + } + + public function testIndexExists() + { + $indexName = 'elastica_test'; + $aliasName = 'elastica_test-alias'; + + $client = $this->_getClient(); + $index = $client->getIndex($indexName); + + try { + // Make sure index is deleted first + $index->delete(); + } catch (ResponseException $e) { + } + + $status = new Status($client); + $this->assertFalse($status->indexExists($indexName)); + $index->create(); + + $status->refresh(); + $this->assertTrue($status->indexExists($indexName)); + } + + public function testAliasExists() + { + $indexName = 'test'; + $aliasName = 'elastica_test-alias'; + + $index1 = $this->_createIndex(); + + $status = new Status($index1->getClient()); + + foreach ($status->getIndicesWithAlias($aliasName) as $tmpIndex) { + $tmpIndex->removeAlias($aliasName); + } + + $this->assertFalse($status->aliasExists($aliasName)); + + $index1->addAlias($aliasName); + $status->refresh(); + $this->assertTrue($status->aliasExists($aliasName)); + + $indicesWithAlias = $status->getIndicesWithAlias($aliasName); + $this->assertEquals(array("elastica_$indexName"), array_map( + function($index) { + return $index->getName(); + }, $indicesWithAlias)); + } + + public function testServerStatus() + { + $client = $this->_getClient(); + $status = $client->getStatus(); + $serverStatus = $status->getServerStatus(); + + $this->assertTrue(!empty($serverStatus) ); + $this->assertTrue('array' == gettype($serverStatus)); + $this->assertArrayHasKey('status', $serverStatus); + $this->assertTrue($serverStatus['status'] == 200); + $this->assertArrayHasKey('version', $serverStatus); + + $versionInfo = $serverStatus['version']; + $this->assertArrayHasKey('number', $versionInfo); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Suggest/PhraseTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Suggest/PhraseTest.php new file mode 100644 index 00000000..eda08ba0 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Suggest/PhraseTest.php @@ -0,0 +1,85 @@ +<?php + +namespace Elastica\Test\Suggest; + +use Elastica\Suggest; +use Elastica\Suggest\CandidateGenerator\DirectGenerator; +use Elastica\Suggest\Phrase; +use Elastica\Test\Base as BaseTest; +use Elastica\Query; +use Elastica\Document; +use Elastica\Index; + +class PhraseTest extends BaseTest +{ + const TEST_TYPE = 'testSuggestType'; + + /** + * @var Index + */ + protected $_index; + + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex('test_suggest_phrase'); + $docs = array(); + $docs[] = new Document(1, array('text' => 'Github is pretty cool')); + $docs[] = new Document(2, array('text' => 'Elasticsearch is bonsai cool')); + $docs[] = new Document(3, array('text' => 'This is a test phrase')); + $docs[] = new Document(4, array('text' => 'Another sentence for testing')); + $docs[] = new Document(5, array('text' => 'Some more words here')); + $type = $this->_index->getType(self::TEST_TYPE); + $type->addDocuments($docs); + $this->_index->refresh(); + } + + protected function tearDown() + { + $this->_index->delete(); + } + + public function testToArray() + { + $suggest = new Suggest(); + $phraseSuggest = new Phrase('suggest1', 'text'); + $phraseSuggest->setText('elasticsearch is bansai coor'); + $phraseSuggest->setAnalyzer('simple'); + $suggest->addSuggestion($phraseSuggest); + $suggest->setGlobalText('global!'); + + $expected = array( + 'suggest' => array( + 'text' => 'global!', + 'suggest1' => array( + 'text' => 'elasticsearch is bansai coor', + 'phrase' => array( + 'field' => 'text', + 'analyzer' => 'simple' + ) + ) + ) + ); + + $this->assertEquals($expected, $suggest->toArray()); + } + + public function testPhraseSuggest() + { + $suggest = new Suggest(); + $phraseSuggest = new Phrase('suggest1', 'text'); + $phraseSuggest->setText("elasticsearch is bansai coor"); + $phraseSuggest->setAnalyzer("simple")->setHighlight("<suggest>", "</suggest>")->setStupidBackoffSmoothing(0.4); + $phraseSuggest->addCandidateGenerator(new DirectGenerator("text")); + $suggest->addSuggestion($phraseSuggest); + + $result = $this->_index->search($suggest); + $suggests = $result->getSuggests(); + + // 3 suggestions should be returned: One in which both misspellings are corrected, and two in which only one misspelling is corrected. + $this->assertEquals(3, sizeof($suggests['suggest1'][0]['options'])); + + $this->assertEquals("elasticsearch is <suggest>bonsai cool</suggest>", $suggests['suggest1'][0]['options'][0]['highlighted']); + $this->assertEquals("elasticsearch is bonsai cool", $suggests['suggest1'][0]['options'][0]['text']); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Suggest/TermTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Suggest/TermTest.php new file mode 100644 index 00000000..7765f1bb --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Suggest/TermTest.php @@ -0,0 +1,104 @@ +<?php + +namespace Elastica\Test\Suggest; + +use Elastica\Suggest; +use Elastica\Suggest\Term; +use Elastica\Test\Base as BaseTest; +use Elastica\Query; +use Elastica\Document; +use Elastica\Index; + +class TermTest extends BaseTest +{ + const TEST_TYPE = 'testSuggestType'; + + /** + * @var Index + */ + protected $_index; + + protected function setUp() + { + parent::setUp(); + $this->_index = $this->_createIndex('test_suggest'); + $docs = array(); + $docs[] = new Document(1, array('id' => 1, 'text' => 'GitHub')); + $docs[] = new Document(2, array('id' => 1, 'text' => 'Elastic')); + $docs[] = new Document(3, array('id' => 1, 'text' => 'Search')); + $docs[] = new Document(4, array('id' => 1, 'text' => 'Food')); + $docs[] = new Document(5, array('id' => 1, 'text' => 'Flood')); + $docs[] = new Document(6, array('id' => 1, 'text' => 'Folks')); + $type = $this->_index->getType(self::TEST_TYPE); + $type->addDocuments($docs); + $this->_index->refresh(); + } + + protected function tearDown() + { + $this->_index->delete(); + } + + public function testToArray() + { + $suggest = new Suggest(); + $suggest1 = new Term('suggest1', '_all'); + $suggest->addSuggestion($suggest1->setText('Foor')); + $suggest2 = new Term('suggest2', '_all'); + $suggest->addSuggestion($suggest2->setText('Girhub')); + + $expected = array( + 'suggest' => array( + 'suggest1' => array( + 'term' => array( + 'field' => '_all' + ), + 'text' => 'Foor' + ), + 'suggest2' => array( + 'term' => array( + 'field' => '_all' + ), + 'text' => 'Girhub' + ) + ) + ); + + $this->assertEquals($expected, $suggest->toArray()); + } + + public function testSuggestResults() + { + $suggest = new Suggest(); + $suggest1 = new Term('suggest1', '_all'); + $suggest->addSuggestion($suggest1->setText('Foor seach')); + $suggest2 = new Term('suggest2', '_all'); + $suggest->addSuggestion($suggest2->setText('Girhub')); + + $result = $this->_index->search($suggest); + + $this->assertEquals(2, $result->countSuggests()); + + $suggests = $result->getSuggests(); + + // Ensure that two suggestion results are returned for suggest1 + $this->assertEquals(2, sizeof($suggests['suggest1'])); + + $this->assertEquals('github', $suggests['suggest2'][0]['options'][0]['text']); + $this->assertEquals('food', $suggests['suggest1'][0]['options'][0]['text']); + } + + public function testSuggestNoResults() + { + $termSuggest = new Term('suggest1', '_all'); + $termSuggest->setText('Foobar')->setSize(4); + + $result = $this->_index->search($termSuggest); + + $this->assertEquals(1, $result->countSuggests()); + + // Assert that no suggestions were returned + $suggests = $result->getSuggests(); + $this->assertEquals(0, sizeof($suggests['suggest1'][0]['options'])); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/AbstractTransportTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/AbstractTransportTest.php new file mode 100644 index 00000000..4f1c7114 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/AbstractTransportTest.php @@ -0,0 +1,77 @@ +<?php + +namespace Elastica\Test\Transport; + +use Elastica\Transport\AbstractTransport; +use Elastica\Transport\Http; +use Elastica\Connection; +use Elastica\Exception\InvalidException; + +class AbstractTransportTest extends \PHPUnit_Framework_TestCase +{ + /** + * Return transport configuration and the expected HTTP method + * + * @return array[] + */ + public function getValidDefinitions() + { + $connection = new Connection(); + + return array( + array('Http'), + array(array('type' => 'Http')), + array(array('type' => new Http())), + array(new Http()), + ); + } + + /** + * @dataProvider getValidDefinitions + */ + public function testCanCreateTransportInstances($transport) + { + $connection = new Connection(); + $params = array(); + $transport = AbstractTransport::create($transport, $connection, $params); + $this->assertInstanceOf('Elastica\Transport\AbstractTransport', $transport); + $this->assertSame($connection, $transport->getConnection()); + } + + public function getInvalidDefinitions() + { + return array( + array(array('transport' => 'Http')), + array('InvalidTransport'), + ); + } + + /** + * @dataProvider getInvalidDefinitions + * @expectedException Elastica\Exception\InvalidException + * @expectedExceptionMessage Invalid transport + */ + public function testThrowsExecptionOnInvalidTransportDefinition($transport) + { + AbstractTransport::create($transport, new Connection()); + } + + public function testCanInjectParamsWhenUsingArray() + { + $connection = new Connection(); + $params = array( + 'param1' => 'some value', + 'param3' => 'value3', + ); + + $transport = AbstractTransport::create(array( + 'type' => 'Http', + 'param1' => 'value1', + 'param2' => 'value2', + ), $connection, $params); + + $this->assertSame('value1', $transport->getParam('param1')); + $this->assertSame('value2', $transport->getParam('param2')); + $this->assertSame('value3', $transport->getParam('param3')); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/GuzzleTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/GuzzleTest.php new file mode 100644 index 00000000..b2e385bb --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/GuzzleTest.php @@ -0,0 +1,163 @@ +<?php + +namespace Elastica\Test\Transport; + +use Elastica\Client; +use Elastica\Document; +use Elastica\Query; +use Elastica\ResultSet; +use Elastica\Test\Base as BaseTest; +use Elastica\Exception\ResponseException; + +class GuzzleTest extends BaseTest +{ + public static function setUpBeforeClass() + { + if (!class_exists('GuzzleHttp\\Client')) { + self::markTestSkipped('guzzlehttp/guzzle package should be installed to run guzzle transport tests'); + } + } + + public function setUp() + { + if (defined('DEBUG') && !DEBUG) { + $this->markTestSkipped('The DEBUG constant must be set to true for this test to run'); + } + + if (!defined('DEBUG')) { + define('DEBUG', true); + } + } + + /** + * Return transport configuration and the expected HTTP method + * + * @return array[] + */ + public function getConfig() + { + return array( + array( + array('transport' => 'Guzzle'), + 'GET' + ), + array( + array('transport' => array('type' => 'Guzzle', 'postWithRequestBody' => false)), + 'GET' + ), + array( + array('transport' => array('type' => 'Guzzle', 'postWithRequestBody' => true)), + 'POST' + ), + ); + } + + /** + * @dataProvider getConfig + */ + public function testDynamicHttpMethodBasedOnConfigParameter(array $config, $httpMethod) + { + $client = new Client($config); + + $index = $client->getIndex('dynamic_http_method_test'); + $index->create(array(), true); + $type = $index->getType('test'); + $type->addDocument(new Document(1, array('test' => 'test'))); + $index->refresh(); + $resultSet = $index->search('test'); + $info = $resultSet->getResponse()->getTransferInfo(); + $this->assertStringStartsWith($httpMethod, $info['request_header']); + } + + /** + * @dataProvider getConfig + */ + public function testDynamicHttpMethodOnlyAffectsRequestsWithBody(array $config, $httpMethod) + { + $client = new Client($config); + + $status = $client->getStatus(); + $info = $status->getResponse()->getTransferInfo(); + $this->assertStringStartsWith('GET', $info['request_header']); + } + + public function testWithEnvironmentalProxy() + { + putenv('http_proxy=http://127.0.0.1:12345/'); + + $client = new \Elastica\Client(array('transport' => 'Guzzle')); + $transferInfo = $client->request('/_nodes')->getTransferInfo(); + $this->assertEquals(200, $transferInfo['http_code']); + + $client->getConnection()->setProxy(null); // will not change anything + $transferInfo = $client->request('/_nodes')->getTransferInfo(); + $this->assertEquals(200, $transferInfo['http_code']); + + putenv('http_proxy='); + } + + public function testWithEnabledEnvironmentalProxy() + { + putenv('http_proxy=http://127.0.0.1:12346/'); + + $client = new \Elastica\Client(array('transport' => 'Guzzle')); + + $transferInfo = $client->request('/_nodes')->getTransferInfo(); + $this->assertEquals(403, $transferInfo['http_code']); + + $client = new \Elastica\Client(); + $client->getConnection()->setProxy(''); + $transferInfo = $client->request('/_nodes')->getTransferInfo(); + $this->assertEquals(200, $transferInfo['http_code']); + + putenv('http_proxy='); + } + + public function testWithProxy() + { + $client = new \Elastica\Client(array('transport' => 'Guzzle')); + $client->getConnection()->setProxy('http://127.0.0.1:12345'); + + $transferInfo = $client->request('/_nodes')->getTransferInfo(); + $this->assertEquals(200, $transferInfo['http_code']); + } + + public function testWithoutProxy() + { + $client = new \Elastica\Client(array('transport' => 'Guzzle')); + $client->getConnection()->setProxy(''); + + $transferInfo = $client->request('/_nodes')->getTransferInfo(); + $this->assertEquals(200, $transferInfo['http_code']); + } + + public function testBodyReuse() + { + $client = new Client(array('transport' => 'Guzzle')); + + $index = $client->getIndex('elastica_body_reuse_test'); + + $index->create(array(), true); + + $type = $index->getType('test'); + $type->addDocument(new Document(1, array('test' => 'test'))); + + $index->refresh(); + + $resultSet = $index->search(array( + 'query' => array( + 'query_string' => array( + 'query' => 'pew pew pew', + ), + ), + )); + + $this->assertEquals(0, $resultSet->getTotalHits()); + + $response = $index->request('/_search', 'POST'); + $resultSet = new ResultSet($response, Query::create(array())); + + $this->assertEquals(1, $resultSet->getTotalHits()); + } + +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/HttpTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/HttpTest.php new file mode 100644 index 00000000..88c93bea --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/HttpTest.php @@ -0,0 +1,227 @@ +<?php + +namespace Elastica\Test\Transport; + +use Elastica\Client; +use Elastica\Document; +use Elastica\Query; +use Elastica\ResultSet; +use Elastica\Test\Base as BaseTest; +use Elastica\Exception\ResponseException; + +class HttpTest extends BaseTest +{ + public function setUp() + { + if (defined('DEBUG') && !DEBUG) { + $this->markTestSkipped('The DEBUG constant must be set to true for this test to run'); + } + + if (!defined('DEBUG')) { + define('DEBUG', true); + } + } + + /** + * Return transport configuration and the expected HTTP method + * + * @return array[] + */ + public function getConfig() + { + return array( + array( + array('transport' => 'Http'), + 'GET' + ), + array( + array('transport' => array('type' => 'Http', 'postWithRequestBody' => false)), + 'GET' + ), + array( + array('transport' => array('type' => 'Http', 'postWithRequestBody' => true)), + 'POST' + ), + ); + } + + /** + * @dataProvider getConfig + */ + public function testDynamicHttpMethodBasedOnConfigParameter(array $config, $httpMethod) + { + $client = new Client($config); + + $index = $client->getIndex('dynamic_http_method_test'); + + $index->create(array(), true); + + $type = $index->getType('test'); + $type->addDocument(new Document(1, array('test' => 'test'))); + + $index->refresh(); + + $resultSet = $index->search('test'); + + $info = $resultSet->getResponse()->getTransferInfo(); + $this->assertStringStartsWith($httpMethod, $info['request_header']); + } + + /** + * @dataProvider getConfig + */ + public function testDynamicHttpMethodOnlyAffectsRequestsWithBody(array $config, $httpMethod) + { + $client = new Client($config); + + $status = $client->getStatus(); + $info = $status->getResponse()->getTransferInfo(); + $this->assertStringStartsWith('GET', $info['request_header']); + } + + public function testCurlNobodyOptionIsResetAfterHeadRequest() + { + $client = new \Elastica\Client(); + $index = $client->getIndex('curl_test'); + $type = $index->getType('item'); + + // Force HEAD request to set CURLOPT_NOBODY = true + $index->exists(); + + $id = 1; + $data = array('id' => $id, 'name' => 'Item 1'); + $doc = new \Elastica\Document($id, $data); + + $type->addDocument($doc); + + $index->refresh(); + + $doc = $type->getDocument($id); + + // Document should be retrieved correctly + $this->assertSame($data, $doc->getData()); + $this->assertEquals($id, $doc->getId()); + } + + public function testUnicodeData() + { + $client = new \Elastica\Client(); + $index = $client->getIndex('curl_test'); + $type = $index->getType('item'); + + // Force HEAD request to set CURLOPT_NOBODY = true + $index->exists(); + + $id = 22; + $data = array('id' => $id, 'name' => ' + Сегодня, я вижу, особенно грустен твой взгляд, / + И руки особенно тонки, колени обняв. / + Послушай: далеко, далеко, на озере Чад / + Изысканный бродит жираф.'); + + $doc = new \Elastica\Document($id, $data); + + $type->addDocument($doc); + + $index->refresh(); + + $doc = $type->getDocument($id); + + // Document should be retrieved correctly + $this->assertSame($data, $doc->getData()); + $this->assertEquals($id, $doc->getId()); + } + + public function testWithEnvironmentalProxy() + { + putenv('http_proxy=http://127.0.0.1:12345/'); + + $client = new \Elastica\Client(); + $transferInfo = $client->request('/_nodes')->getTransferInfo(); + $this->assertEquals(200, $transferInfo['http_code']); + + $client->getConnection()->setProxy(null); // will not change anything + $transferInfo = $client->request('/_nodes')->getTransferInfo(); + $this->assertEquals(200, $transferInfo['http_code']); + + putenv('http_proxy='); + } + + public function testWithEnabledEnvironmentalProxy() + { + putenv('http_proxy=http://127.0.0.1:12346/'); + + $client = new \Elastica\Client(); + + $transferInfo = $client->request('/_nodes')->getTransferInfo(); + $this->assertEquals(403, $transferInfo['http_code']); + + $client = new \Elastica\Client(); + $client->getConnection()->setProxy(''); + $transferInfo = $client->request('/_nodes')->getTransferInfo(); + $this->assertEquals(200, $transferInfo['http_code']); + + putenv('http_proxy='); + } + + public function testWithProxy() + { + $client = new \Elastica\Client(); + $client->getConnection()->setProxy('http://127.0.0.1:12345'); + + $transferInfo = $client->request('/_nodes')->getTransferInfo(); + $this->assertEquals(200, $transferInfo['http_code']); + } + + public function testWithoutProxy() + { + $client = new \Elastica\Client(); + $client->getConnection()->setProxy(''); + + $transferInfo = $client->request('/_nodes')->getTransferInfo(); + $this->assertEquals(200, $transferInfo['http_code']); + } + + public function testBodyReuse() + { + $client = new Client(); + + $index = $client->getIndex('elastica_body_reuse_test'); + + $index->create(array(), true); + + $type = $index->getType('test'); + $type->addDocument(new Document(1, array('test' => 'test'))); + + $index->refresh(); + + $resultSet = $index->search(array( + 'query' => array( + 'query_string' => array( + 'query' => 'pew pew pew', + ), + ), + )); + + $this->assertEquals(0, $resultSet->getTotalHits()); + + $response = $index->request('/_search', 'POST'); + $resultSet = new ResultSet($response, Query::create(array())); + + $this->assertEquals(1, $resultSet->getTotalHits()); + } + + public function testPostWith0Body() + { + $client = new Client(); + + $index = $client->getIndex('elastica_0_body'); + $index->create(array(), true); + $index->refresh(); + + $tokens = $index->analyze('0'); + + $this->assertNotEmpty($tokens); + } + +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/MemcacheTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/MemcacheTest.php new file mode 100644 index 00000000..17d46d88 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/MemcacheTest.php @@ -0,0 +1,51 @@ +<?php + +namespace Elastica\Test\Transport; + +use Elastica\Client; +use Elastica\Document; +use Elastica\Test\Base as BaseTest; + +class MemcacheTest extends BaseTest +{ + public function setUp() + { + if (!extension_loaded('Memcache')) { + $this->markTestSkipped('pecl/memcache must be installed to run this test case'); + } + } + + public function testExample() + { + // Creates a new index 'xodoa' and a type 'user' inside this index + $host = 'localhost'; + $port = 11211; + $client = new Client(array('host' => $host, 'port' => $port, 'transport' => 'Memcache')); + + $index = $client->getIndex('elastica_test1'); + $index->create(array(), true); + + $type = $index->getType('user'); + + // Adds 1 document to the index + $doc1 = new Document(1, + array('username' => 'hans', 'test' => array('2', '3', '5')) + ); + $type->addDocument($doc1); + + // Adds a list of documents with _bulk upload to the index + $docs = array(); + $docs[] = new Document(2, + array('username' => 'john', 'test' => array('1', '3', '6')) + ); + $docs[] = new Document(3, + array('username' => 'rolf', 'test' => array('2', '3', '7')) + ); + $type->addDocuments($docs); + + // Refresh index + $index->refresh(); + $this->markTestIncomplete('Memcache implementation is not finished yet'); + $resultSet = $type->search('rolf'); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/NullTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/NullTest.php new file mode 100644 index 00000000..c07f5da1 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/NullTest.php @@ -0,0 +1,59 @@ +<?php + +namespace Elastica\Test\Transport; + +use Elastica\Client; +use Elastica\Connection; +use Elastica\Query; +use Elastica\Test\Base as BaseTest; + +/** + * Elastica Null Transport Test + * + * @package Elastica + * @author James Boehmer <james.boehmer@jamesboehmer.com> + */ +class NullTest extends BaseTest +{ + + public function testEmptyResult() + { + // Creates a client with any destination, and verify it returns a response object when executed + $client = $this->_getClient(); + $connection = new Connection(array('transport' => 'Null')); + $client->setConnections(array($connection)); + + $index = $client->getIndex('elasticaNullTransportTest1'); + + $resultSet = $index->search(new Query()); + $this->assertNotNull($resultSet); + + $response = $resultSet->getResponse(); + $this->assertNotNull($response); + + // Validate most of the expected fields in the response data. Consumers of the response + // object have a reasonable expectation of finding "hits", "took", etc + $responseData = $response->getData(); + $this->assertContains("took", $responseData); + $this->assertEquals(0, $responseData["took"]); + $this->assertContains("_shards", $responseData); + $this->assertContains("hits", $responseData); + $this->assertContains("total", $responseData["hits"]); + $this->assertEquals(0, $responseData["hits"]["total"]); + $this->assertContains("params", $responseData); + + $took = $response->getEngineTime(); + $this->assertEquals(0, $took); + + $errorString = $response->getError(); + $this->assertEmpty($errorString); + + $shards = $response->getShardsStatistics(); + $this->assertContains("total", $shards); + $this->assertEquals(0, $shards["total"]); + $this->assertContains("successful", $shards); + $this->assertEquals(0, $shards["successful"]); + $this->assertContains("failed", $shards); + $this->assertEquals(0, $shards["failed"]); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/ThriftTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/ThriftTest.php new file mode 100644 index 00000000..f1698ff6 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/ThriftTest.php @@ -0,0 +1,132 @@ +<?php + +namespace Elastica\Test\Transport; + +use Elastica\Client; +use Elastica\Connection; +use Elastica\Document; +use Elastica\Index; +use Elastica\Query; +use Elastica\Test\Base as BaseTest; + +class ThriftTest extends BaseTest +{ + public static function setUpBeforeClass() + { + if (!class_exists('Elasticsearch\\RestClient')) { + self::markTestSkipped('munkie/elasticsearch-thrift-php package should be installed to run thrift transport tests'); + } + } + + public function testConstruct() + { + $host = 'localhost'; + $port = 9500; + $client = new Client(array('host' => $host, 'port' => $port, 'transport' => 'Thrift')); + + $this->assertEquals($host, $client->getConnection()->getHost()); + $this->assertEquals($port, $client->getConnection()->getPort()); + } + + /** + * @dataProvider configProvider + */ + public function testSearchRequest($config) + { + $this->_checkPlugin(); + + // Creates a new index 'xodoa' and a type 'user' inside this index + $client = new Client($config); + + $index = $client->getIndex('elastica_test1'); + $index->create(array(), true); + + $type = $index->getType('user'); + + // Adds 1 document to the index + $doc1 = new Document(1, + array('username' => 'hans', 'test' => array('2', '3', '5')) + ); + $doc1->setVersion(0); + $type->addDocument($doc1); + + // Adds a list of documents with _bulk upload to the index + $docs = array(); + $docs[] = new Document(2, + array('username' => 'john', 'test' => array('1', '3', '6')) + ); + $docs[] = new Document(3, + array('username' => 'rolf', 'test' => array('2', '3', '7')) + ); + $type->addDocuments($docs); + + // Refresh index + $index->refresh(); + $resultSet = $type->search('rolf'); + + $this->assertEquals(1, $resultSet->getTotalHits()); + } + + /** + * @expectedException \Elastica\Exception\ConnectionException + */ + public function testInvalidHostRequest() + { + $this->_checkPlugin(); + + $client = new Client(array('host' => 'unknown', 'port' => 9555, 'transport' => 'Thrift')); + $client->getStatus(); + } + + /** + * @expectedException \Elastica\Exception\ResponseException + */ + public function testInvalidElasticRequest() + { + $this->_checkPlugin(); + + $connection = new Connection(); + $connection->setHost('localhost'); + $connection->setPort(9500); + $connection->setTransport('Thrift'); + + $client = new Client(); + $client->addConnection($connection); + + $index = new Index($client, 'missing_index'); + $index->getStatus(); + } + + public function configProvider() + { + return array( + array( + array( + 'host' => 'localhost', + 'port' => 9500, + 'transport' => 'Thrift' + ) + ), + array( + array( + 'host' => 'localhost', + 'port' => 9500, + 'transport' => 'Thrift', + 'config' => array( + 'framedTransport' => false, + 'sendTimeout' => 10000, + 'recvTimeout' => 20000, + ) + ) + ) + ); + } + + protected function _checkPlugin() + { + $nodes = $this->_getClient()->getCluster()->getNodes(); + if (!$nodes[0]->getInfo()->hasPlugin('transport-thrift')) { + $this->markTestSkipped("transport-thrift plugin not installed."); + } + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/Type/MappingTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/Type/MappingTest.php new file mode 100644 index 00000000..796bfb8d --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/Type/MappingTest.php @@ -0,0 +1,304 @@ +<?php + +namespace Elastica\Test\Type; + +use Elastica\Document; +use Elastica\Query; +use Elastica\Query\QueryString; +use Elastica\Test\Base as BaseTest; +use Elastica\Type; +use Elastica\Type\Mapping; + +class MappingTest extends BaseTest +{ + public function testMappingStoreFields() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + + $index->create(array(), true); + $type = $index->getType('test'); + + $mapping = new Mapping($type, + array( + 'firstname' => array('type' => 'string', 'store' => 'yes'), + // default is store => no expected + 'lastname' => array('type' => 'string'), + ) + ); + $mapping->disableSource(); + + $type->setMapping($mapping); + + $firstname = 'Nicolas'; + $doc = new Document(1, + array( + 'firstname' => $firstname, + 'lastname' => 'Ruflin' + ) + ); + + $type->addDocument($doc); + + $index->refresh(); + $queryString = new QueryString('ruflin'); + $query = Query::create($queryString); + $query->setFields(array('*')); + + $resultSet = $type->search($query); + $result = $resultSet->current(); + $fields = $result->getFields(); + + $this->assertEquals($firstname, $fields['firstname'][0]); + $this->assertArrayNotHasKey('lastname', $fields); + $this->assertEquals(1, count($fields)); + + $index->flush(); + $document = $type->getDocument(1); + + $this->assertEmpty($document->getData()); + + $index->delete(); + } + + public function testEnableAllField() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + + $mapping = new Mapping($type, array()); + + $mapping->enableAllField(); + + $data = $mapping->toArray(); + $this->assertTrue($data[$type->getName()]['_all']['enabled']); + + $response = $mapping->send(); + $this->assertTrue($response->isOk()); + + $index->delete(); + } + + public function testEnableTtl() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + + $index->create(array(), true); + $type = $index->getType('test'); + + $mapping = new Mapping($type, array()); + + $mapping->enableTtl(); + + $data = $mapping->toArray(); + $this->assertTrue($data[$type->getName()]['_ttl']['enabled']); + + $index->delete(); + } + + public function testNestedMapping() + { + $client = $this->_getClient(); + $index = $client->getIndex('test'); + + $index->create(array(), true); + $type = $index->getType('test'); + + $this->markTestIncomplete('nested mapping is not set right yet'); + $mapping = new Mapping($type, + array( + 'test' => array( + 'type' => 'object', 'store' => 'yes', 'properties' => array( + 'user' => array( + 'properties' => array( + 'firstname' => array('type' => 'string', 'store' => 'yes'), + 'lastname' => array('type' => 'string', 'store' => 'yes'), + 'age' => array('type' => 'integer', 'store' => 'yes'), + ) + ), + ), + ), + ) + ); + + $type->setMapping($mapping); + + $doc = new Document(1, array( + 'user' => array( + 'firstname' => 'Nicolas', + 'lastname' => 'Ruflin', + 'age' => 9 + ), + )); + + $type->addDocument($doc); + + $index->refresh(); + $resultSet = $type->search('ruflin'); + + $index->delete(); + } + + public function testParentMapping() + { + $index = $this->_createIndex(); + $parenttype = new Type($index, 'parenttype'); + $parentmapping = new Mapping($parenttype, + array( + 'name' => array('type' => 'string', 'store' => 'yes') + ) + ); + + $parenttype->setMapping($parentmapping); + + $childtype = new Type($index, 'childtype'); + $childmapping = new Mapping($childtype, + array( + 'name' => array('type' => 'string', 'store' => 'yes'), + ) + ); + $childmapping->setParent('parenttype'); + + $childtype->setMapping($childmapping); + + $data = $childmapping->toArray(); + $this->assertEquals('parenttype', $data[$childtype->getName()]['_parent']['type']); + + $index->delete(); + } + + public function testMappingExample() + { + $index = $this->_createIndex(); + $type = $index->getType('notes'); + + $mapping = new Mapping($type, + array( + 'note' => array( + 'store' => 'yes', 'properties' => array( + 'titulo' => array('type' => 'string', 'store' => 'no', 'include_in_all' => true, 'boost' => 1.0), + 'contenido' => array('type' => 'string', 'store' => 'no', 'include_in_all' => true, 'boost' => 1.0) + ) + ) + ) + ); + + $type->setMapping($mapping); + + $doc = new Document(1, array( + 'note' => array( + array( + 'titulo' => 'nota1', + 'contenido' => 'contenido1' + ), + array( + 'titulo' => 'nota2', + 'contenido' => 'contenido2' + ) + ) + ) + ); + + $type->addDocument($doc); + + $index->delete(); + } + + /** + * Test setting a dynamic template and validate whether the right mapping is applied after adding a document which + * should match the dynamic template. The example is the template_1 from the Elasticsearch documentation. + * + * @link http://www.elasticsearch.org/guide/reference/mapping/root-object-type/ + */ + public function testDynamicTemplate() + { + $index = $this->_createIndex(); + $type = $index->getType('person'); + + // set a dynamic template "template_1" which creates a multi field for multi* matches. + $mapping = new Mapping($type); + $mapping->setParam('dynamic_templates', array( + array('template_1' => array( + 'match' => 'multi*', + 'mapping' => array( + 'type' => 'multi_field', + 'fields' => array( + '{name}' => array('type' => '{dynamic_type}', 'index' => 'analyzed'), + 'org' => array('type' => '{dynamic_type}', 'index' => 'not_analyzed') + ) + ) + )) + )); + + $mapping->send(); + + // when running the tests, the mapping sometimes isn't available yet. Optimize index to enforce reload mapping. + $index->optimize(); + + // create a document which should create a mapping for the field: multiname. + $testDoc = new Document('person1', array('multiname' => 'Jasper van Wanrooy'), $type); + $index->addDocuments(array($testDoc)); + sleep(1); //sleep 1 to ensure that the test passes every time + + // read the mapping from Elasticsearch and assert that the multiname.org field is "not_analyzed" + $newMapping = $type->getMapping(); + $this->assertArrayHasKey('person', $newMapping, + 'Person type not available in mapping from ES. Mapping set at all?'); + $this->assertArrayHasKey('properties', $newMapping['person'], + 'Person type doesnt have any properties. Document properly added?'); + $this->assertArrayHasKey('multiname', $newMapping['person']['properties'], + 'The multiname property is not added to the mapping. Document properly added?'); + $this->assertArrayHasKey('fields', $newMapping['person']['properties']['multiname'], + 'The multiname field of the Person type is presumably not a multi_field type. Dynamic mapping not applied?'); + $this->assertArrayHasKey('org', $newMapping['person']['properties']['multiname']['fields'], + 'The multi* matcher did not create a mapping for the multiname.org property when indexing the document.'); + $this->assertArrayHasKey('index', $newMapping['person']['properties']['multiname']['fields']['org'], + 'Indexing status of the multiname.org not available. Dynamic mapping not fully applied!'); + $this->assertEquals('not_analyzed', $newMapping['person']['properties']['multiname']['fields']['org']['index']); + + $index->delete(); + } + + public function testSetMeta() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + $mapping = new Mapping($type, array( + 'firstname' => array('type' => 'string', 'store' => 'yes'), + 'lastname' => array('type' => 'string') + )); + $mapping->setMeta(array('class' => 'test')); + $type->setMapping($mapping); + + $mappingData = $type->getMapping(); + $this->assertEquals('test', $mappingData['test']['_meta']['class']); + + $index->delete(); + } + + public function testGetters() + { + $index = $this->_createIndex(); + $type = $index->getType('test'); + $properties = array( + 'firstname' => array('type' => 'string', 'store' => 'yes'), + 'lastname' => array('type' => 'string') + ); + $mapping = new Mapping($type, $properties); + $all = array( + "enabled" => true, + "store" => "yes" + ); + $mapping->setParam('_all', $all); + $get_all = $mapping->getParam('_all'); + + $this->assertEquals($get_all, $all); + + $this->assertNull($mapping->getParam('_boost', $all)); + + $this->assertEquals($properties, $mapping->getProperties()); + + $index->delete(); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/TypeTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/TypeTest.php new file mode 100644 index 00000000..40e56c3b --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/TypeTest.php @@ -0,0 +1,823 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Client; +use Elastica\Document; +use Elastica\Exception\NotFoundException; +use Elastica\Exception\ResponseException; +use Elastica\Query; +use Elastica\Query\MatchAll; +use Elastica\Query\SimpleQueryString; +use Elastica\Script; +use Elastica\Search; +use Elastica\Filter\Term; +use Elastica\Type; +use Elastica\Index; +use Elastica\Type\Mapping; +use Elastica\Test\Base as BaseTest; + +class TypeTest extends BaseTest +{ + public function testSearch() + { + $index = $this->_createIndex(); + + $type = new Type($index, 'user'); + + // Adds 1 document to the index + $doc1 = new Document(1, + array('username' => 'hans', 'test' => array('2', '3', '5')) + ); + $type->addDocument($doc1); + + // Adds a list of documents with _bulk upload to the index + $docs = array(); + $docs[] = new Document(2, + array('username' => 'john', 'test' => array('1', '3', '6')) + ); + $docs[] = new Document(3, + array('username' => 'rolf', 'test' => array('2', '3', '7')) + ); + $type->addDocuments($docs); + $index->refresh(); + + $resultSet = $type->search('rolf'); + $this->assertEquals(1, $resultSet->count()); + + $count = $type->count('rolf'); + $this->assertEquals(1, $count); + + // Test if source is returned + $result = $resultSet->current(); + $this->assertEquals(3, $result->getId()); + $data = $result->getData(); + $this->assertEquals('rolf', $data['username']); + } + + public function testCreateSearch() + { + $client = $this->_getClient(); + $index = new Index($client, 'test_index'); + $type = new Type($index, 'test_type'); + + $query = new Query\QueryString('test'); + $options = array( + 'limit' => 5, + 'explain' => true, + ); + + $search = $type->createSearch($query, $options); + + $expected = array( + 'query' => array( + 'query_string' => array( + 'query' => 'test' + ) + ), + 'size' => 5, + 'explain' => true + ); + $this->assertEquals($expected, $search->getQuery()->toArray()); + $this->assertEquals(array('test_index'), $search->getIndices()); + $this->assertTrue($search->hasIndices()); + $this->assertTrue($search->hasIndex($index)); + $this->assertTrue($search->hasIndex('test_index')); + $this->assertFalse($search->hasIndex('test')); + $this->assertEquals(array('test_type'), $search->getTypes()); + $this->assertTrue($search->hasTypes()); + $this->assertTrue($search->hasType($type)); + $this->assertTrue($search->hasType('test_type')); + $this->assertFalse($search->hasType('test_type2')); + } + + public function testCreateSearchWithArray() + { + $client = $this->_getClient(); + $index = new Index($client, 'test_index'); + $type = new Type($index, 'test_type'); + + $query = array( + 'query' => array( + 'query_string' => array( + 'query' => 'test' + ) + ) + ); + + $options = array( + 'limit' => 5, + 'explain' => true, + ); + + $search = $type->createSearch($query, $options); + + $expected = array( + 'query' => array( + 'query_string' => array( + 'query' => 'test' + ) + ), + 'size' => 5, + 'explain' => true + ); + $this->assertEquals($expected, $search->getQuery()->toArray()); + $this->assertEquals(array('test_index'), $search->getIndices()); + $this->assertTrue($search->hasIndices()); + $this->assertTrue($search->hasIndex($index)); + $this->assertTrue($search->hasIndex('test_index')); + $this->assertFalse($search->hasIndex('test')); + $this->assertEquals(array('test_type'), $search->getTypes()); + $this->assertTrue($search->hasTypes()); + $this->assertTrue($search->hasType($type)); + $this->assertTrue($search->hasType('test_type')); + $this->assertFalse($search->hasType('test_type2')); + } + + public function testNoSource() + { + $index = $this->_createIndex(); + + $type = new Type($index, 'user'); + $mapping = new Mapping($type, array( + 'id' => array('type' => 'integer', 'store' => 'yes'), + 'username' => array('type' => 'string', 'store' => 'no'), + )); + $mapping->setSource(array('enabled' => false)); + $type->setMapping($mapping); + + $mapping = $type->getMapping(); + + $this->assertArrayHasKey('user', $mapping); + $this->assertArrayHasKey('properties', $mapping['user']); + $this->assertArrayHasKey('id', $mapping['user']['properties']); + $this->assertArrayHasKey('type', $mapping['user']['properties']['id']); + $this->assertEquals('integer', $mapping['user']['properties']['id']['type']); + + // Adds 1 document to the index + $doc1 = new Document(1, + array('username' => 'hans', 'test' => array('2', '3', '5')) + ); + $type->addDocument($doc1); + + // Adds a list of documents with _bulk upload to the index + $docs = array(); + $docs[] = new Document(2, + array('username' => 'john', 'test' => array('1', '3', '6')) + ); + $docs[] = new Document(3, + array('username' => 'rolf', 'test' => array('2', '3', '7')) + ); + $type->addDocuments($docs); + + // To update index + $index->refresh(); + + $resultSet = $type->search('rolf'); + + $this->assertEquals(1, $resultSet->count()); + + // Tests if no source is in response except id + $result = $resultSet->current(); + $this->assertEquals(3, $result->getId()); + $this->assertEmpty($result->getData()); + } + + public function testDeleteById() + { + $index = $this->_createIndex(); + $type = new Type($index, 'user'); + + // Adds hans, john and rolf to the index + $docs = array( + new Document(1, array('username' => 'hans', 'test' => array('2', '3', '5'))), + new Document(2, array('username' => 'john', 'test' => array('1', '3', '6'))), + new Document(3, array('username' => 'rolf', 'test' => array('2', '3', '7'))), + new Document('foo/bar', array('username' => 'georg', 'test' => array('4', '2', '5'))), + ); + $type->addDocuments($docs); + $index->refresh(); + + // sanity check for rolf + $resultSet = $type->search('rolf'); + $this->assertEquals(1, $resultSet->count()); + $data = $resultSet->current()->getData(); + $this->assertEquals('rolf', $data['username']); + + // delete rolf + $type->deleteById(3); + $index->refresh(); + + // rolf should no longer be there + $resultSet = $type->search('rolf'); + $this->assertEquals(0, $resultSet->count()); + + // sanity check for id with slash + $resultSet = $type->search('georg'); + $this->assertEquals(1, $resultSet->count()); + + // delete georg + $type->deleteById('foo/bar'); + $index->refresh(); + + // georg should no longer be there + $resultSet = $type->search('georg'); + $this->assertEquals(0, $resultSet->count()); + + // it should not be possible to delete the entire type with this method + try { + $type->deleteById(''); + $this->fail('Delete with empty string id should fail'); + } catch (\InvalidArgumentException $e) { + $this->assertTrue(true); + } + + try { + $type->deleteById(' '); + $this->fail('Delete with one space string id should fail'); + } catch (\InvalidArgumentException $e) { + $this->assertTrue(true); + } + + try { + $type->deleteById(null); + $this->fail('Delete with null id should fail'); + } catch (\InvalidArgumentException $e) { + $this->assertTrue(true); + } + + try { + $type->deleteById(array()); + $this->fail('Delete with empty array id should fail'); + } catch (\InvalidArgumentException $e) { + $this->assertTrue(true); + } + + try { + $type->deleteById('*'); + $this->fail('Delete request should fail because of invalid id: *'); + } catch (NotFoundException $e) { + $this->assertTrue(true); + } + + try { + $type->deleteById('*:*'); + $this->fail('Delete request should fail because document with id *.* does not exist'); + } catch (NotFoundException $e) { + $this->assertTrue(true); + } + + try { + $type->deleteById('!'); + $this->fail('Delete request should fail because document with id ! does not exist'); + } catch (NotFoundException $e) { + $this->assertTrue(true); + } + + $index->refresh(); + + // rolf should no longer be there + $resultSet = $type->search('john'); + $this->assertEquals(1, $resultSet->count()); + } + + public function testDeleteDocument() + { + $index = $this->_createIndex(); + $type = new Type($index, 'user'); + + // Adds hans, john and rolf to the index + $docs = array( + new Document(1, array('username' => 'hans', 'test' => array('2', '3', '5'))), + new Document(2, array('username' => 'john', 'test' => array('1', '3', '6'))), + new Document(3, array('username' => 'rolf', 'test' => array('2', '3', '7'))), + ); + $type->addDocuments($docs); + $index->refresh(); + + $document = $type->getDocument(1); + $this->assertEquals(1, $document->getId()); + $this->assertEquals('hans', $document->get('username')); + + $this->assertEquals(3, $type->count()); + + $type->deleteDocument($document); + $index->refresh(); + + try { + $type->getDocument(1); + $this->fail('Document was not deleted'); + } catch (NotFoundException $e) { + $this->assertTrue(true); + $this->assertEquals(2, $type->count(), 'Documents count in type should be 2'); + } + } + + /** + * @expectedException \Elastica\Exception\NotFoundException + */ + public function testGetDocumentNotExist() + { + $index = $this->_createIndex(); + $type = new Type($index, 'test'); + $type->addDocument(new Document(1, array('name' => 'ruflin'))); + $index->refresh(); + + $type->getDocument(1); + + $type->getDocument(2); + } + + /** + * @expectedException \Elastica\Exception\NotFoundException + */ + public function testGetDocumentNotExistingIndex() + { + $client = new Client(); + $index = new Index($client, 'index'); + $type = new Type($index, 'type'); + + $type->getDocument(1); + } + + public function testDeleteByQueryWithQueryString() + { + $index = $this->_createIndex(); + $type = new Type($index, 'test'); + $type->addDocument(new Document(1, array('name' => 'ruflin nicolas'))); + $type->addDocument(new Document(2, array('name' => 'ruflin'))); + $index->refresh(); + + $response = $index->search('ruflin*'); + $this->assertEquals(2, $response->count()); + + $response = $index->search('nicolas'); + $this->assertEquals(1, $response->count()); + + // Delete first document + $response = $type->deleteByQuery('nicolas'); + $this->assertTrue($response->isOk()); + + $index->refresh(); + + // Makes sure, document is deleted + $response = $index->search('ruflin*'); + $this->assertEquals(1, $response->count()); + + $response = $index->search('nicolas'); + $this->assertEquals(0, $response->count()); + } + + public function testDeleteByQueryWithQuery() + { + $index = $this->_createIndex(); + $type = new Type($index, 'test'); + $type->addDocument(new Document(1, array('name' => 'ruflin nicolas'))); + $type->addDocument(new Document(2, array('name' => 'ruflin'))); + $index->refresh(); + + $response = $index->search('ruflin*'); + $this->assertEquals(2, $response->count()); + + $response = $index->search('nicolas'); + $this->assertEquals(1, $response->count()); + + // Delete first document + $response = $type->deleteByQuery(new SimpleQueryString('nicolas')); + $this->assertTrue($response->isOk()); + + $index->refresh(); + + // Makes sure, document is deleted + $response = $index->search('ruflin*'); + $this->assertEquals(1, $response->count()); + + $response = $index->search('nicolas'); + $this->assertEquals(0, $response->count()); + } + + public function testDeleteByQueryWithQueryAndOptions() + { + $index = $this->_createIndex('test', true, 2); + $type = new Type($index, 'test'); + $type->addDocument(new Document(1, array('name' => 'ruflin nicolas'))); + $type->addDocument(new Document(2, array('name' => 'ruflin'))); + $index->refresh(); + + $response = $index->search('ruflin*'); + $this->assertEquals(2, $response->count()); + + $response = $index->search('nicolas'); + $this->assertEquals(1, $response->count()); + + // Route to the wrong document id; should not delete + $response = $type->deleteByQuery(new SimpleQueryString('nicolas'), array('routing'=>'2')); + $this->assertTrue($response->isOk()); + + $index->refresh(); + + $response = $index->search('ruflin*'); + $this->assertEquals(2, $response->count()); + + $response = $index->search('nicolas'); + $this->assertEquals(1, $response->count()); + + // Delete first document + $response = $type->deleteByQuery(new SimpleQueryString('nicolas'), array('routing'=>'1')); + $this->assertTrue($response->isOk()); + + $index->refresh(); + + // Makes sure, document is deleted + $response = $index->search('ruflin*'); + $this->assertEquals(1, $response->count()); + + $response = $index->search('nicolas'); + $this->assertEquals(0, $response->count()); + } + + /** + * Test to see if Elastica_Type::getDocument() is properly using + * the fields array when available instead of _source + */ + public function testGetDocumentWithFieldsSelection() + { + $index = $this->_createIndex(); + $type = new Type($index, 'test'); + $type->addDocument(new Document(1, array('name' => 'loris', 'country' => 'FR', 'email' => 'test@test.com'))); + $index->refresh(); + + $document = $type->getDocument(1, array('fields' => 'name,email')); + $data = $document->getData(); + + $this->assertArrayHasKey('name', $data); + $this->assertArrayHasKey('email', $data); + $this->assertArrayNotHasKey('country', $data); + } + + /** + * Test to see if search Default Limit works + */ + public function testLimitDefaultType() + { + $client = $this->_getClient(); + $index = $client->getIndex('zero'); + $index->create(array('index' => array('number_of_shards' => 1, 'number_of_replicas' => 0)), true); + + $docs = array(); + $docs[] = new Document(1, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(2, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(3, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(4, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(5, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(6, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(7, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(8, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(9, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(10, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + $docs[] = new Document(11, array('id' => 1, 'email' => 'test@test.com', 'username' => 'farrelley')); + + $type = $index->getType('zeroType'); + $type->addDocuments($docs); + $index->refresh(); + + // default results (limit default is 10) + $resultSet = $type->search('farrelley'); + $this->assertEquals(10, $resultSet->count()); + + // limit = 1 + $resultSet = $type->search('farrelley', 1); + $this->assertEquals(1, $resultSet->count()); + } + + /** + * Test Delete of index type. After delete will check for type mapping. + */ + public function testDeleteType() + { + $index = $this->_createIndex(); + $type = new Type($index, 'test'); + $type->addDocument(new Document(1, array('name' => 'ruflin nicolas'))); + $type->addDocument(new Document(2, array('name' => 'ruflin'))); + $index->refresh(); + + $type->delete(); + $this->assertFalse($type->exists()); + } + + public function testMoreLikeThisApi() + { + $client = new Client(array('persistent' => false)); + $index = $client->getIndex('elastica_test'); + $index->create(array('index' => array('number_of_shards' => 1, 'number_of_replicas' => 0)), true); + + $type = new Type($index, 'mlt_test'); + $type->addDocument(new Document(1, array('visible' => true, 'name' => 'bruce wayne batman'))); + $type->addDocument(new Document(2, array('visible' => true, 'name' => 'bruce wayne'))); + $type->addDocument(new Document(3, array('visible' => false, 'name' => 'bruce wayne'))); + $type->addDocument(new Document(4, array('visible' => true, 'name' => 'batman'))); + $type->addDocument(new Document(5, array('visible' => false, 'name' => 'batman'))); + $type->addDocument(new Document(6, array('visible' => true, 'name' => 'superman'))); + $type->addDocument(new Document(7, array('visible' => true, 'name' => 'spiderman'))); + + $index->refresh(); + + $document = $type->getDocument(1); + + // Return all similar + $resultSet = $type->moreLikeThis($document, array('min_term_freq' => '1', 'min_doc_freq' => '1')); + $this->assertEquals(4, $resultSet->count()); + + // Return just the visible similar + $query = new Query(); + $filterTerm = new Term(); + $filterTerm->setTerm('visible', true); + $query->setFilter($filterTerm); + + $resultSet = $type->moreLikeThis($document, array('min_term_freq' => '1', 'min_doc_freq' => '1'), $query); + $this->assertEquals(2, $resultSet->count()); + } + + public function testUpdateDocument() + { + $client = $this->_getClient(); + $index = $client->getIndex('elastica_test'); + $type = $index->getType('update_type'); + $id = 1; + $type->addDocument(new Document($id, array('name' => 'bruce wayne batman', 'counter' => 1))); + $newName = 'batman'; + + $document = new Document(); + $script = new Script( + "ctx._source.name = name; ctx._source.counter += count", + array( + 'name' => $newName, + 'count' => 2, + ), + null, + $id + ); + $script->setUpsert($document); + + $type->updateDocument($script, array('refresh' => true)); + $updatedDoc = $type->getDocument($id)->getData(); + $this->assertEquals($newName, $updatedDoc['name'], "Name was not updated"); + $this->assertEquals(3, $updatedDoc['counter'], "Counter was not incremented"); + } + + public function testUpdateDocumentWithFieldsSource() + { + $client = $this->_getClient(); + $index = $client->getIndex('elastica_test'); + $type = $index->getType('update_type'); + + $client->setConfigValue('document', array('autoPopulate' => true)); + + $newDocument = new Document(null, array('counter' => 5, 'name' => 'Batman')); + + $this->assertFalse($newDocument->hasVersion()); + + $response = $type->addDocument($newDocument); + $responseData = $response->getData(); + + $this->assertTrue($newDocument->hasVersion()); + $this->assertArrayHasKey('_version', $responseData, '_version is missing in response data it is weird'); + $this->assertEquals(1, $responseData['_version']); + $this->assertEquals($responseData['_version'], $newDocument->getVersion()); + + $this->assertTrue($newDocument->hasId()); + + $script = new Script('ctx._source.counter += count; ctx._source.realName = realName'); + $script->setId($newDocument->getId()); + $script->setParam('count', 7); + $script->setParam('realName', 'Bruce Wayne'); + $script->setUpsert($newDocument); + + $newDocument->setFieldsSource(); + + $response = $type->updateDocument($script); + $responseData = $response->getData(); + + $data = $type->getDocument($newDocument->getId())->getData(); + + $this->assertEquals(12, $data['counter']); + $this->assertEquals('Batman', $data['name']); + $this->assertEquals('Bruce Wayne', $data['realName']); + + $this->assertTrue($newDocument->hasVersion()); + $this->assertArrayHasKey('_version', $responseData, '_version is missing in response data it is weird'); + $this->assertEquals(2, $responseData['_version']); + + $document = $type->getDocument($newDocument->getId()); + } + + /** + * @expectedException \Elastica\Exception\InvalidException + */ + public function testUpdateDocumentWithoutId() + { + $index = $this->_createIndex(); + $type = $index->getType('elastica_type'); + + $document = new Document(); + + $type->updateDocument($document); + } + + public function testUpdateDocumentWithoutSource() + { + $index = $this->_createIndex(); + $type = $index->getType('elastica_type'); + + $mapping = new Mapping(); + $mapping->setProperties(array( + 'name' => array( + 'type' => 'string', + 'store' => 'yes'), + 'counter' => array( + 'type' => 'integer', + 'store' => 'no' + ), + )); + $mapping->disableSource(); + $type->setMapping($mapping); + + $newDocument = new Document(); + $newDocument->setAutoPopulate(); + $newDocument->set('name', 'Batman'); + $newDocument->set('counter', 1); + + $type->addDocument($newDocument); + + $script = new Script('ctx._source.counter += count; ctx._source.name = name'); + $script->setId($newDocument->getId()); + $script->setParam('count', 2); + $script->setParam('name', 'robin'); + + $script->setUpsert($newDocument); + + try { + $type->updateDocument($script); + $this->fail('Update request should fail because source is disabled. Fields param is not set'); + } catch (ResponseException $e) { + $this->assertContains('DocumentSourceMissingException', $e->getMessage()); + } + + $newDocument->setFieldsSource(); + + try { + $type->updateDocument($newDocument); + $this->fail('Update request should fail because source is disabled. Fields param is set to _source'); + } catch (ResponseException $e) { + $this->assertContains('DocumentSourceMissingException', $e->getMessage()); + } + } + + public function testAddDocumentHashId() + { + $index = $this->_createIndex(); + $type = $index->getType('test2'); + + $hashId = '#1'; + + $doc = new Document($hashId, array('name' => 'ruflin')); + $type->addDocument($doc); + + $index->refresh(); + + $search = new Search($index->getClient()); + $search->addIndex($index); + $resultSet = $search->search(new MatchAll()); + $this->assertEquals($hashId, $resultSet->current()->getId()); + + $doc = $type->getDocument($hashId); + $this->assertEquals($hashId, $doc->getId()); + } + + public function testAddDocumentAutoGeneratedId() + { + $index = $this->_createIndex(); + $type = $index->getType('elastica_type'); + + $document = new Document(); + $document->setAutoPopulate(); + $document->set('name', 'ruflin'); + $this->assertEquals('', $document->getId()); + $this->assertFalse($document->hasId()); + + $type->addDocument($document); + + $this->assertNotEquals('', $document->getId()); + $this->assertTrue($document->hasId()); + + $foundDoc = $type->getDocument($document->getId()); + $this->assertInstanceOf('Elastica\Document', $foundDoc); + $this->assertEquals($document->getId(), $foundDoc->getId()); + $data = $foundDoc->getData(); + $this->assertArrayHasKey('name', $data); + $this->assertEquals('ruflin', $data['name']); + } + + /** + * @expectedException \Elastica\Exception\RuntimeException + */ + public function testAddDocumentWithoutSerializer() + { + $index = $this->_createIndex(); + + $type = new Type($index, 'user'); + + $type->addObject(new \stdClass()); + } + + public function testAddObject() + { + $index = $this->_createIndex(); + + $type = new Type($index, 'user'); + $type->setSerializer(array(new SerializerMock(), 'serialize')); + + $userObject = new \stdClass(); + $userObject->username = 'hans'; + $userObject->test = array('2', '3', '5'); + + $type->addObject($userObject); + + $index->refresh(); + + $resultSet = $type->search('hans'); + $this->assertEquals(1, $resultSet->count()); + + // Test if source is returned + $result = $resultSet->current(); + $data = $result->getData(); + $this->assertEquals('hans', $data['username']); + } + + public function testExists() + { + $index = $this->_createIndex(); + $this->assertTrue($index->exists()); + + $type = new Type($index, 'user'); + $this->assertFalse($type->exists()); + + $type->addDocument(new Document(1, array('name' => 'test name'))); + $index->optimize(); + + //Test if type exists + $this->assertTrue($type->exists()); + + $index->delete(); + $this->assertFalse($index->exists()); + } + + public function testGetMapping() { + $indexName = 'test'; + $typeName = 'test-type'; + + $index = $this->_createIndex($indexName); + $indexName = $index->getName(); + $type = new Type($index, $typeName); + $mapping = new Mapping($type, $expect = array( + 'id' => array('type' => 'integer', 'store' => true) + )); + $type->setMapping($mapping); + + $client = $index->getClient(); + + $this->assertEquals( + array('test-type' => array('properties' => $expect)), + $client->getIndex($indexName)->getType($typeName)->getMapping() + ); + } + + public function testGetMappingAlias() { + $indexName = 'test'; + $aliasName = 'test-alias'; + $typeName = 'test-alias-type'; + + $index = $this->_createIndex($indexName); + $index->addAlias($aliasName); + $type = new Type($index, $typeName); + $mapping = new Mapping($type, $expect = array( + 'id' => array('type' => 'integer', 'store' => true) + )); + $type->setMapping($mapping); + + $client = $index->getClient(); + + $this->assertEquals( + array('test-alias-type' => array('properties' => $expect)), + $client->getIndex($aliasName)->getType($typeName)->getMapping() + ); + } +} + +class SerializerMock +{ + public function serialize($object) + { + return get_object_vars($object); + } +} diff --git a/vendor/ruflin/elastica/test/lib/Elastica/Test/UtilTest.php b/vendor/ruflin/elastica/test/lib/Elastica/Test/UtilTest.php new file mode 100644 index 00000000..09d4b5b1 --- /dev/null +++ b/vendor/ruflin/elastica/test/lib/Elastica/Test/UtilTest.php @@ -0,0 +1,77 @@ +<?php + +namespace Elastica\Test; + +use Elastica\Util; +use Elastica\Request; +use Elastica\Connection; +use Elastica\Test\Base as BaseTest; + +class UtilTest extends BaseTest +{ + /** + * @dataProvider getEscapeTermPairs + */ + public function testEscapeTerm($unescaped, $escaped) + { + $this->assertEquals($escaped, Util::escapeTerm($unescaped)); + } + + public function getEscapeTermPairs() + { + return array( + array('', ''), + array('pragmatic banana', 'pragmatic banana'), + array('oh yeah!', 'oh yeah\\!'), + // Seperate test below because phpunit seems to have some problems + //array('\\+-&&||!(){}[]^"~*?:', '\\\\\\+\\-\\&&\\||\\!\\(\\)\\{\\}\\[\\]\\^\\"\\~\\*\\?\\:'), + array('some signs, can stay.', 'some signs, can stay.') + ); + } + + public function testEscapeTermSpecialCharacters() + { + $before = '\\+-&&||!(){}[]^"~*?:/'; + $after = '\\\\\\+\\-\\&&\\||\\!\\(\\)\\{\\}\\[\\]\\^\\"\\~\\*\\?\\:\\\\/'; + + $this->assertEquals(Util::escapeTerm($before), $after); + } + + public function testToCamelCase() + { + $string = 'hello_world'; + $this->assertEquals('HelloWorld', Util::toCamelCase($string)); + + $string = 'how_are_you_today'; + $this->assertEquals('HowAreYouToday', Util::toCamelCase($string)); + } + + public function testToSnakeCase() + { + $string = 'HelloWorld'; + $this->assertEquals('hello_world', Util::toSnakeCase($string)); + + $string = 'HowAreYouToday'; + $this->assertEquals('how_are_you_today', Util::toSnakeCase($string)); + } + + public function testConvertRequestToCurlCommand() + { + $path = 'test'; + $method = Request::POST; + $query = array('no' => 'params'); + $data = array('key' => 'value'); + + $connection = new Connection(); + $connection->setHost('localhost'); + $connection->setPort('9200'); + + $request = new Request($path, $method, $data, $query, $connection); + + $curlCommand = Util::convertRequestToCurlCommand($request); + + $expected = 'curl -XPOST \'http://localhost:9200/test?no=params\' -d \'{"key":"value"}\''; + $this->assertEquals($expected, $curlCommand); + + } +} diff --git a/vendor/ruflin/elastica/test/nginx/nginx.conf b/vendor/ruflin/elastica/test/nginx/nginx.conf new file mode 100644 index 00000000..97f45fbc --- /dev/null +++ b/vendor/ruflin/elastica/test/nginx/nginx.conf @@ -0,0 +1,24 @@ +events { + worker_connections 1024; +} + +http { + access_log logs/access.log; + error_log logs/error.log; + + server { + listen 127.0.0.1:12345; + + location / { + proxy_pass http://127.0.0.1:9201; + } + } + + server { + listen 127.0.0.1:12346; + + location / { + return 403; + } + } +} diff --git a/vendor/ruflin/elastica/test/phpunit.xml.dist b/vendor/ruflin/elastica/test/phpunit.xml.dist new file mode 100644 index 00000000..a863692c --- /dev/null +++ b/vendor/ruflin/elastica/test/phpunit.xml.dist @@ -0,0 +1,32 @@ +<phpunit + bootstrap="./bootstrap.php" + backupGlobals="false" + backupStaticAttributes="false" + convertErrorsToExceptions="true" + convertNoticesToExceptions="true" + convertWarningsToExceptions="true" + stopOnError="false" + stopOnFailure="false" + stopOnIncomplete="false" + stopOnSkipped="false" + syntaxCheck="false" + processIsolation="false"> + + <testsuites> + <testsuite name="Elastica"> + <directory>./lib/Elastica/</directory> + </testsuite> + </testsuites> + <filter> + <whitelist> + <directory suffix=".php">../lib/</directory> + </whitelist> + </filter> + <logging> + <log type="coverage-html" target="../build/coverage" title="Elastica" + charset="UTF-8" yui="true" highlight="true" + lowUpperBound="35" highLowerBound="70"/> + <log type="coverage-clover" target="../build/logs/clover.xml"/> + <log type="junit" target="../build/logs/junit.xml" logIncompleteSkipped="false"/> + </logging> +</phpunit> diff --git a/vendor/zordius/lightncandy/build/gen_doc b/vendor/zordius/lightncandy/build/gen_doc deleted file mode 100644 index 428e619d..00000000 --- a/vendor/zordius/lightncandy/build/gen_doc +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -curl -O https://cloud.github.com/downloads/apigen/apigen/ApiGen-2.8.0-standalone.zip -unzip -oq ApiGen-2.8.0-standalone.zip -rm ApiGen-2.8.0-standalone.zip -php -dopen_basedir=/ apigen/apigen.php --source src/ --destination build/result/docs/ --template-config apigen/templates/bootstrap/config.neon --deprecated yes -rm -rf apigen diff --git a/vendor/zordius/lightncandy/build/gen_test.php b/vendor/zordius/lightncandy/build/gen_test.php deleted file mode 100644 index 97d49489..00000000 --- a/vendor/zordius/lightncandy/build/gen_test.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -foreach (Array( - 'vendor/phpunit/phpunit/PHPUnitPHPUnit/Autoload.php', - 'PHPUnit/Autoload.php', - 'src/lightncandy.php' -) as $inc) { - if (file_exists($inc)) { - include_once($inc); - break; - } -} - -genTestForClass('LightnCandy'); -genTestForClass('LCRun3'); - -function genTestForClass($classname) { - ob_start(); - - echo <<<VAR -<?php -/** - * Generated by build/gen_test - */ -require_once('src/lightncandy.php'); - -class {$classname}Test extends PHPUnit_Framework_TestCase -{ - -VAR - ; - - $class = new ReflectionClass($classname); - foreach ($class->getMethods() as $method) { - if (preg_match_all('/@expect (.+) when input (.+)( after (.+))?/', $method->getDocComment(), $matched)) { - echo <<<VAR - /** - * @covers {$classname}::{$method->name} - */ - public function testOn_{$method->name}() { - \$method = new ReflectionMethod('$classname', '{$method->name}'); - -VAR - ; - if ($method->isPrivate() || $method->isProtected()) { - echo " \$method->setAccessible(true);\n"; - } - foreach ($matched[1] as $idx => $expect) { - if ($matched[3][$idx]) { - echo " {$matched[3][$idx]}\n"; - } - echo " \$this->assertEquals($expect, \$method->invoke(null,\n {$matched[2][$idx]}\n ));\n"; - } - echo " }\n"; - } - } - echo "}\n?>"; - - $fn = "tests/{$classname}Test.php"; - if (!file_put_contents($fn, ob_get_clean())) { - die("Can not generate tests into file $fn !!\n"); - } -} -?> diff --git a/vendor/zordius/lightncandy/build/push_ghpage b/vendor/zordius/lightncandy/build/push_ghpage deleted file mode 100644 index de64e2b9..00000000 --- a/vendor/zordius/lightncandy/build/push_ghpage +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh -git checkout -B gh-pages -git pull origin gh-pages -rm * -rm -rf src -rm -rf test -cp -r build/result/docs/* . -rm -rf build -rm .travis.yml -git add . -git commit -a -m "New documents on github" -git push origin gh-pages diff --git a/vendor/zordius/lightncandy/build/runphp b/vendor/zordius/lightncandy/build/runphp deleted file mode 100644 index aa694de3..00000000 --- a/vendor/zordius/lightncandy/build/runphp +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -php -dopen_basedir=/ $1 $2 diff --git a/vendor/zordius/lightncandy/build/travis_push b/vendor/zordius/lightncandy/build/travis_push deleted file mode 100644 index b51e4dcc..00000000 --- a/vendor/zordius/lightncandy/build/travis_push +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/sh -echo "DEBUG ENV: ${TRAVIS_JOB_NUMBER} , ${TRAVIS_BUILD_NUMBER} , ${TRAVIS_PULL_REQUEST} ..." - -if [ "${TRAVIS_PULL_REQUEST}" != "false" ]; then - echo "This is a PR, skip push." - exit 0 -fi - -if [ "${TRAVIS_BUILD_NUMBER}.1" != "${TRAVIS_JOB_NUMBER}" ]; then - echo "Only push documents 1 time... quit." - exit 0 -fi - -# Push coverage report -wget https://scrutinizer-ci.com/ocular.phar -php ocular.phar code-coverage:upload --format=php-clover coverage.clover - -# Set for all push in this script. -git config --global user.name "Travis-CI" -git config --global user.email "zordius@yahoo-inc.com" - -# Generate ANSI sample -git clone https://github.com/fcambus/ansilove -php tests/example_debug.php > example_debug -php ansilove/ansilove example_debug -git add example_debug.png - -# Push new tests back to this branch -git commit -a -m "Auto generated tests from Travis [ci skip]" -git push "https://${GHTK}@github.com/zordius/lightncandy.git" HEAD:${TRAVIS_BRANCH} > /dev/null 2>&1 - -# Update hash in HandlebarsTest and push back, trigger new tests there. -git clone https://github.com/zordius/HandlebarsTest -cd HandlebarsTest -echo ${TRAVIS_COMMIT} > lightncandy -git add lightncandy -git commit -a -m "Auto test on zordius/lightncandy@${TRAVIS_COMMIT}" -git push "https://${GHTK}@github.com/zordius/HandlebarsTest.git" > /dev/null 2>&1 -cd .. - -# Generate documents for this branch -build/gen_doc -cd build/result/docs - -if [ "${TRAVIS_BRANCH}" != "master" ]; then - echo "Document will be pushed here: http://zordius.github.io/lightncandy/${TRAVIS_BRANCH}/" - cd .. - git init - git pull --quiet "https://${GHTK}@github.com/zordius/lightncandy.git" gh-pages:master > /dev/null 2>&1 - rm -rf $TRAVIS_BRANCH - mv docs $TRAVIS_BRANCH - git add $TRAVIS_BRANCH -else - echo "Document will be pushed here: http://zordius.github.io/lightncandy/" - git init - git add . -fi - -git commit -m "Auto deployed to Github Pages from branch ${TRAVIS_BRANCH} @${TRAVIS_COMMIT} [ci skip]" -git push --force --quiet "https://${GHTK}@github.com/zordius/lightncandy.git" master:gh-pages > /dev/null 2>&1 |