summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--RELEASE-NOTES-1.2530
-rw-r--r--docs/hooks.txt5
-rw-r--r--extensions/ArchInterWiki.sql2
-rw-r--r--extensions/ConfirmEdit/FancyCaptcha/ApiFancyCaptchaReload.php (renamed from extensions/ConfirmEdit/ApiFancyCaptchaReload.php)0
-rw-r--r--extensions/ConfirmEdit/FancyCaptcha/extension.json4
-rw-r--r--extensions/ConfirmEdit/ReCaptcha/extension.json2
-rw-r--r--extensions/ConfirmEdit/includes/ConfirmEditHooks.php27
-rw-r--r--extensions/SyntaxHighlight_GeSHi/geshi/contrib/aliased.php122
-rw-r--r--extensions/SyntaxHighlight_GeSHi/geshi/contrib/cssgen.php464
-rw-r--r--extensions/SyntaxHighlight_GeSHi/geshi/contrib/cssgen2.php59
-rw-r--r--extensions/SyntaxHighlight_GeSHi/geshi/contrib/example.php217
-rw-r--r--extensions/SyntaxHighlight_GeSHi/geshi/contrib/langcheck.php778
-rw-r--r--extensions/SyntaxHighlight_GeSHi/geshi/contrib/langwiz.php1153
-rw-r--r--includes/DefaultSettings.php2
-rw-r--r--includes/GlobalFunctions.php2
-rw-r--r--includes/Setup.php4
-rw-r--r--includes/User.php37
-rw-r--r--includes/api/ApiBase.php2
-rw-r--r--includes/api/ApiOpenSearch.php14
-rw-r--r--includes/api/ApiQueryImageInfo.php5
-rw-r--r--includes/exception/MWExceptionHandler.php7
-rw-r--r--includes/filerepo/ForeignAPIRepo.php1
-rw-r--r--includes/installer/DatabaseUpdater.php23
-rw-r--r--includes/registration/ExtensionProcessor.php1
-rw-r--r--includes/registration/ExtensionRegistry.php20
-rw-r--r--includes/specials/SpecialDeletedContributions.php2
-rw-r--r--includes/specials/SpecialVersion.php4
-rw-r--r--languages/i18n/af.json2
-rw-r--r--languages/i18n/am.json2
-rw-r--r--languages/i18n/an.json2
-rw-r--r--languages/i18n/ar.json2
-rw-r--r--languages/i18n/arc.json2
-rw-r--r--languages/i18n/arn.json2
-rw-r--r--languages/i18n/ary.json2
-rw-r--r--languages/i18n/arz.json2
-rw-r--r--languages/i18n/as.json2
-rw-r--r--languages/i18n/ast.json2
-rw-r--r--languages/i18n/avk.json2
-rw-r--r--languages/i18n/awa.json2
-rw-r--r--languages/i18n/az.json2
-rw-r--r--languages/i18n/azb.json2
-rw-r--r--languages/i18n/ba.json2
-rw-r--r--languages/i18n/bar.json2
-rw-r--r--languages/i18n/bcc.json2
-rw-r--r--languages/i18n/bcl.json2
-rw-r--r--languages/i18n/be-tarask.json2
-rw-r--r--languages/i18n/be.json2
-rw-r--r--languages/i18n/bg.json2
-rw-r--r--languages/i18n/bgn.json2
-rw-r--r--languages/i18n/bjn.json2
-rw-r--r--languages/i18n/bn.json2
-rw-r--r--languages/i18n/br.json2
-rw-r--r--languages/i18n/bs.json2
-rw-r--r--languages/i18n/ca.json2
-rw-r--r--languages/i18n/ce.json2
-rw-r--r--languages/i18n/ckb.json2
-rw-r--r--languages/i18n/crh-cyrl.json2
-rw-r--r--languages/i18n/crh-latn.json2
-rw-r--r--languages/i18n/cs.json2
-rw-r--r--languages/i18n/cv.json2
-rw-r--r--languages/i18n/cy.json2
-rw-r--r--languages/i18n/da.json2
-rw-r--r--languages/i18n/de.json2
-rw-r--r--languages/i18n/diq.json2
-rw-r--r--languages/i18n/dsb.json2
-rw-r--r--languages/i18n/el.json2
-rw-r--r--languages/i18n/en.json2
-rw-r--r--languages/i18n/eo.json2
-rw-r--r--languages/i18n/es.json2
-rw-r--r--languages/i18n/et.json2
-rw-r--r--languages/i18n/eu.json2
-rw-r--r--languages/i18n/ext.json2
-rw-r--r--languages/i18n/fa.json2
-rw-r--r--languages/i18n/fi.json2
-rw-r--r--languages/i18n/fo.json2
-rw-r--r--languages/i18n/fr.json2
-rw-r--r--languages/i18n/frp.json2
-rw-r--r--languages/i18n/frr.json2
-rw-r--r--languages/i18n/fur.json2
-rw-r--r--languages/i18n/fy.json2
-rw-r--r--languages/i18n/ga.json2
-rw-r--r--languages/i18n/gan-hans.json2
-rw-r--r--languages/i18n/gan-hant.json2
-rw-r--r--languages/i18n/gd.json2
-rw-r--r--languages/i18n/gl.json2
-rw-r--r--languages/i18n/gn.json2
-rw-r--r--languages/i18n/grc.json2
-rw-r--r--languages/i18n/gsw.json2
-rw-r--r--languages/i18n/gu.json2
-rw-r--r--languages/i18n/hak.json2
-rw-r--r--languages/i18n/he.json2
-rw-r--r--languages/i18n/hi.json2
-rw-r--r--languages/i18n/hif-latn.json2
-rw-r--r--languages/i18n/hr.json2
-rw-r--r--languages/i18n/hrx.json2
-rw-r--r--languages/i18n/hsb.json2
-rw-r--r--languages/i18n/hu.json2
-rw-r--r--languages/i18n/hy.json2
-rw-r--r--languages/i18n/ia.json2
-rw-r--r--languages/i18n/id.json2
-rw-r--r--languages/i18n/ig.json2
-rw-r--r--languages/i18n/ilo.json2
-rw-r--r--languages/i18n/io.json2
-rw-r--r--languages/i18n/is.json2
-rw-r--r--languages/i18n/it.json2
-rw-r--r--languages/i18n/ja.json2
-rw-r--r--languages/i18n/jv.json2
-rw-r--r--languages/i18n/ka.json2
-rw-r--r--languages/i18n/kaa.json2
-rw-r--r--languages/i18n/kab.json2
-rw-r--r--languages/i18n/kiu.json2
-rw-r--r--languages/i18n/kk-arab.json2
-rw-r--r--languages/i18n/kk-cyrl.json2
-rw-r--r--languages/i18n/kk-latn.json2
-rw-r--r--languages/i18n/km.json2
-rw-r--r--languages/i18n/kn.json2
-rw-r--r--languages/i18n/ko.json2
-rw-r--r--languages/i18n/krc.json2
-rw-r--r--languages/i18n/ksh.json2
-rw-r--r--languages/i18n/ku-latn.json2
-rw-r--r--languages/i18n/la.json2
-rw-r--r--languages/i18n/lb.json2
-rw-r--r--languages/i18n/li.json2
-rw-r--r--languages/i18n/lmo.json2
-rw-r--r--languages/i18n/loz.json2
-rw-r--r--languages/i18n/lrc.json2
-rw-r--r--languages/i18n/lt.json2
-rw-r--r--languages/i18n/lus.json2
-rw-r--r--languages/i18n/lv.json2
-rw-r--r--languages/i18n/lzh.json2
-rw-r--r--languages/i18n/mai.json2
-rw-r--r--languages/i18n/map-bms.json2
-rw-r--r--languages/i18n/mdf.json2
-rw-r--r--languages/i18n/mg.json2
-rw-r--r--languages/i18n/mhr.json2
-rw-r--r--languages/i18n/min.json2
-rw-r--r--languages/i18n/mk.json2
-rw-r--r--languages/i18n/ml.json2
-rw-r--r--languages/i18n/mn.json2
-rw-r--r--languages/i18n/mr.json2
-rw-r--r--languages/i18n/ms.json2
-rw-r--r--languages/i18n/mt.json2
-rw-r--r--languages/i18n/myv.json2
-rw-r--r--languages/i18n/nap.json2
-rw-r--r--languages/i18n/nb.json2
-rw-r--r--languages/i18n/nds-nl.json2
-rw-r--r--languages/i18n/nds.json2
-rw-r--r--languages/i18n/ne.json2
-rw-r--r--languages/i18n/nl.json2
-rw-r--r--languages/i18n/nn.json2
-rw-r--r--languages/i18n/oc.json2
-rw-r--r--languages/i18n/or.json2
-rw-r--r--languages/i18n/os.json2
-rw-r--r--languages/i18n/pa.json2
-rw-r--r--languages/i18n/pam.json2
-rw-r--r--languages/i18n/pl.json2
-rw-r--r--languages/i18n/pms.json2
-rw-r--r--languages/i18n/pnb.json2
-rw-r--r--languages/i18n/prg.json2
-rw-r--r--languages/i18n/ps.json2
-rw-r--r--languages/i18n/pt-br.json2
-rw-r--r--languages/i18n/pt.json2
-rw-r--r--languages/i18n/qqq.json1
-rw-r--r--languages/i18n/qu.json2
-rw-r--r--languages/i18n/rm.json2
-rw-r--r--languages/i18n/ro.json2
-rw-r--r--languages/i18n/roa-tara.json2
-rw-r--r--languages/i18n/ru.json2
-rw-r--r--languages/i18n/rue.json2
-rw-r--r--languages/i18n/sa.json2
-rw-r--r--languages/i18n/sah.json2
-rw-r--r--languages/i18n/sc.json2
-rw-r--r--languages/i18n/scn.json2
-rw-r--r--languages/i18n/sco.json2
-rw-r--r--languages/i18n/sdc.json2
-rw-r--r--languages/i18n/se.json2
-rw-r--r--languages/i18n/sei.json2
-rw-r--r--languages/i18n/ses.json2
-rw-r--r--languages/i18n/sgs.json2
-rw-r--r--languages/i18n/sh.json2
-rw-r--r--languages/i18n/shi.json2
-rw-r--r--languages/i18n/si.json2
-rw-r--r--languages/i18n/sk.json2
-rw-r--r--languages/i18n/sl.json2
-rw-r--r--languages/i18n/sli.json2
-rw-r--r--languages/i18n/sma.json2
-rw-r--r--languages/i18n/sq.json2
-rw-r--r--languages/i18n/sr-ec.json2
-rw-r--r--languages/i18n/sr-el.json2
-rw-r--r--languages/i18n/srn.json2
-rw-r--r--languages/i18n/stq.json2
-rw-r--r--languages/i18n/su.json2
-rw-r--r--languages/i18n/sv.json2
-rw-r--r--languages/i18n/sw.json2
-rw-r--r--languages/i18n/szl.json2
-rw-r--r--languages/i18n/ta.json2
-rw-r--r--languages/i18n/te.json2
-rw-r--r--languages/i18n/tg-cyrl.json2
-rw-r--r--languages/i18n/tg-latn.json2
-rw-r--r--languages/i18n/th.json2
-rw-r--r--languages/i18n/tk.json2
-rw-r--r--languages/i18n/tl.json2
-rw-r--r--languages/i18n/tr.json2
-rw-r--r--languages/i18n/tyv.json2
-rw-r--r--languages/i18n/tzm.json2
-rw-r--r--languages/i18n/ug-arab.json2
-rw-r--r--languages/i18n/uk.json2
-rw-r--r--languages/i18n/vec.json2
-rw-r--r--languages/i18n/vep.json2
-rw-r--r--languages/i18n/vi.json2
-rw-r--r--languages/i18n/vo.json2
-rw-r--r--languages/i18n/vro.json2
-rw-r--r--languages/i18n/wa.json2
-rw-r--r--languages/i18n/war.json2
-rw-r--r--languages/i18n/wo.json2
-rw-r--r--languages/i18n/yi.json2
-rw-r--r--languages/i18n/yo.json2
-rw-r--r--languages/i18n/yue.json2
-rw-r--r--languages/i18n/zh-hans.json2
-rw-r--r--languages/i18n/zh-hant.json2
-rw-r--r--languages/i18n/zh-tw.json1
-rw-r--r--languages/messages/MessagesAce.php2
-rw-r--r--languages/messages/MessagesAf.php2
-rw-r--r--languages/messages/MessagesAln.php2
-rw-r--r--languages/messages/MessagesAn.php2
-rw-r--r--languages/messages/MessagesAr.php2
-rw-r--r--languages/messages/MessagesArc.php2
-rw-r--r--languages/messages/MessagesArz.php2
-rw-r--r--languages/messages/MessagesAs.php2
-rw-r--r--languages/messages/MessagesAv.php2
-rw-r--r--languages/messages/MessagesAvk.php2
-rw-r--r--languages/messages/MessagesBa.php2
-rw-r--r--languages/messages/MessagesBcc.php2
-rw-r--r--languages/messages/MessagesBe_tarask.php2
-rw-r--r--languages/messages/MessagesBg.php2
-rw-r--r--languages/messages/MessagesBjn.php2
-rw-r--r--languages/messages/MessagesBr.php2
-rw-r--r--languages/messages/MessagesBs.php2
-rw-r--r--languages/messages/MessagesBxr.php2
-rw-r--r--languages/messages/MessagesCa.php2
-rw-r--r--languages/messages/MessagesCdo.php2
-rw-r--r--languages/messages/MessagesCe.php2
-rw-r--r--languages/messages/MessagesCkb.php2
-rw-r--r--languages/messages/MessagesCs.php2
-rw-r--r--languages/messages/MessagesDa.php2
-rw-r--r--languages/messages/MessagesDe.php2
-rw-r--r--languages/messages/MessagesDiq.php2
-rw-r--r--languages/messages/MessagesDsb.php2
-rw-r--r--languages/messages/MessagesEl.php2
-rw-r--r--languages/messages/MessagesEn.php1
-rw-r--r--languages/messages/MessagesEo.php2
-rw-r--r--languages/messages/MessagesEs.php2
-rw-r--r--languages/messages/MessagesEt.php2
-rw-r--r--languages/messages/MessagesFa.php2
-rw-r--r--languages/messages/MessagesFi.php2
-rw-r--r--languages/messages/MessagesFr.php2
-rw-r--r--languages/messages/MessagesFrp.php2
-rw-r--r--languages/messages/MessagesFur.php2
-rw-r--r--languages/messages/MessagesFy.php2
-rw-r--r--languages/messages/MessagesGag.php2
-rw-r--r--languages/messages/MessagesGl.php2
-rw-r--r--languages/messages/MessagesGsw.php2
-rw-r--r--languages/messages/MessagesGu.php2
-rw-r--r--languages/messages/MessagesHe.php2
-rw-r--r--languages/messages/MessagesHr.php2
-rw-r--r--languages/messages/MessagesHsb.php2
-rw-r--r--languages/messages/MessagesHt.php2
-rw-r--r--languages/messages/MessagesHu.php2
-rw-r--r--languages/messages/MessagesHy.php2
-rw-r--r--languages/messages/MessagesIa.php2
-rw-r--r--languages/messages/MessagesId.php2
-rw-r--r--languages/messages/MessagesIe.php2
-rw-r--r--languages/messages/MessagesIs.php2
-rw-r--r--languages/messages/MessagesIt.php2
-rw-r--r--languages/messages/MessagesJa.php2
-rw-r--r--languages/messages/MessagesKa.php2
-rw-r--r--languages/messages/MessagesKaa.php2
-rw-r--r--languages/messages/MessagesKk_arab.php2
-rw-r--r--languages/messages/MessagesKk_cyrl.php2
-rw-r--r--languages/messages/MessagesKk_latn.php2
-rw-r--r--languages/messages/MessagesKm.php2
-rw-r--r--languages/messages/MessagesKo.php2
-rw-r--r--languages/messages/MessagesKrc.php2
-rw-r--r--languages/messages/MessagesKsh.php2
-rw-r--r--languages/messages/MessagesKw.php2
-rw-r--r--languages/messages/MessagesLa.php2
-rw-r--r--languages/messages/MessagesLad.php2
-rw-r--r--languages/messages/MessagesLb.php2
-rw-r--r--languages/messages/MessagesLi.php2
-rw-r--r--languages/messages/MessagesLij.php2
-rw-r--r--languages/messages/MessagesLrc.php2
-rw-r--r--languages/messages/MessagesLt.php2
-rw-r--r--languages/messages/MessagesMdf.php2
-rw-r--r--languages/messages/MessagesMg.php2
-rw-r--r--languages/messages/MessagesMin.php2
-rw-r--r--languages/messages/MessagesMk.php2
-rw-r--r--languages/messages/MessagesMl.php2
-rw-r--r--languages/messages/MessagesMr.php2
-rw-r--r--languages/messages/MessagesMs.php2
-rw-r--r--languages/messages/MessagesMt.php2
-rw-r--r--languages/messages/MessagesMyv.php2
-rw-r--r--languages/messages/MessagesNb.php2
-rw-r--r--languages/messages/MessagesNds.php2
-rw-r--r--languages/messages/MessagesNds_nl.php2
-rw-r--r--languages/messages/MessagesNl.php2
-rw-r--r--languages/messages/MessagesNn.php2
-rw-r--r--languages/messages/MessagesOc.php2
-rw-r--r--languages/messages/MessagesOr.php2
-rw-r--r--languages/messages/MessagesOs.php2
-rw-r--r--languages/messages/MessagesPa.php2
-rw-r--r--languages/messages/MessagesPl.php2
-rw-r--r--languages/messages/MessagesPs.php2
-rw-r--r--languages/messages/MessagesPt.php2
-rw-r--r--languages/messages/MessagesPt_br.php2
-rw-r--r--languages/messages/MessagesQu.php2
-rw-r--r--languages/messages/MessagesRo.php2
-rw-r--r--languages/messages/MessagesRu.php2
-rw-r--r--languages/messages/MessagesRue.php2
-rw-r--r--languages/messages/MessagesSa.php2
-rw-r--r--languages/messages/MessagesScn.php2
-rw-r--r--languages/messages/MessagesSd.php2
-rw-r--r--languages/messages/MessagesSdc.php2
-rw-r--r--languages/messages/MessagesSe.php2
-rw-r--r--languages/messages/MessagesSh.php2
-rw-r--r--languages/messages/MessagesSi.php2
-rw-r--r--languages/messages/MessagesSk.php2
-rw-r--r--languages/messages/MessagesSl.php2
-rw-r--r--languages/messages/MessagesSq.php2
-rw-r--r--languages/messages/MessagesSr_ec.php2
-rw-r--r--languages/messages/MessagesSu.php2
-rw-r--r--languages/messages/MessagesSv.php2
-rw-r--r--languages/messages/MessagesSw.php2
-rw-r--r--languages/messages/MessagesTe.php2
-rw-r--r--languages/messages/MessagesTh.php2
-rw-r--r--languages/messages/MessagesTl.php2
-rw-r--r--languages/messages/MessagesTr.php2
-rw-r--r--languages/messages/MessagesTt_cyrl.php2
-rw-r--r--languages/messages/MessagesUk.php2
-rw-r--r--languages/messages/MessagesUr.php2
-rw-r--r--languages/messages/MessagesVec.php2
-rw-r--r--languages/messages/MessagesVi.php2
-rw-r--r--languages/messages/MessagesYi.php2
-rw-r--r--languages/messages/MessagesYue.php2
-rw-r--r--languages/messages/MessagesZh.php2
-rw-r--r--languages/messages/MessagesZh_hans.php1
-rw-r--r--languages/messages/MessagesZh_hant.php1
-rw-r--r--maintenance/Maintenance.php2
-rw-r--r--maintenance/dictionary/mediawiki.dic1
-rw-r--r--resources/Resources.php2
-rw-r--r--resources/assets/file-type-icons/fileicon-djvu.xcfbin0 -> 83394 bytes
-rw-r--r--resources/assets/file-type-icons/fileicon-ogg.xcfbin0 -> 40236 bytes
-rw-r--r--tests/parser/preprocess/All_system_messages.expected14
-rw-r--r--tests/parser/preprocess/All_system_messages.txt14
-rw-r--r--tests/phpunit/data/media/80x60-2layers.xcfbin0 -> 1162 bytes
-rw-r--r--tests/phpunit/data/media/80x60-Greyscale.xcfbin0 -> 667 bytes
-rw-r--r--tests/phpunit/data/media/80x60-RGB.xcfbin0 -> 677 bytes
-rw-r--r--tests/phpunit/includes/registration/ExtensionRegistryTest.php14
-rw-r--r--thumb.php26
-rw-r--r--vendor/README.md28
-rw-r--r--vendor/autoload.php2
-rw-r--r--vendor/composer.json25
-rw-r--r--vendor/composer.lock (renamed from composer.lock)140
-rw-r--r--vendor/composer/ClassLoader.php8
-rw-r--r--vendor/composer/autoload_classmap.php260
-rw-r--r--vendor/composer/autoload_namespaces.php5
-rw-r--r--vendor/composer/autoload_psr4.php3
-rw-r--r--vendor/composer/autoload_real.php9
-rw-r--r--vendor/composer/installed.json381
-rw-r--r--vendor/monolog/monolog/CHANGELOG.mdown202
-rw-r--r--vendor/monolog/monolog/LICENSE19
-rw-r--r--vendor/monolog/monolog/README.mdown283
-rw-r--r--vendor/monolog/monolog/composer.json50
-rw-r--r--vendor/monolog/monolog/doc/extending.md76
-rw-r--r--vendor/monolog/monolog/doc/sockets.md37
-rw-r--r--vendor/monolog/monolog/doc/usage.md162
-rw-r--r--vendor/monolog/monolog/phpunit.xml.dist15
-rw-r--r--vendor/monolog/monolog/src/Monolog/ErrorHandler.php208
-rw-r--r--vendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php79
-rw-r--r--vendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php87
-rw-r--r--vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php104
-rw-r--r--vendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php36
-rw-r--r--vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php101
-rw-r--r--vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php140
-rw-r--r--vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php116
-rw-r--r--vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php159
-rw-r--r--vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php47
-rw-r--r--vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php165
-rw-r--r--vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php105
-rw-r--r--vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php141
-rw-r--r--vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php48
-rw-r--r--vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php113
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php184
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php66
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php92
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php98
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php184
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php117
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php204
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php72
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php145
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php45
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php89
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php128
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php82
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php140
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php28
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php59
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php34
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php150
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php195
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php126
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php103
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php72
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php80
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php90
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php300
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php55
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php98
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php55
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php69
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php21
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php55
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php155
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php174
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php45
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php56
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php172
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php181
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php58
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php73
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php153
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php83
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php234
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php284
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php104
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php56
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php67
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php46
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php80
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php140
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php57
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php95
-rw-r--r--vendor/monolog/monolog/src/Monolog/Logger.php615
-rw-r--r--vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php64
-rw-r--r--vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php82
-rw-r--r--vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php40
-rw-r--r--vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php63
-rw-r--r--vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php40
-rw-r--r--vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php31
-rw-r--r--vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php48
-rw-r--r--vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php34
-rw-r--r--vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php38
-rw-r--r--vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php105
-rw-r--r--vendor/monolog/monolog/src/Monolog/Registry.php118
-rw-r--r--vendor/monolog/monolog/tests/Monolog/ErrorHandlerTest.php31
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Formatter/ChromePHPFormatterTest.php158
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Formatter/ElasticaFormatterTest.php79
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Formatter/FlowdockFormatterTest.php55
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Formatter/GelfMessageFormatterTest.php189
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Formatter/JsonFormatterTest.php78
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Formatter/LineFormatterTest.php208
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Formatter/LogglyFormatterTest.php40
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Formatter/LogstashFormatterTest.php289
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Formatter/MongoDBFormatterTest.php253
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Formatter/NormalizerFormatterTest.php247
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Formatter/ScalarFormatterTest.php98
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Formatter/WildfireFormatterTest.php142
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Functional/Handler/FirePHPHandlerTest.php32
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/AbstractHandlerTest.php115
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/AbstractProcessingHandlerTest.php80
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/AmqpHandlerTest.php137
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/BrowserConsoleHandlerTest.php130
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/BufferHandlerTest.php158
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/ChromePHPHandlerTest.php141
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/CouchDBHandlerTest.php41
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/DoctrineCouchDBHandlerTest.php52
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/DynamoDbHandlerTest.php73
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/ElasticSearchHandlerTest.php239
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/ErrorLogHandlerTest.php66
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/FilterHandlerTest.php170
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/FingersCrossedHandlerTest.php240
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/FirePHPHandlerTest.php96
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/FleepHookHandlerTest.php85
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/FlowdockHandlerTest.php88
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/GelfHandlerLegacyTest.php93
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/GelfHandlerTest.php117
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/GroupHandlerTest.php89
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/HipChatHandlerTest.php166
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/LogEntriesHandlerTest.php84
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/MailHandlerTest.php75
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/MockRavenClient.php26
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/MongoDBHandlerTest.php65
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/NativeMailerHandlerTest.php61
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/NewRelicHandlerTest.php192
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/NullHandlerTest.php33
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/PsrHandlerTest.php50
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/PushoverHandlerTest.php141
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/RavenHandlerTest.php150
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/RedisHandlerTest.php71
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/RotatingFileHandlerTest.php99
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/SamplingHandlerTest.php33
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/SlackHandlerTest.php133
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/SocketHandlerTest.php282
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/StreamHandlerTest.php118
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/SyslogHandlerTest.php44
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/SyslogUdpHandlerTest.php49
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/TestHandlerTest.php56
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/UdpSocketTest.php46
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/WhatFailureGroupHandlerTest.php121
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Handler/ZendMonitorHandlerTest.php69
-rw-r--r--vendor/monolog/monolog/tests/Monolog/LoggerTest.php409
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Processor/GitProcessorTest.php29
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Processor/IntrospectionProcessorTest.php123
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Processor/MemoryPeakUsageProcessorTest.php42
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Processor/MemoryUsageProcessorTest.php42
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Processor/ProcessIdProcessorTest.php30
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Processor/PsrLogMessageProcessorTest.php43
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Processor/TagProcessorTest.php29
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Processor/UidProcessorTest.php27
-rw-r--r--vendor/monolog/monolog/tests/Monolog/Processor/WebProcessorTest.php98
-rw-r--r--vendor/monolog/monolog/tests/Monolog/PsrLogCompatTest.php47
-rw-r--r--vendor/monolog/monolog/tests/Monolog/TestCase.php58
-rw-r--r--vendor/monolog/monolog/tests/bootstrap.php15
-rw-r--r--vendor/oojs/oojs-ui/.mailmap18
-rw-r--r--vendor/psr/log/Psr/Log/LoggerAwareTrait.php22
-rw-r--r--vendor/psr/log/Psr/Log/LoggerTrait.php131
-rw-r--r--vendor/ruflin/elastica/LICENSE.txt21
-rw-r--r--vendor/ruflin/elastica/README.markdown29
-rw-r--r--vendor/ruflin/elastica/Vagrantfile14
-rw-r--r--vendor/ruflin/elastica/build.xml232
-rw-r--r--vendor/ruflin/elastica/changes.txt797
-rw-r--r--vendor/ruflin/elastica/composer.json40
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/AbstractUpdateAction.php544
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/AbstractAggregation.php88
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/AbstractSimpleAggregation.php33
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/Avg.php14
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/Cardinality.php14
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/DateHistogram.php82
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/DateRange.php21
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/ExtendedStats.php13
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/Filter.php41
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/GeoDistance.php90
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/GeohashGrid.php61
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/GlobalAggregation.php13
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/Histogram.php55
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/IpRange.php66
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/Max.php13
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/Min.php13
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/Missing.php31
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/Nested.php31
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/Range.php45
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/ReverseNested.php50
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/Stats.php13
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/Sum.php13
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/Terms.php97
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Aggregation/ValueCount.php31
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Bulk.php423
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Bulk/Action.php219
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Bulk/Action/AbstractDocument.php162
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Bulk/Action/CreateDocument.php11
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Bulk/Action/DeleteDocument.php33
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Bulk/Action/IndexDocument.php52
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Bulk/Action/UpdateDocument.php69
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Bulk/Response.php47
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Bulk/ResponseSet.php142
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Client.php691
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Cluster.php181
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Cluster/Health.php189
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Cluster/Health/Index.php142
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Cluster/Health/Shard.php107
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Cluster/Settings.php197
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Connection.php274
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Document.php334
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Exception/Bulk/Response/ActionException.php66
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Exception/Bulk/ResponseException.php103
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Exception/Bulk/UdpException.php9
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Exception/BulkException.php7
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Exception/ClientException.php14
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Exception/Connection/GuzzleException.php51
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Exception/Connection/HttpException.php88
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Exception/Connection/ThriftException.php51
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Exception/ConnectionException.php65
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Exception/ElasticsearchException.php99
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Exception/ExceptionInterface.php14
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Exception/InvalidException.php14
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Exception/JSONParseException.php12
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Exception/NotFoundException.php14
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Exception/NotImplementedException.php16
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Exception/PartialShardFailureException.php33
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Exception/ResponseException.php76
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Exception/RuntimeException.php14
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Facet/AbstractFacet.php141
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Facet/DateHistogram.php44
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Facet/Filter.php27
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Facet/GeoCluster.php54
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Facet/GeoDistance.php66
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Facet/Histogram.php90
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Facet/Query.php27
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Facet/Range.php138
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Facet/Statistical.php61
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Facet/Terms.php129
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Facet/TermsStats.php103
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/AbstractFilter.php57
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/AbstractGeoDistance.php190
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/AbstractGeoShape.php50
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/AbstractMulti.php77
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/Bool.php146
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/BoolAnd.php22
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/BoolNot.php43
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/BoolOr.php22
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/Exists.php35
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/GeoBoundingBox.php49
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/GeoDistance.php73
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/GeoDistanceRange.php101
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/GeoPolygon.php59
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/GeoShapePreIndexed.php85
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/GeoShapeProvided.php74
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/GeohashCell.php45
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/HasChild.php78
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/HasParent.php77
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/Ids.php92
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/Indices.php51
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/Limit.php36
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/MatchAll.php22
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/Missing.php37
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/Nested.php60
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/NumericRange.php15
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/Prefix.php79
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/Query.php90
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/Range.php61
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/Regexp.php80
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/Script.php49
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/Term.php47
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/Terms.php132
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Filter/Type.php60
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Index.php462
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Index/Settings.php318
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Index/Stats.php109
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Index/Status.php144
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/JSON.php67
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Log.php84
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Multi/ResultSet.php208
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Multi/Search.php198
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Node.php130
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Node/Info.php196
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Node/Stats.php115
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Param.php162
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Percolator.php132
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query.php420
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/AbstractQuery.php15
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/Bool.php92
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/Boosting.php44
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/Builder.php933
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/Common.php150
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/ConstantScore.php68
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/DisMax.php59
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/Filtered.php95
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/FunctionScore.php201
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/Fuzzy.php84
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/FuzzyLikeThis.php215
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/HasChild.php63
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/HasParent.php62
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/Ids.php117
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/Match.php198
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/MatchAll.php22
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/MoreLikeThis.php162
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/MultiMatch.php180
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/Nested.php47
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/Prefix.php48
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/QueryString.php267
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/Range.php39
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/Simple.php55
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/SimpleQueryString.php65
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/Term.php49
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/Terms.php103
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/TopChildren.php52
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Query/Wildcard.php41
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Request.php200
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Rescore/AbstractRescore.php36
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Rescore/Query.php90
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Response.php299
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Result.php216
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/ResultSet.php383
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/ScanAndScroll.php150
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Script.php148
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/ScriptFields.php63
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Search.php514
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/SearchableInterface.php52
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Snapshot.php155
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Status.php179
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Suggest.php62
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Suggest/AbstractSuggest.php92
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Suggest/CandidateGenerator/AbstractCandidateGenerator.php11
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Suggest/CandidateGenerator/DirectGenerator.php127
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Suggest/Phrase.php148
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Suggest/Term.php115
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Transport/AbstractTransport.php109
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Transport/Guzzle.php179
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Transport/Http.php188
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Transport/Https.php30
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Transport/Memcache.php82
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Transport/Null.php44
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Transport/Thrift.php173
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Type.php537
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Type/AbstractType.php200
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Type/Mapping.php280
-rw-r--r--vendor/ruflin/elastica/lib/Elastica/Util.php171
-rw-r--r--vendor/ruflin/elastica/phpdoc.dist.xml13
-rw-r--r--vendor/ruflin/elastica/test/benchmark/BulkMemoryUsageTest.php46
-rw-r--r--vendor/ruflin/elastica/test/benchmark/ClientTest.php31
-rw-r--r--vendor/ruflin/elastica/test/benchmark/TransportTest.php252
-rw-r--r--vendor/ruflin/elastica/test/benchmark/phpunit.benchmark.xml10
-rw-r--r--vendor/ruflin/elastica/test/benchmark/phpunit.xhprof.xml39
-rw-r--r--vendor/ruflin/elastica/test/bin/install_php_memcache.sh8
-rw-r--r--vendor/ruflin/elastica/test/bin/run_elasticsearch.sh56
-rw-r--r--vendor/ruflin/elastica/test/bin/run_proxy.sh15
-rw-r--r--vendor/ruflin/elastica/test/bin/show_logs.sh3
-rw-r--r--vendor/ruflin/elastica/test/bootstrap.php5
-rw-r--r--vendor/ruflin/elastica/test/data/test.docbin0 -> 22016 bytes
-rw-r--r--vendor/ruflin/elastica/test/data/test.docxbin0 -> 25890 bytes
-rw-r--r--vendor/ruflin/elastica/test/data/test.pdfbin0 -> 16107 bytes
-rw-r--r--vendor/ruflin/elastica/test/data/test.txt1
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/AvgTest.php38
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/BaseAggregationTest.php28
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/CardinalityTest.php38
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/DateHistogramTest.php43
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/DateRangeTest.php51
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/ExtendedStatsTest.php43
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/FilterTest.php78
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/GeoDistanceTest.php45
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/GeohashGridTest.php45
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/GlobalAggregationTest.php27
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/HistogramTest.php45
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/IpRangeTest.php56
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/MaxTest.php72
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/MinTest.php38
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/MissingTest.php37
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/NestedTest.php62
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/RangeTest.php41
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/ReverseNestedTest.php124
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/StatsTest.php42
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/SumTest.php38
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/TermsTest.php39
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Aggregation/ValueCountTest.php38
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Base.php31
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Bulk/ActionTest.php69
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Bulk/ResponseSetTest.php188
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/BulkTest.php711
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/ClientTest.php1008
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Cluster/Health/IndexTest.php113
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Cluster/Health/ShardTest.php63
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Cluster/HealthTest.php113
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Cluster/SettingsTest.php110
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/ClusterTest.php89
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/ConnectionTest.php103
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/DocumentTest.php309
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/ExampleTest.php58
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Exception/NotImplementedTest.php23
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Exception/PartialShardFailureExceptionTest.php55
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Exception/ResponseExceptionTest.php60
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/DateHistogramTest.php59
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/FilterTest.php40
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/GeoClusterTest.php49
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/QueryTest.php40
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/StatisticalTest.php82
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/TermsStatsTest.php105
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Facet/TermsTest.php69
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/AbstractTest.php69
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/BoolAndTest.php65
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/BoolNotTest.php25
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/BoolOrTest.php42
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/BoolTest.php107
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/ExistsTests.php31
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoDistanceRangeTest.php218
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoDistanceTest.php129
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoPolygonTest.php65
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoShapePreIndexedTest.php90
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeoShapeProvidedTest.php88
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/GeohashCellTest.php60
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/HasChildTest.php166
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/HasParentTest.php139
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/IdsTest.php201
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/IndicesTest.php93
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/MatchAllTest.php18
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/MultiTest.php95
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/NestedFilterWithSetFilterTest.php121
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/NestedTest.php121
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/NumericRangeTest.php32
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/PrefixTest.php149
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/QueryTest.php46
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/RangeTest.php32
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/RegexpTest.php137
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/ScriptTest.php52
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/TermTest.php23
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/TermsTest.php54
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Filter/TypeTest.php27
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Index/SettingsTest.php300
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Index/StatsTest.php23
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Index/StatusTest.php66
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/IndexTest.php696
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/LogTest.php153
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Multi/SearchTest.php549
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Node/InfoTest.php42
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/NodeTest.php84
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/ParamTest.php97
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/PercolatorTest.php224
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/BoolTest.php114
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/BoostingTest.php99
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/BuilderTest.php270
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/CommonTest.php59
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/ConstantScoreTest.php158
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/DisMaxTest.php83
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/FilteredTest.php112
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/FunctionScoreTest.php210
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/FuzzyLikeThisTest.php228
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/FuzzyTest.php129
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/HasChildTest.php107
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/HasParentTest.php50
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/HighlightTest.php49
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/IdsTest.php165
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/MatchAllTest.php44
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/MatchTest.php187
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/MoreLikeThisTest.php176
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/MultiMatchTest.php187
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/NestedTest.php28
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/PostFilterTest.php83
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/PrefixTest.php26
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/QueryStringTest.php126
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/RangeTest.php73
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/RescoreTest.php165
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/SimpleQueryStringTest.php73
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/SimpleTest.php17
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/TermTest.php26
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/TermsTest.php62
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Query/WildcardTest.php101
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/QueryTest.php194
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/RequestTest.php87
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/ResponseTest.php94
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/ResultSetTest.php93
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/ResultTest.php121
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/ScanAndScrollTest.php115
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/ScriptFieldsTest.php95
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/ScriptTest.php129
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/SearchTest.php500
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/SnapshotTest.php112
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/StatusTest.php116
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Suggest/PhraseTest.php85
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Suggest/TermTest.php104
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/AbstractTransportTest.php77
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/GuzzleTest.php163
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/HttpTest.php227
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/MemcacheTest.php51
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/NullTest.php59
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Transport/ThriftTest.php132
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/Type/MappingTest.php304
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/TypeTest.php823
-rw-r--r--vendor/ruflin/elastica/test/lib/Elastica/Test/UtilTest.php77
-rw-r--r--vendor/ruflin/elastica/test/nginx/nginx.conf24
-rw-r--r--vendor/ruflin/elastica/test/phpunit.xml.dist32
-rw-r--r--vendor/zordius/lightncandy/build/gen_doc6
-rw-r--r--vendor/zordius/lightncandy/build/gen_test.php64
-rw-r--r--vendor/zordius/lightncandy/build/push_ghpage12
-rw-r--r--vendor/zordius/lightncandy/build/runphp2
-rw-r--r--vendor/zordius/lightncandy/build/travis_push60
864 files changed, 55633 insertions, 3667 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/ArchInterWiki.sql b/extensions/ArchInterWiki.sql
index ea3a7391..64507150 100644
--- a/extensions/ArchInterWiki.sql
+++ b/extensions/ArchInterWiki.sql
@@ -48,7 +48,7 @@ VALUES
('hu', 'https://wiki.archlinux.org/index.php/$1_(Magyar)', 1, 0),
('id', 'https://wiki.archlinux.org/index.php/$1_(Indonesia)', 1, 0),
('it', 'https://wiki.archlinux.org/index.php/$1_(Italiano)', 1, 0),
- ('ja', 'https://archlinuxjp.kusakata.com/wiki/$1', 1, 0),
+ ('ja', 'https://wiki.archlinuxjp.org/index.php/$1', 1, 0),
('ko', 'https://wiki.archlinux.org/index.php/$1_(%ED%95%9C%EA%B5%AD%EC%96%B4)', 1, 0),
('lt', 'https://wiki.archlinux.org/index.php/$1_(Lietuvi%C5%A1kai)', 1, 0),
('nl', 'https://wiki.archlinux.org/index.php/$1_(Nederlands)', 1, 0),
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> &copy; 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 &quot;submit&quot; 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\" />&nbsp;$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 &nbsp;
- // 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 &nbsp
- // 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 &copy; 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 &copy; 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 (&amp;) 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 '&lt;PIPE&gt;' 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 '&lt;PIPE&gt;' 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 &copy; 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 &copy; 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' => "&quot;",
- '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 &copy; 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&nbsp;$1&nbsp;→&nbsp;{{PLURAL:$2|eine Sigg|$2&nbsp;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
new file mode 100644
index 00000000..8043dcdb
--- /dev/null
+++ b/resources/assets/file-type-icons/fileicon-djvu.xcf
Binary files differ
diff --git a/resources/assets/file-type-icons/fileicon-ogg.xcf b/resources/assets/file-type-icons/fileicon-ogg.xcf
new file mode 100644
index 00000000..a91024bf
--- /dev/null
+++ b/resources/assets/file-type-icons/fileicon-ogg.xcf
Binary files differ
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
&lt;/td&gt;&lt;td&gt;
<template lineStart="1"><title>int:Nstab-wp</title></template>
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
-[http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Nviews&amp;action=edit nviews]&lt;br&gt;
-[[MediaWiki_talk:Nviews|Talk]]
-&lt;/td&gt;&lt;td&gt;
-$1 views
-&lt;/td&gt;&lt;td&gt;
-<template lineStart="1"><title>int:Nviews</title></template>
-&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
[http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Ok&amp;action=edit ok]&lt;br&gt;
[[MediaWiki_talk:Ok|Talk]]
&lt;/td&gt;&lt;td&gt;
@@ -3319,13 +3312,6 @@ Personal tools
&lt;/td&gt;&lt;td&gt;
<template lineStart="1"><title>int:Personaltools</title></template>
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
-[http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Popularpages&amp;action=edit popularpages]&lt;br&gt;
-[[MediaWiki_talk:Popularpages|Talk]]
-&lt;/td&gt;&lt;td&gt;
-Popular pages
-&lt;/td&gt;&lt;td&gt;
-<template lineStart="1"><title>int:Popularpages</title></template>
-&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
[http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Portal&amp;action=edit portal]&lt;br&gt;
[[MediaWiki_talk:Portal|Talk]]
&lt;/td&gt;&lt;td&gt;
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
new file mode 100644
index 00000000..c51e980c
--- /dev/null
+++ b/tests/phpunit/data/media/80x60-2layers.xcf
Binary files differ
diff --git a/tests/phpunit/data/media/80x60-Greyscale.xcf b/tests/phpunit/data/media/80x60-Greyscale.xcf
new file mode 100644
index 00000000..84bf3e67
--- /dev/null
+++ b/tests/phpunit/data/media/80x60-Greyscale.xcf
Binary files differ
diff --git a/tests/phpunit/data/media/80x60-RGB.xcf b/tests/phpunit/data/media/80x60-RGB.xcf
new file mode 100644
index 00000000..1d58f16d
--- /dev/null
+++ b/tests/phpunit/data/media/80x60-RGB.xcf
Binary files differ
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,
+ ),
+ ),
);
}
}
diff --git a/thumb.php b/thumb.php
index 2ea3f076..34e27ee9 100644
--- a/thumb.php
+++ b/thumb.php
@@ -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&notify=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&timestamp=\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&timestamp=\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&timestamp=\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&timestamp=\d{10}&priority=2&retry=30&expire=25200POST/', $content);
+ $this->assertRegexp('/token=myToken&user=userB&message=test1&title=Monolog&timestamp=\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
new file mode 100644
index 00000000..d90d83c1
--- /dev/null
+++ b/vendor/ruflin/elastica/test/data/test.doc
Binary files differ
diff --git a/vendor/ruflin/elastica/test/data/test.docx b/vendor/ruflin/elastica/test/data/test.docx
new file mode 100644
index 00000000..924c1066
--- /dev/null
+++ b/vendor/ruflin/elastica/test/data/test.docx
Binary files differ
diff --git a/vendor/ruflin/elastica/test/data/test.pdf b/vendor/ruflin/elastica/test/data/test.pdf
new file mode 100644
index 00000000..e94c3f67
--- /dev/null
+++ b/vendor/ruflin/elastica/test/data/test.pdf
Binary files differ
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